- [+] auto swap places with peaceful lfs only if they are a lot smaller

- [+] prevent autoswap if there is somethign dangerous to the other lf
      in your cell
- [+] sometime give monsters random loot (if they dont have f_nopack)
- [+] stop sprinting and spellcasting if you slip. 
- [+] impement "C"ommunicate command
    - [+] ' with who'?
    * [+] list of options:
- [+] can throw items TO allies
- [+] improvements to getbestweapon()
* [+] give xp for using can of insecticide
- [+] fix monser spell casting
- [+] in describeob, include BONUS for armour
This commit is contained in:
Rob Pearce 2011-03-25 01:23:15 +00:00
parent 290d91677e
commit e9f752dd2f
16 changed files with 849 additions and 226 deletions

91
ai.c
View File

@ -19,6 +19,45 @@ extern enum ERROR reason;
int wantdb = B_TRUE;
void aiattack(lifeform_t *lf, lifeform_t *victim, int timelimit) {
int db = B_FALSE;
if (lfhasflag(lf, F_DEBUG)) {
db = B_TRUE;
}
if (db) {
char lfname[BUFLEN],vicname[BUFLEN];
getlfname(lf, lfname);
getlfname(victim, vicname);
dblog(".oO { %s settings new target: %s }", lfname, vicname);
}
killflagsofid(lf->flags, F_TARGET);
killflagsofid(lf->flags, F_TARGETCELL);
if ((timelimit == PERMENANT) || (timelimit == UNLIMITED)) {
addflag(lf->flags, F_TARGET, victim->id, victim->cell->x, victim->cell->y, NULL);
} else {
addtempflag(lf->flags, F_TARGET, victim->id , victim->cell->x , victim->cell->y, NULL,timelimit);
}
// tell the player
if (cansee(player, lf)) {
makenoise(lf, N_GETANGRY);
}
// change allegience ?
if (!areenemies(lf, victim)) {
if (getallegiance(victim) == AL_FRIENDLY) {
if (!hasflag(lf->flags, F_HOSTILE)) {
addflag(lf->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
}
}
}
}
enum OBTYPE aigetattackspell(lifeform_t *lf, lifeform_t *victim) {
flag_t *f;
@ -199,6 +238,30 @@ object_t *aigetwand(lifeform_t *lf, enum FLAG purpose) {
return NULL;
}
void aigoto(lifeform_t *lf, cell_t *c, int timelimit) {
int db = B_FALSE;
if (lfhasflag(lf, F_DEBUG)) {
db = B_TRUE;
}
if (db) {
char lfname[BUFLEN];
getlfname(lf, lfname);
dblog(".oO { %s going to targecell: %d, %d }", lfname, c->x, c->y);
}
killflagsofid(lf->flags, F_TARGET);
killflagsofid(lf->flags, F_TARGETCELL);
if ((timelimit == PERMENANT) || (timelimit == UNLIMITED)) {
addflag(lf->flags, F_TARGETCELL, c->x, c->y, NA, NULL);
} else {
addtempflag(lf->flags, F_TARGETCELL, c->x, c->y, NA, NULL,timelimit);
}
}
void aimove(lifeform_t *lf) {
int db = B_FALSE;
object_t *curwep,*bestwep, *o;
@ -231,7 +294,7 @@ void aimove(lifeform_t *lf) {
if (db) {
char lfname[BUFLEN];
getlfname(lf, lfname);
real_getlfname(lf, lfname, B_FALSE);
dblog("AIMOVE: %s", lfname);
}
@ -408,7 +471,7 @@ void aimove(lifeform_t *lf) {
}
}
if (spellfailed) {
if (db) dblog(".oO { cast spell/ability tried but failed (2)! }");
if (db) dblog(".oO { cast spell/ability tried but failed (2)! reason = %d }", reason);
} else {
// spell succesful
return;
@ -503,13 +566,17 @@ void aimove(lifeform_t *lf) {
}
}
} else {
cell_t *targcell;
if (db) dblog(".oO { i cannot see my target. moving to last known loc %d/%d }",lastx,lasty);
// can't see target.
// move towards their last known location instead
addflag(lf->flags, F_TARGETCELL, lastx, lasty, NA, NULL);
// remove f_target
killflag(f);
targcell = getcellat(lf->cell->map, lastx, lasty);
if (targcell) {
aigoto(lf, targcell, PERMENANT);
} else {
if (db) dblog(".oO { go to target's last known loc failed! }");
}
/*
// just try to move in a random direction
@ -540,7 +607,7 @@ void aimove(lifeform_t *lf) {
// remember NOT to target this one.
lf->ignorecell = c;
} else {
if (db) dblog(".oO { successfully walked towards f_targetcell. }");
if (db) dblog(".oO { successfully walked towards f_targetcell. arrived at %d,%d }",lf->cell->x, lf->cell->y);
// moved towards it.
// reset lifetime
f->lifetime = AI_FOLLOWTIME;
@ -586,12 +653,8 @@ void aimove(lifeform_t *lf) {
if (c->lf && cansee(lf, c->lf)) {
if (isplayer(c->lf)) { // TODO: change to if isenemy ?
if (db) dblog(".oO { found a target - lfid %d (%s) ! }",c->lf->id, c->lf->race->name);
// target them!
addtempflag(lf->flags, F_TARGET, c->lf->id, c->x, c->y, NULL, AI_FOLLOWTIME);
// tell the player
if (cansee(player, lf)) {
makenoise(lf, N_GETANGRY);
}
aiattack(lf, c->lf, AI_FOLLOWTIME);
// then move towards them...
if (db) dblog(".oO { moving towards my new target }");
@ -1064,9 +1127,7 @@ int lookforobs(lifeform_t *lf, int covetsonly) {
if (gothere) {
// start walking towards target cell
addtempflag(lf->flags, F_TARGETCELL, c->x, c->y, NA, NULL, AI_FOLLOWTIME);
// forget about people we are attacking
killflagsofid(lf->flags, F_TARGET);
aigoto(lf, c, AI_FOLLOWTIME);
return B_TRUE;
}
}

2
ai.h
View File

@ -1,9 +1,11 @@
#include "defs.h"
void aiattack(lifeform_t *lf, lifeform_t *victim, int timelimit);
enum OBTYPE aigetattackspell(lifeform_t *lf, lifeform_t *victim);
enum OBTYPE aigetfleespell(lifeform_t *lf);
void aigetspelltarget(lifeform_t *lf, objecttype_t *spelltype, lifeform_t *victim, lifeform_t **spelllf, cell_t **spellcell, object_t **spellob, enum FLAG purpose);
object_t * aigetwand(lifeform_t *lf, enum FLAG purpose);
void aigoto(lifeform_t *lf, cell_t *c, int timelimit);
void aimove(lifeform_t *lf);
int aipickup(lifeform_t *lf, object_t *o);
int aiobok(lifeform_t *lf, object_t *o, lifeform_t *target);

4
defs.h
View File

@ -24,6 +24,7 @@ enum GAMEMODE {
GM_LOADING,
GM_LOADED,
GM_GAMESTARTED,
GM_GAMEOVER,
};
enum ATTRIB {
@ -1075,6 +1076,7 @@ enum FLAG {
F_NONE, // dummy flag
// object flags
F_DEAD, // object will be removed
F_CREATEDBY, // object was made by lf id v0, text=real lfname
F_ENCHANTABLE, // object can get +1/-1 ect
F_STACKABLE, // can stack multiple objects togethr
F_NO_PLURAL, // this obname doesn't need an 's' for plurals (eg. gold, money)
@ -1573,6 +1575,7 @@ enum ERROR {
enum COMMAND {
CMD_AIM,
CMD_CLOSE,
CMD_COMMS,
CMD_DOWN,
CMD_DROP,
CMD_DROPMULTI,
@ -1601,6 +1604,7 @@ enum COMMAND {
CMD_RESTFULL,
CMD_SAVEQUIT,
CMD_TAKEOFF,
CMD_THROW,
CMD_UP,
CMD_WEAR,
CMD_WEILD,

11
flag.c
View File

@ -307,7 +307,16 @@ void killflag(flag_t *f) {
if ((gamemode == GM_GAMESTARTED)) {
if (f->pile->owner) {
if (announceflagloss(f->pile->owner, f)) {
interrupt(f->pile->owner);
// don't include flags which interrupt will kill!
switch (f->id) {
case F_RESTING:
case F_RUNNING:
case F_AUTOCMD:
break;
default:
interrupt(f->pile->owner);
break;
}
}
} else if (f->pile->ob) {
announceobflagloss(f->pile->ob, f);

204
io.c
View File

@ -5,6 +5,7 @@
#include <string.h>
#include <ncurses.h>
#include <unistd.h>
#include "ai.h"
#include "attack.h"
#include "defs.h"
#include "flag.h"
@ -2227,7 +2228,9 @@ void describeob(object_t *o) {
f = hasflag(o->flags, F_ACCURACY);
if (f) {
mvwprintw(mainwin, y, 0, "It has %s accuracy.",getaccuracyname(f->val[0]));
int acc;
acc = getobaccuracy(o, NULL);
mvwprintw(mainwin, y, 0, "It has %s accuracy.",getaccuracyname(acc));
y++;
}
@ -2236,7 +2239,7 @@ void describeob(object_t *o) {
if (isarmour(o)) {
f = hasflag(o->flags, F_ARMOURRATING);
if (f) {
mvwprintw(mainwin, y, 0, "It has an Armour Rating of %d.",f->val[0]);
mvwprintw(mainwin, y, 0, "It has an Armour Rating of %d.",f->val[0] + getobbonus(o));
y++;
}
f = hasflag(o->flags, F_GOESON);
@ -2690,15 +2693,134 @@ void doclose(void) {
}
}
void dodrop(obpile_t *op, int wantmulti) {
void docomms(void) {
lifeform_t *lf = NULL;
cell_t *where;
char buf[BUFLEN];
char lfname[BUFLEN];
char ch;
where = askcoords("Talk to who?", TT_MONSTER);
if (where && where->lf && cansee(player, where->lf)) {
lf = where->lf;
}
if (!lf) {
msg("Cancelled.");
return;
}
getlfname(lf, lfname);
sprintf(buf, "What will you say to %s?",lfname);
initprompt(&prompt, buf);
prompt.maycancel = B_TRUE;
// are they friendly?
if (areallies(player, lf)) {
addchoice(&prompt, 'a', "Attack something", NULL, NULL);
if (!isadjacent(lf->cell, player->cell)) {
addchoice(&prompt, 'c', "Come here", NULL, NULL);
}
if (isadjacent(lf->cell, player->cell)) {
addchoice(&prompt, 't', "Trade items with me", NULL, NULL);
}
} else {
addchoice(&prompt, 'y', "Yeeeeeaaaargh!", NULL, NULL);
}
addchoice(&prompt, 'n', "(nothing)", NULL, NULL);
ch = getchoice(&prompt);
switch (ch) {
cell_t *c;
lifeform_t *lf2 = NULL;
char lfname2[BUFLEN];
case 'a':
sprintf(buf, "Tell %s to attack who?",lfname);
c = askcoords(buf, TT_MONSTER);
if (c && c->lf && cansee(player, c->lf)) {
lf2 = c->lf;
}
if (!lf2) {
msg("Cancelled.");
return;
}
getlfname(lf2, lfname2);
msg("You say \"Attack %s!\" to %s.",lfname2, lfname);
aiattack(lf, lf2, AI_FOLLOWTIME);
break;
case 'c':
msg("You say \"Come here!\" to %s.",lfname);
// find adjacent cell
c = getrandomadjcell(player->cell, WE_NOTSOLID);
if (c) {
aigoto(lf, c, AI_FOLLOWTIME);
}
break;
case 'n':
msg("Cancelled.");
return;
case 't':
// ask whtehr to give/take
initprompt(&prompt, "How will you trade?");
sprintf(buf, "Give items to %s",lfname);
addchoice(&prompt, 'i', buf, NULL, NULL);
sprintf(buf, "Take items from %s",lfname);
addchoice(&prompt, 'o', buf, NULL, NULL);
sprintf(buf, "Both");
addchoice(&prompt, 'b', buf, NULL, NULL);
sprintf(buf, "Neither");
addchoice(&prompt, 'n', buf, NULL, NULL);
ch = getchoice(&prompt);
switch (ch) {
case 'i':
dodrop(player->pack, B_MULTIPLE, lf->pack);
break;
case 'o':
dopickup(lf->pack);
break;
case 'b':
dodrop(player->pack, B_MULTIPLE, lf->pack);
dopickup(lf->pack);
break;
case 'n':
msg("Cancelled.");
return;
}
break;
case 'y':
msg("You shout at %s!", lfname);
noise(where, player, "someone shouting!", NULL);
break;
}
taketime(player, getactspeed(player));
}
void dodrop(obpile_t *op, int wantmulti, obpile_t *dst) {
object_t *o;
char buf[BUFLEN];
int count = ALL;
int i;
if (wantmulti) {
askobjectmulti(op, "Drop what", AO_NONE);
lifeform_t *tolf = NULL;
char lfname[BUFLEN];
// where is destination?
if (dst->owner) {
tolf = dst->owner;
getlfname(tolf, lfname);
} else {
o = askobject(op, "Drop what", &count, AO_NONE);
// on ground
}
if (tolf) {
sprintf(buf, "Give what to %s",lfname);
} else {
strcpy(buf, "Drop what");
}
if (wantmulti) {
askobjectmulti(op, buf, AO_NONE);
} else {
o = askobject(op, buf, &count, AO_NONE);
if (o) {
retobs[0] = o;
retobscount[0] = count;
@ -2726,7 +2848,13 @@ void dodrop(obpile_t *op, int wantmulti) {
if (f->val[0] == BP_WEAPON) {
// first try to unweild it
if (unweild(player, o)) {
if (nretobs > 1) msg("Not dropping %s.",buf); more();
if (nretobs > 1) {
if (tolf) {
msg("Not giving %s to %s.",buf, lfname); more();
} else {
msg("Not dropping %s.",buf); more();
}
}
continue;
}
} else { // armour
@ -2738,12 +2866,24 @@ void dodrop(obpile_t *op, int wantmulti) {
if (ch == 'y') {
if (takeoff(player, o)) {
// failed to take it off - can't drop it.
if (nretobs > 1) msg("Not dropping %s.",buf); more();
if (nretobs > 1) {
if (tolf) {
msg("Not giving %s to %s.",buf, lfname); more();
} else {
msg("Not dropping %s.",buf); more();
}
}
continue;
}
} else {
if (nretobs > 1) msg("Not dropping %s.",buf); more();
if (nretobs > 1) {
if (tolf) {
msg("Not giving %s to %s.",buf, lfname); more();
} else {
msg("Not dropping %s.",buf); more();
}
}
continue;
}
}
@ -2751,7 +2891,17 @@ void dodrop(obpile_t *op, int wantmulti) {
if (count == ALL) count = o->amt;
drop(o, count);
if (tolf) {
o = moveob(o, dst, count);
if (o) {
getobname(o, buf, o->amt);
msg("%s takes %s from you.",lfname, buf);
} else {
msg("%s can't carry that.",lfname);
}
} else {
drop(o, count);
}
}
}
@ -3364,21 +3514,39 @@ int dopickup(obpile_t *op) {
//object_t *o = NULL;
int howmany = ALL;
int i;
lifeform_t *fromlf = NULL;
char lfname[BUFLEN];
char buf[BUFLEN];
if (op->owner) {
fromlf = op->owner;
getlfname(fromlf, lfname);
}
obcount = countobs(op);
// anything here?
if (obcount == 0) {
msg("There is nothing here to pick up!");
if (fromlf) {
msg("%s is not carrying anything!", lfname);
} else {
msg("There is nothing here to pick up!");
}
return B_TRUE;
} else if ((obcount == 1) && (op->first->amt == 1)) {
} else if (!fromlf && (obcount == 1) && (op->first->amt == 1)) {
// just get it
howmany = ALL;
retobs[0] = op->first;
retobscount[0] = op->first->amt;
nretobs = 1;
} else {
if (fromlf) {
sprintf(buf, "Take what from %s",lfname);
} else {
strcpy(buf, "Pick up what");
}
// prompt which one to pick up
askobjectmulti(op, "Pick up what", AO_NONE);
askobjectmulti(op, buf, AO_NONE);
}
if (nretobs <= 0) {
@ -4771,14 +4939,17 @@ void handleinput(void) {
addflag(player->flags, F_LASTCMD, NA, NA, NA, temp);
doclose();
break;
case 'C': // communicate
docomms();
break;
case 'e': // eat
doeat(player->pack);
break;
case 'd': // drop
dodrop(player->pack, B_SINGLE);
dodrop(player->pack, B_SINGLE, player->cell->obpile);
break;
case 'D': // drop multiple things
dodrop(player->pack, B_MULTIPLE);
dodrop(player->pack, B_MULTIPLE, player->cell->obpile);
break;
case 'W': // wear
dowear(player->pack);
@ -6403,6 +6574,9 @@ void tombstone(lifeform_t *lf) {
int y;
char *p, *dummy;
gamemode = GM_GAMEOVER;
getplayernamefull(pname);
// clear screen

3
io.h
View File

@ -31,7 +31,8 @@ int contains(enum OBCLASS *array, int nargs, enum OBCLASS want);
void describeob(object_t *o);
void doattackcell(char dirch);
void doclose(void);
void dodrop(obpile_t *op, int wantmulti);
void docomms(void);
void dodrop(obpile_t *op, int wantmulti, obpile_t *dst);
void doeat(obpile_t *op);
void doenter(lifeform_t *lf);
void doexplain(void);

112
lf.c
View File

@ -394,24 +394,33 @@ int areallies(lifeform_t *lf1, lifeform_t *lf2) {
return B_FALSE;
}
// make sure player has at least novice skill in their start weapon
// make sure player has at least novice skill in all their start weapons
void autoskill(lifeform_t *lf) {
object_t *wep;
skill_t *sk;
wep = getweapon(lf);
if (wep) {
sk = getobskill(wep);
object_t *o;
enum SKILLLEVEL slev;
int nweps = 0;
if (isplayer(lf)) {
slev = PR_NOVICE;
} else {
sk = findskill(SK_UNARMED);
slev = PR_ADEPT;
}
if (sk) {
if (isplayer(lf)) {
giveskilllev(lf, sk->id, PR_NOVICE);
} else {
giveskilllev(lf, sk->id, PR_ADEPT);
for (o = lf->pack->first ; o ; o = o->next) {
if (isweapon(o) && canweild(lf, o)) {
sk = getobskill(o);
if (sk) {
giveskilllev(lf, sk->id, slev);
}
nweps++;
}
}
if (!nweps) {
giveskilllev(lf, SK_UNARMED, slev);
}
}
void autotarget(lifeform_t *lf) {
@ -523,9 +532,6 @@ void autoweild(lifeform_t *lf) {
// make sure it doesn't take any time
lf->timespent = pretimespent;
// make sure we are skilled in this.
autoskill(lf);
}
int appearsrandomly(enum RACE rid) {
@ -1750,7 +1756,7 @@ void fightback(lifeform_t *lf, lifeform_t *attacker) {
} else {
lifeform_t *l;
setlftarget(lf, attacker);
aiattack(lf, attacker, AI_FOLLOWTIME);
// any nearby monsters which will help out?
if (getallegiance(lf) != AL_FRIENDLY) {
@ -1758,7 +1764,7 @@ void fightback(lifeform_t *lf, lifeform_t *attacker) {
if (l->race->baseid == lf->race->baseid) {
if (!isdead(l) && areallies(l,lf)) {
if (cansee(l, attacker)) {
setlftarget(l, attacker);
aiattack(l, attacker, AI_FOLLOWTIME);
}
}
}
@ -2589,52 +2595,26 @@ int getlfaccuracy(lifeform_t *lf) {
// get weapon
wep = getweapon(lf);
if (wep) {
acc = getobaccuracy(wep);
acc = getobaccuracy(wep, lf);
} else {
// ie. unarmed
op = getunarmedweapon(lf, NULL);
if (op->first) {
wep = op->first;
acc = getobaccuracy(wep);
acc = getobaccuracy(wep, lf);
} else {
// cannot attack
acc = 0;
}
}
// modify for skill level
if (wep) {
skill_t *sk;
sk = getobskill(wep);
if (sk) {
switch (getskill(lf, sk->id)) {
case PR_INEPT:
acc -= 75;
break;
case PR_NOVICE:
acc -= 25;
break;
case PR_BEGINNER:
acc -= 5;
break;
case PR_ADEPT:
break;
case PR_SKILLED:
acc += 25;
break;
case PR_EXPERT:
acc += 50;
break;
case PR_MASTER:
acc += 75;
break;
}
}
}
if (op) killobpile(op);
// modify for weilder's level
acc += (lf->level * 2);
// modify with dexterity
acc += getstatmod(lf, A_DEX);
@ -3014,11 +2994,15 @@ char *real_getlfname(lifeform_t *lf, char *buf, int usevis) {
}
char *getlfnamea(lifeform_t *lf, char *buf) {
return real_getlfnamea(lf, buf, B_TRUE);
}
char *real_getlfnamea(lifeform_t *lf, char *buf, int usevis) {
if (lf == player) {
sprintf(buf, "you");
} else {
char buf2[BUFLEN];
getlfname(lf, buf2);
real_getlfname(lf, buf2, usevis);
sprintf(buf, "%s %s",
isvowel(lf->race->name[0]) ? "an" : "a",
noprefix(buf2));
@ -3662,6 +3646,7 @@ void givejob(lifeform_t *lf, enum JOB jobid) {
// now give start obs/skills from it
givestartobs(lf, lf->flags);
givestartskills(lf, lf->flags);
autoskill(lf);
// override hp/mp from race
@ -4255,6 +4240,7 @@ int haslof(lifeform_t *viewer, cell_t *dest, enum LOFTYPE loftype, cell_t **newd
cell_t *retcell[MAXRETCELLS];
reason = E_OK;
if (newdest) *newdest = viewer->cell;
if (!viewer) return B_FALSE;
if (!viewer->cell) return B_FALSE;
@ -4279,8 +4265,6 @@ int haslof(lifeform_t *viewer, cell_t *dest, enum LOFTYPE loftype, cell_t **newd
calcbresnham(map, x1, y1, x2, y2, retcell, &numpixels);
if (newdest) *newdest = viewer->cell;
for (i = 0; i < numpixels ; i++) {
cell_t *cell;
object_t *blockob;
@ -4512,6 +4496,9 @@ void initjobs(void) {
}
}
addjob(J_ADVENTURER, "Adventurer");
addflag(lastjob->flags, F_STARTATT, A_STR, ST_AVERAGE, NA, NULL);
addflag(lastjob->flags, F_STARTATT, A_DEX, DX_AVERAGE, NA, NULL);
addflag(lastjob->flags, F_STARTATT, A_IQ, IQ_AVERAGE, NA, NULL);
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "short sword");
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "2 bananas");
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "leather armour");
@ -6548,6 +6535,7 @@ void noise(cell_t *c, lifeform_t *noisemaker, char *text, char *seetext) {
void outfitlf(lifeform_t *lf) {
givestartobs(lf, lf->flags);
givestartskills(lf, lf->flags);
autoskill(lf);
// weild/wear stuff
autoweild(lf);
@ -7346,6 +7334,8 @@ void interrupt(lifeform_t *lf) {
stoprunning(lf);
killflagsofid(lf->flags, F_AUTOCMD);
}
/*j
void setlftarget(lifeform_t *lf, lifeform_t *victim) {
// first remove existing targets
killflagsofid(lf->flags, F_TARGET);
@ -7362,6 +7352,7 @@ void setlftarget(lifeform_t *lf, lifeform_t *victim) {
}
}
}
*/
int shoot(lifeform_t *lf) {
object_t *gun,*ammo;
@ -7562,6 +7553,10 @@ int slipon(lifeform_t *lf, object_t *o) {
moveob(o, new->obpile, 1);
}
}
// stop sprinting
killflagsofid(lf->flags, F_SPRINTING);
// boost spells end
stopallspells(lf);
return B_FALSE;
}
@ -8061,9 +8056,22 @@ void turneffectslf(lifeform_t *lf) {
f = hasflag(o->flags, F_WALKDAM);
if (f) {
int dam;
flag_t *fromlfflag;
lifeform_t *fromlf = NULL;
char damstring[BUFLEN];
dam = roll(f->text);
getobname(o, buf, o->amt);
dam = losehp(lf, dam, f->val[0], NULL, buf);
fromlfflag = hasflag(o->flags, F_CREATEDBY);
if (fromlfflag) {
sprintf(damstring, "%s^created by %s",buf, fromlfflag->text);
} else {
strcpy(damstring, buf);
}
dam = losehp(lf, dam, f->val[0], fromlf, damstring);
if (dam > 0) {
if (f->val[0] == DT_POISONGAS) {
if (isplayer(lf) || cansee(player, lf)) {

3
lf.h
View File

@ -94,6 +94,7 @@ lifeform_t *getnearbypeaceful(lifeform_t *lf);
char *getlfname(lifeform_t *lf, char *buf);
char *real_getlfname(lifeform_t *lf, char *buf, int usevis);
char *getlfnamea(lifeform_t *lf, char *buf);
char *real_getlfnamea(lifeform_t *lf, char *buf, int usevis);
enum LFSIZE getlfsize(lifeform_t *lf);
float getlfweight(lifeform_t *lf, int withobs);
int getspellspeed(lifeform_t *lf);
@ -188,7 +189,7 @@ void setattr(lifeform_t *lf, enum ATTRIB attr, int val);
void setguntarget(lifeform_t *lf, lifeform_t *targ);
void setrace(lifeform_t *lf, enum RACE rid);
void setlastdam(lifeform_t *lf, char *buf);
void setlftarget(lifeform_t *lf, lifeform_t *victim);
//void setlftarget(lifeform_t *lf, lifeform_t *victim);
int shoot(lifeform_t *lf);
int skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod);
int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *result);

181
log.txt
View File

@ -7,7 +7,6 @@ xxx
xxx
xxx
xxx
xxx
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
@ -116,3 +115,183 @@ finding random lf with rarity val 85-100
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 9 possibilities.
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 9 possibilities.
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 9 possibilities.
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 9 possibilities.
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 9 possibilities.
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 9 possibilities.
rollhitdice() - rolling 2d4 + 2
rollhitdice() - mod is +-5%
rollhitdice() ---- die 1/2 == 5
rollhitdice() ---- die 2/2 == 6
TOTAL: 11
-> modified to: 11
givejob() starting.
processing normal flag: 186
processing normal flag: 145
processing normal flag: 145
processing normal flag: 145
processing normal flag: 145
processing normal flag: 145
processing normal flag: 145
processing normal flag: 145
processing normal flag: 145
processing normal flag: 145
processing normal flag: 145
processing normal flag: 145
processing normal flag: 145
processing normal flag: 146
processing normal flag: 146
processing normal flag: 146
processing normal flag: 146
processing normal flag: 146
processing normal flag: 213
processing normal flag: 213
processing normal flag: 213
processing normal flag: 213
processing normal flag: 213
processing normal flag: 213
processing normal flag: 213
processing normal flag: 213
processing normal flag: 213
processing normal flag: 213
processing normal flag: 213
processing normal flag: 213
processing normal flag: 213
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
processing normal flag: 212
fireat(): dam = throwdam(2) * speed(2) = 4
AIMOVE: something
.oO { looking for covetted objects... }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { i have a target... }
.oO { my target is lfid 31 (human). }
.oO { i cannot see my target. moving to last known loc 12/15 }
.oO { something going to targecell: 12, 15 }
.oO { walking from 12,17 towards f_targetcell (12,15) ... }
.oO { successfully walked towards f_targetcell. }
AIMOVE: something
.oO { looking for covetted objects... }
.oO { didn't find any obs i want }
.oO { walking from 11,18 towards f_targetcell (12,15) ... }
.oO { successfully walked towards f_targetcell. }

13
map.c
View File

@ -167,6 +167,19 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt) {
}
free(moncell);
}
// sometimes give the lf random objects (extra monsters through
// 'numappears' don't get them.
if (!lfhasflag(lf, F_NOPACK)) {
if (rnd(1,3) == 1) {
int nobs = rnd(1,3);
char buf[BUFLEN];
int i;
for (i = 0; i < nobs; i++) {
if (getrandomob(c->map, buf)) addob(lf->pack, buf);
}
}
}
lf->born = B_TRUE;
} // end if lf
}

115
move.c
View File

@ -81,24 +81,53 @@ int canmove(lifeform_t *lf, int dir, enum ERROR *error) {
}
// lf is the one moving, lf2 is the one who is being forced to swap
int canswapwith(lifeform_t *lf, lifeform_t *lf2) {
// player can never be forced to swap
if (isplayer(lf2)) {
return B_FALSE;
}
// cannot swap if lf's cell is dangerous to lf2
if (celldangerous(lf2, lf->cell, B_FALSE, NULL)) {
return B_FALSE;
}
// allies can always swap
if (areallies(lf, lf2)) {
return B_TRUE;
}
if (isplayer(lf) && !areenemies(lf, lf2)) {
// player can swap with peaceful lgs
// if they are a lot smaller
if (getlfsize(lf) - getlfsize(lf2) >= 2) {
return B_TRUE;
}
}
return B_FALSE;
}
// will populate rdata
int celldangerous(lifeform_t *lf, cell_t *cell, enum ERROR *error) {
// onlyifknown = true means "check for _known_ dangerous objects"
// onlyifknown = false means "check for _any dangerous objects, doesn't matter if we know about them"
int celldangerous(lifeform_t *lf, cell_t *cell, int onlyifknown, enum ERROR *error) {
enum IQBRACKET iq;
int include_nonobvious = B_FALSE;
flag_t *f;
object_t *o;
// default
if (error) {
*error = E_OK;
rdata = NULL;
}
// check for _known_ dangerous objects
iq = getiqname(getattr(lf, A_IQ), NULL);
if ((iq >= IQ_AVERAGE) && !isblind(lf)) {
flag_t *f;
object_t *o;
// obvious things that you can see
if (!onlyifknown || haslos(lf, cell)) {
for (o = cell->obpile->first ; o ; o = o->next) {
// don't walk on sharp objects without boots
if (hasflag(o->flags, F_SHARP)) {
if (!getequippedob(lf->pack, BP_FEET)) {
f = hasflag(o->flags, F_WALKDAM);
if (f) {
// are we immune to this?
if (!lfhasflagval(lf, F_DTIMMUNE, f->val[0], NA, NA, NULL)) {
if (error) {
*error = E_AVOIDOB;
rdata = o;
@ -106,10 +135,23 @@ int celldangerous(lifeform_t *lf, cell_t *cell, enum ERROR *error) {
return B_TRUE;
}
}
f = hasflag(o->flags, F_WALKDAM);
if (f) {
// are we immune to this?
if (!lfhasflagval(lf, F_DTIMMUNE, f->val[0], NA, NA, NULL)) {
}
}
// non-obvious things - only include these if we are smart enough
if (!onlyifknown) {
include_nonobvious = B_TRUE;
} else {
iq = getiqname(getattr(lf, A_IQ), NULL);
if ((iq >= IQ_AVERAGE) && haslos(lf, cell)) {
include_nonobvious = B_TRUE;
}
}
if (include_nonobvious) {
for (o = cell->obpile->first ; o ; o = o->next) {
// don't walk on sharp objects without boots
if (hasflag(o->flags, F_SHARP)) {
if (!getequippedob(lf->pack, BP_FEET)) {
if (error) {
*error = E_AVOIDOB;
rdata = o;
@ -616,7 +658,6 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
if (haslos(l, newcell)) {
int dointerrupt = B_FALSE;
if (isplayer(l)) {
if (areenemies(lf, l)) {
if (lfhasflag(l, F_RUNNING) || lfhasflag(l, F_RESTING)) {
@ -1213,31 +1254,31 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
}
break;
case E_LFINWAY:
if (areallies(lf, cell->lf)) {
// if it's the player in the way...
if (isplayer(cell->lf)) {
return attacklf(lf, cell->lf);
} else {
lifeform_t *lfinway;
cell_t *oldcell;
// otherwise swap locations.
// make lf who is there vanish temporarily...
lfinway = cell->lf;
cell->lf = NULL;
lfinway->cell = NULL;
if (canswapwith(lf, cell->lf)) {
lifeform_t *lfinway;
cell_t *oldcell;
// otherwise swap locations.
// make lf who is there vanish temporarily...
lfinway = cell->lf;
cell->lf = NULL;
lfinway->cell = NULL;
// remember your cell
oldcell = lf->cell;
// remember your cell
oldcell = lf->cell;
// move you..
moveto(lf, cell, onpurpose);
taketime(lf, getmovespeed(lf));
// move you..
moveto(lf, cell, onpurpose);
taketime(lf, getmovespeed(lf));
// move them...
lfinway->cell = oldcell;
oldcell->lf = lfinway;
reason = E_OK;
// move them...
lfinway->cell = oldcell;
oldcell->lf = lfinway;
reason = E_OK;
if (isplayer(lf)) {
char lfname[BUFLEN];
getlfname(lfinway, lfname);
msg("You swap places with %s.", lfname);
}
} else {
// attack!
@ -1315,7 +1356,7 @@ int willmove(lifeform_t *lf, int dir, enum ERROR *error) {
}
cell = getcellindir(lf->cell, dir);
if (celldangerous(lf, cell, error)) {
if (celldangerous(lf, cell, B_TRUE, error)) {
return B_FALSE;
}

3
move.h
View File

@ -2,7 +2,8 @@
int canandwillmove(lifeform_t *lf, int dir, enum ERROR *error);
int canmove(lifeform_t *lf, int dir, enum ERROR *error);
int celldangerous(lifeform_t *lf, cell_t *cell, enum ERROR *error);
int canswapwith(lifeform_t *lf, lifeform_t *lf2);
int celldangerous(lifeform_t *lf, cell_t *cell, int onlyifknown, enum ERROR *error);
int cellwalkable(lifeform_t *lf, cell_t *cell, enum ERROR *error);
int closedoorat(lifeform_t *lf, cell_t *c);
int closedoor(lifeform_t *lf, object_t *o);

View File

@ -631,6 +631,7 @@ void initcommands(void) {
addcommand(CMD_REST, '.', "Rest once.");
addcommand(CMD_PICKUP, ',', "Pick up something from the ground.");
addcommand(CMD_CLOSE, 'c', "Close a door.");
addcommand(CMD_COMMS, 'C', "Communicate with an ally.");
addcommand(CMD_DROP, 'd', "Drop an item.");
addcommand(CMD_DROPMULTI, 'D', "Drop multiple items.");
addcommand(CMD_EAT, 'e', "Eat something.");
@ -643,6 +644,7 @@ void initcommands(void) {
addcommand(CMD_QUAFF, 'q', "Quaff (drink) a potion.");
addcommand(CMD_READ, 'r', "Read a scroll/book.");
addcommand(CMD_RESTFULL, 'R', "Rest until healed, or train your skills.");
addcommand(CMD_THROW, 't', "Throw an object.");
addcommand(CMD_TAKEOFF, 'T', "Take off an item of clothing/jewelery.");
addcommand(CMD_WEILD, 'w', "Weild a weapon.");
addcommand(CMD_WEAR, 'W', "Wear an item of clothing/jewelery.");

265
objects.c
View File

@ -975,7 +975,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack) {
// add objects in a circle
// returns # added.
int addobburst(cell_t *where, int range, int dirtype, char *name) {
int addobburst(cell_t *where, int range, int dirtype, char *name, lifeform_t *fromlf) {
int (*distfunc)(cell_t *, cell_t *);
int x,y;
cell_t *c;
@ -994,7 +994,12 @@ int addobburst(cell_t *where, int range, int dirtype, char *name) {
c = getcellat(where->map, x,y);
if (distfunc(where, c) <= range) {
if (!c->type->solid) {
if (addob(c->obpile, name)) nadded++;
object_t *o;
o = addob(c->obpile, name);
if (o) {
if (fromlf) setobcreatedby(o, fromlf);
nadded++;
}
}
}
}
@ -1245,6 +1250,7 @@ void adjustdamob(object_t *o, unsigned int *dam, enum DAMTYPE damtype) {
}
o->blessknown = B_TRUE;
}
*dam = 0;
return;
}
} else if (o->blessed == B_CURSED) {
@ -2044,7 +2050,7 @@ int getcharges(object_t *o) {
return amt;
}
int getobaccuracy(object_t *wep) {
int getobaccuracy(object_t *wep, lifeform_t *weilder) {
int acc;
flag_t *f;
@ -2063,6 +2069,36 @@ int getobaccuracy(object_t *wep) {
acc = f->val[0];
}
if (weilder) {
skill_t *sk;
// modify for weilder's skill
sk = getobskill(wep);
if (sk) {
switch (getskill(weilder, sk->id)) {
case PR_INEPT:
acc -= 75;
break;
case PR_NOVICE:
acc -= 25;
break;
case PR_BEGINNER:
acc -= 5;
break;
case PR_ADEPT:
break;
case PR_SKILLED:
acc += 25;
break;
case PR_EXPERT:
acc += 50;
break;
case PR_MASTER:
acc += 75;
break;
}
}
}
// modify for attacker's level
if (wep->pile->owner) {
acc += (wep->pile->owner->level * 2);
@ -4400,7 +4436,7 @@ void initobjects(void) {
addflag(lastot->flags, F_AIFLEEITEM, B_TRUE, NA, NA, NULL);
addot(OT_SCR_REMOVECURSE, "scroll of remove curse", "Removes curses from all weilded equipment.", MT_PAPER, 0.5, OC_SCROLL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 85, NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, NULL);
addot(OT_SCR_TURNUNDEAD, "scroll of turn undead", "Instills fear in undead creatures.", MT_PAPER, 0.5, OC_SCROLL);
addflag(lastot->flags, F_LINKSPELL, OT_S_TURNUNDEAD, NA, NA, NULL);
@ -4583,7 +4619,7 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLLEVEL, 5, NA, NA, NULL);
addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL);
// l6
addot(OT_S_FLIGHT, "flight", "Allows the caster to fly.", MT_NOTHING, 0, OC_SPELL);
addot(OT_S_FLIGHT, "fly", "Allows the caster to fly.", MT_NOTHING, 0, OC_SPELL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_GRAVITY, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 6, NA, NA, NULL);
addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL);
@ -4844,7 +4880,7 @@ void initobjects(void) {
addflag(lastot->flags, F_MANUALOF, SK_SS_GRAVITY, NA, NA, NULL);
addot(OT_MAN_SS_LIFE, "manual of life magic", "Teaches you the skill 'life magic'.", MT_PAPER, 3, OC_BOOK);
addflag(lastot->flags, F_MANUALOF, SK_SS_LIFE, NA, NA, NULL);
addot(OT_MAN_SS_MODIFICATION, "manual of modification", "Teaches you the skill 'modification'.", MT_PAPER, 3, OC_BOOK);
addot(OT_MAN_SS_MODIFICATION, "manual of modification magic", "Teaches you the skill 'modification magic'.", MT_PAPER, 3, OC_BOOK);
addflag(lastot->flags, F_MANUALOF, SK_SS_MODIFICATION, NA, NA, NULL);
addot(OT_MAN_SS_MENTAL, "manual of psionics", "Teaches you the skill 'psionics'.", MT_PAPER, 3, OC_BOOK);
addflag(lastot->flags, F_MANUALOF, SK_SS_MENTAL, NA, NA, NULL);
@ -4901,7 +4937,7 @@ void initobjects(void) {
addflag(lastot->flags, F_LINKSPELL, OT_S_GRAVLOWER, NA, NA, NULL);
addot(OT_SB_GRAVBOOST, "spellbook of boost gravity", "Teaches the spell 'boost gravity'.", MT_PAPER, 1.5, OC_BOOK);
addflag(lastot->flags, F_LINKSPELL, OT_S_GRAVBOOST, NA, NA, NULL);
addot(OT_SB_FLIGHT, "spellbook of flight", "Teaches the spell 'flight'.", MT_PAPER, 1.5, OC_BOOK);
addot(OT_SB_FLIGHT, "spellbook of fly", "Teaches the spell 'fly'.", MT_PAPER, 1.5, OC_BOOK);
addflag(lastot->flags, F_LINKSPELL, OT_S_FLIGHT, NA, NA, NULL);
addot(OT_SB_HASTE, "spellbook of haste", "Teaches the spell 'haste'.", MT_PAPER, 1.5, OC_BOOK);
addflag(lastot->flags, F_LINKSPELL, OT_S_HASTE, NA, NA, NULL);
@ -6348,33 +6384,63 @@ int isbetterarmourthan(object_t *a, object_t *b) {
// compare weapons using max damage
int isbetterwepthan(object_t *a, object_t *b) {
flag_t *f;
//flag_t *f;
int dama,damb;
float acca,accb;
int db = B_FALSE;
char namea[BUFLEN];
char nameb[BUFLEN];
if (!a) return B_FALSE;
if (!b) return B_TRUE;
f = hasflag(a->flags, F_DAM);
if (f) {
dama = (f->val[0] * f->val[1]) + f->val[2];
} else {
dama = 0;
/* if (a->pile->owner && lfhasflag(a->pile->owner, F_DEBUG)) {
db = B_TRUE;
}
if (b->pile->owner && lfhasflag(b->pile->owner, F_DEBUG)) {
db = B_TRUE;
} */
if (db) {
getobname(a, namea, a->amt);
getobname(b, nameb, b->amt);
}
f = hasflag(b->flags, F_DAM);
if (f) {
damb = (f->val[0] * f->val[1]) + f->val[2];
} else {
damb = 0;
}
getdamrange(a->flags, NULL, &dama);
getdamrange(b->flags, NULL, &damb);
// modify based on extra props
if (hasflag(a->flags, F_HASBRAND)) {
dama *= 3;
}
if (hasflag(a->flags, F_ONFIRE)) {
dama += 8;
}
if (hasflag(b->flags, F_HASBRAND)) {
damb *= 3;
}
if (hasflag(b->flags, F_ONFIRE)) {
damb += 8;
}
// modify with accuracy
acca = getobaccuracy(a, a->pile->owner);
accb = getobaccuracy(b, b->pile->owner);
if (db) {
msg("PREACC:a=%s:%d(acc %d), b=%s:%d(acc %d)",namea,dama,(int)acca, nameb, damb,(int)accb);
}
dama = (int)((float)dama * (acca/100));
damb = (int)((float)damb * (accb/100));
if (db) {
msg("POST:a=%s:%d(acc %d), b=%s:%d(acc %d)",namea,dama,(int)acca, nameb, damb,(int)accb);
}
if (dama > damb) return B_TRUE;
return B_FALSE;
@ -8972,6 +9038,15 @@ void setinscription(object_t *o, char *text) {
o->inscription = strdup(text);
}
void setobcreatedby(object_t *o, lifeform_t *lf) {
char lfname[BUFLEN];
if (!lf) {
return;
}
real_getlfnamea(lf, lfname, B_FALSE);
addflag(o->flags, F_CREATEDBY, lf->id, NA, NA, lfname);
}
// randomizes hidden names
void shufflehiddennames(void) {
int i,n;
@ -9240,6 +9315,7 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
object_t *newob;
cell_t *newloc;
int db = B_TRUE;
int willcatch = B_FALSE;
reason = E_OK;
@ -9333,6 +9409,9 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
}
if (target) {
getlfname(target, targetname);
if (areallies(thrower, target) && !firearm) {
willcatch = B_TRUE;
}
}
// touch effects
@ -9346,7 +9425,7 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
if (thrower && isplayer(thrower)) {
// player is throwing something
if (target) {
msg("You %s %s at %s.", throwverbpres, obname, targetname);
msg("You %s %s %s %s.", throwverbpres, obname, willcatch ? "to" : "at", targetname);
} else {
msg("You %s %s.",throwverbpres, obname);
}
@ -9358,7 +9437,7 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
obname);
if (target && haslos(player, where)) {
strcat(throwstring, " at ");
strcat(throwstring, willcatch ? " to " : " at ");
strcat(throwstring, targetname);
}
strcat(throwstring, ".");
@ -9430,7 +9509,11 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
// find out your chances of hitting
if (target) {
if (thrower) {
acc = getmissileaccuracy(thrower, where, o, firearm, A_DEX);
if (willcatch) {
acc = 100;
} else {
acc = getmissileaccuracy(thrower, where, o, firearm, A_DEX);
}
} else {
// purely based on saving throw...
acc = 100;
@ -9450,7 +9533,7 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
}
// saving throw
if (youhit) {
if (youhit && !willcatch) {
if (skillcheck(target, SC_DODGE, 20, 0)) {
youhit = B_FALSE;
}
@ -9462,77 +9545,87 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
msg("%s recoils in fear!", targetname);
}
o->blessknown = B_TRUE;
// ... but undead won't catch blessed things
willcatch = B_FALSE;
}
// if someone is there, they take damage and the object might die
// this should be "if target && youhit"
if (youhit) {
int dam = 0,shatterdam = 0;
char damstring[BUFLEN];
int reduceamt = 0;
int throwdam;
throwdam = getthrowdam(o);
dam = throwdam * speed;
if (db) dblog("fireat(): dam = throwdam(%d) * speed(%d) = %d",throwdam, speed, dam);
// special case
if (o->type->id == OT_RUBBERBULLET) {
dam = 1;
}
// deal extra cutting damage afterwards?
shatterdam = getshatterdam(o);
if (shatterdam > 0) {
shattered = B_TRUE;
}
// announce
if (seen) {
char buf2[BUFLEN];
sprintf(buf2, "%s hit%s %s%s",obname,(amt == 1) ? "s" : "", targetname,
(willshatter(o->material->id)) ? " and shatters!" : "."
);
if (lfhasflag(player, F_EXTRAINFO)) {
char damstring[BUFLEN];
sprintf(damstring, " [%d dmg]",dam);
strcat(buf2, damstring);
}
msg("%s", buf2);
} else {
if (willshatter(o->material->id)) {
noise(where, NULL, "shattering glass.", NULL);
}
}
sprintf(damstring, "%s (%s by %s)",obname,throwverbpast, realthrowernamea);
reduceamt = getarmourdamreduction(target, o, dam, DT_PROJECTILE);
applyarmourdamreduction(target, o, reduceamt, &dam, DT_PROJECTILE);
if (dam > 0) {
lifeform_t *whogetsxp = NULL;
// TODO: at the moment you won't get experience if you telekenetically
// throw an object at something. is this okay?
if (thrower && (thrower->cell == srcloc)) {
whogetsxp = thrower;
}
losehp(target, dam, DT_PROJECTILE, whogetsxp, damstring);
}
if (reduceamt && (speed >= 3)) {
applyarmourdamage(target, o, reduceamt, DT_PROJECTILE);
}
if (shatterdam && !isdead(target)) {
// extra glass damage
if (willcatch) {
if (seen) {
msg("%s %s showered in glass shards!", targetname, isplayer(target) ? "are" : "is");
msg("%s catches %s.", targetname, obname);
}
moveob(o, target->pack, amt);
return B_FALSE;
} else {
int dam = 0,shatterdam = 0;
char damstring[BUFLEN];
int reduceamt = 0;
int throwdam;
throwdam = getthrowdam(o);
dam = throwdam * speed;
if (db) dblog("fireat(): dam = throwdam(%d) * speed(%d) = %d",throwdam, speed, dam);
// special case
if (o->type->id == OT_RUBBERBULLET) {
dam = 1;
}
// deal extra cutting damage afterwards?
shatterdam = getshatterdam(o);
if (shatterdam > 0) {
shattered = B_TRUE;
}
// announce
if (seen) {
char buf2[BUFLEN];
sprintf(buf2, "%s hit%s %s%s",obname,(amt == 1) ? "s" : "", targetname,
(willshatter(o->material->id)) ? " and shatters!" : "."
);
if (lfhasflag(player, F_EXTRAINFO)) {
char damstring[BUFLEN];
sprintf(damstring, " [%d dmg]",dam);
strcat(buf2, damstring);
}
msg("%s", buf2);
} else {
if (willshatter(o->material->id)) {
noise(where, NULL, "shattering glass.", NULL);
}
}
sprintf(damstring, "%s (%s by %s)",obname,throwverbpast, realthrowernamea);
losehp(target, shatterdam, DT_SLASH, thrower, damstring);
}
reduceamt = getarmourdamreduction(target, o, dam, DT_PROJECTILE);
applyarmourdamreduction(target, o, reduceamt, &dam, DT_PROJECTILE);
if (dam > 0) {
lifeform_t *whogetsxp = NULL;
// TODO: at the moment you won't get experience if you telekenetically
// throw an object at something. is this okay?
if (thrower && (thrower->cell == srcloc)) {
whogetsxp = thrower;
}
losehp(target, dam, DT_PROJECTILE, whogetsxp, damstring);
}
if (reduceamt && (speed >= 3)) {
applyarmourdamage(target, o, reduceamt, DT_PROJECTILE);
}
if (shatterdam && !isdead(target)) {
// extra glass damage
if (seen) {
msg("%s %s showered in glass shards!", targetname, isplayer(target) ? "are" : "is");
}
sprintf(damstring, "%s (%s by %s)",obname,throwverbpast, realthrowernamea);
losehp(target, shatterdam, DT_SLASH, thrower, damstring);
}
}
} else {
if (isplayer(thrower)) {
msg("Your %s misses %s.", noprefix(obname), targetname);
@ -10298,7 +10391,7 @@ int getmissileaccuracy(lifeform_t *thrower, cell_t *where, object_t *missile, ob
// base accuracy
if (firearm) {
acc = getobaccuracy(firearm);
acc = getobaccuracy(firearm, thrower);
} else {
acc = 50;
}

View File

@ -10,7 +10,7 @@ material_t *addmaterial(enum MATERIAL id, char *name, float weightrating);
objectclass_t *addoc(enum OBCLASS id, char *name, char *desc, char glyph);
object_t *addob(obpile_t *where, char *name);
object_t *addobject(obpile_t *where, char *name, int canstack);
int addobburst(cell_t *where, int range, int dirtype, char *name);
int addobburst(cell_t *where, int range, int dirtype, char *name, lifeform_t *fromlf);
obmod_t *addobmod(enum OBMOD id, char *prefix);
obpile_t *addobpile(lifeform_t *owner, cell_t *where);
objecttype_t *addot(int id, char *name, char *description, int material, float weight, int obclassid);
@ -49,7 +49,7 @@ int geteffecttime(int min, int max, enum BLESSTYPE isblessed);
objecttype_t *getlinkspell(object_t *o);
enum MATSTATE getmaterialstate(enum MATERIAL mat);
int getmissileaccuracy(lifeform_t *thrower, cell_t *where, object_t *missile, object_t *firearm, enum ATTRIB whichatt);
int getobaccuracy(object_t *wep);
int getobaccuracy(object_t *wep, lifeform_t *weilder);
int getobbonus(object_t *o);
skill_t *getobskill(object_t *o);
int getobvalue(object_t *o);
@ -170,6 +170,7 @@ int removeob(object_t *o, int howmany);
object_t *relinkob(object_t *src, obpile_t *dst);
void setblessed(object_t *o, enum BLESSTYPE wantbless);
void setinscription(object_t *o, char *text);
void setobcreatedby(object_t *o, lifeform_t *lf);
void shufflehiddennames(void);
object_t *splitob(object_t *o);
int takedamage(object_t *o, unsigned int howmuch, int damtype);

61
spell.c
View File

@ -19,6 +19,8 @@
extern lifeform_t *player;
extern skill_t *firstskill, *lastskill;
extern int needredraw;
extern prompt_t prompt;
extern WINDOW *msgwin;
@ -830,7 +832,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
int tries = 0,maxtries = 10;
// pick a random location
targcell = NULL;
while (!targcell || !cellwalkable(caster, targcell, NULL) || celldangerous(caster, targcell, NULL)) {
while (!targcell || !cellwalkable(caster, targcell, NULL) || celldangerous(caster, targcell, B_FALSE, NULL)) {
int i;
i = rnd(0,caster->nlos-1);
targcell = caster->los[i];
@ -858,19 +860,31 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// don't set caster's cell on fire!
for (i = 1; i < nretcell; i++) {
cell_t *c;
object_t *o;
c = retcell[i];
// set on fire
addob(c->obpile, "medium fire");
if (c->lf) {
char buf[BUFLEN];
getlfname(c->lf,buf);
if (!isimmuneto(c->lf->flags, DT_FIRE)) {
msg("%s burn%s!",buf,isplayer(c->lf) ? "" : "s");
o = addob(c->obpile, "medium fire");
if (o) {
setobcreatedby(o, caster);
if (c->lf) {
char buf[BUFLEN];
char damstring[BUFLEN];
char realcname[BUFLEN];
getlfname(c->lf,buf);
if (!isimmuneto(c->lf->flags, DT_FIRE)) {
msg("%s burn%s!",buf,isplayer(c->lf) ? "" : "s");
}
real_getlfname(caster, realcname, B_FALSE);
sprintf(damstring, "%s%s wave of fire", realcname, getpossessive(realcname));
losehp(c->lf, rolldie(2,10), DT_FIRE, caster, damstring);
}
losehp(c->lf, rolldie(2,10), DT_FIRE, caster, "a wave of fire");
}
}
if (cansee(player, caster)) {
needredraw = B_TRUE;
}
} else if (spellid == OT_S_CLOUDKILL) {
if (!validatespellcell(caster, &targcell, TT_MONSTER, B_FALSE, LOF_NEED, spellid, power)) return B_TRUE;
@ -880,7 +894,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
return B_FALSE;
}
addobburst(targcell, (power/3), DT_COMPASS, "cloud of gas");
addobburst(targcell, (power/3), DT_COMPASS, "cloud of gas", caster);
if (haslos(player, targcell)) {
msg("A cloud of poison gas appears!");
@ -1331,6 +1345,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (!targcell->type->solid || hasflag(targcell->type->material->flags, F_FLAMMABLE)) {
int dir;
cell_t *c;
object_t *o;
// centre fireball here...
if (isplayer(caster)) {
msg("You launch an enormous ball of fire!");
@ -1356,14 +1371,20 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
for (dir = D_N; dir <= D_W; dir++) {
c = getcellindir(targcell, dir);
if (c && (!c->type->solid || hasflag(c->type->material->flags, F_FLAMMABLE)) ) {
addob(c->obpile, "large fire");
o = addob(c->obpile, "large fire");
if (o) {
setobcreatedby(o, caster);
}
}
}
for (dir = DC_NE; dir <= DC_NW; dir += 2) {
cell_t *c;
c = getcellindir(targcell, dir);
if (c && (!c->type->solid || hasflag(c->type->material->flags, F_FLAMMABLE)) ) {
addob(c->obpile, "medium fire");
o = addob(c->obpile, "medium fire");
if (o) {
setobcreatedby(o, caster);
}
}
}
for (dir = D_N; dir <= D_W; dir++) {
@ -1372,7 +1393,10 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (c) {
c = getcellindir(c, dir);
if (c && (!c->type->solid || hasflag(c->type->material->flags, F_FLAMMABLE)) ) {
addob(c->obpile, "small fire");
o = addob(c->obpile, "small fire");
if (o) {
setobcreatedby(o, caster);
}
}
}
}
@ -1476,6 +1500,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
f->val[0] += power;
f->val[1] += power;
}
setobcreatedby(o, caster);
} else {
failed = B_TRUE;
}
@ -1659,7 +1684,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
if (skillcheck(target, SC_RESISTMAG, 20 + power, 0)) {
if (getmr(target) && skillcheck(target, SC_RESISTMAG, 20 + power, 0)) {
if (isplayer(target) || haslos(player, target->cell)) {
getlfname(target, buf);
msg("%s blur%s for a moment.",buf, isplayer(target) ? "" : "s");
@ -1819,7 +1844,11 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
} else {
losehp(l, 9999, DT_DIRECT, NULL, "an infinite death spell");
char dambuf[BUFLEN];
char cname[BUFLEN];
real_getlfname(caster, cname, B_FALSE);
sprintf(dambuf, "%s%s infinite death spell", cname, getpossessive(cname));
losehp(l, 9999, DT_DIRECT, NULL, dambuf);
}
}
}
@ -2303,6 +2332,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
// create the source portal
srcportal = addob(srccell->obpile, "magic portal");
setobcreatedby(srcportal, caster);
// announce, because we might have a delay creating the level...
if (isplayer(caster)) {
@ -2327,6 +2357,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
// add the dst portal
dstportal = addob(newcell->obpile, "magic portal");
setobcreatedby(dstportal, caster);
// link the dst portal
addflag_real(dstportal->flags, F_MAPLINK, caster->cell->map->id, srccell->x, srccell->y, NULL, PERMENANT, B_FALSE, -1);
@ -3367,6 +3398,8 @@ cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, i
maxrange = getspellrange(spellid, power);
if (*targcell) where = *targcell;
while (!done) {
if (where) {
cell_t *newwhere = NULL;