- [+] BUG: lfs are getting map flags!
- [+] Implement a* pathfinding for pets - [+] done - [+] TEST... seems okay so far. - [+] druid spells not showing in starting list. - [+] don't announce noise from unseen things which are attacking the player. - [+] fix crash when no pet location found at start of game. - [+] swap spell levels for warp wood and absorb wood. - [+] only set godprayedto if you got a positive effect. - [+] warp wood should affect wooden lifeforms. - [+] pathfinding for player: - [+] only allow this to explored cells - [+] consider unexplored cells non-walkable. - [+] set f_pathfinding - [+] STOP if we see a monster - [+] never let stamina exceed max. - [+] you can now actually climb when you get the spiderclimb ability but don't have climbing skill
This commit is contained in:
parent
095fb8b7d4
commit
29483cd29f
484
ai.c
484
ai.c
|
@ -23,8 +23,8 @@ extern int playerhasmoved;
|
|||
int wantdb = B_TRUE;
|
||||
|
||||
void addignorecell(lifeform_t *lf, cell_t *c) {
|
||||
if (c) {
|
||||
addflag(lf->flags, F_IGNORECELL, c->x, c->y, NA, NULL);
|
||||
if (c && !lfhasflagval(lf, F_IGNORECELL, c->x, c->y, NA, NULL)) {
|
||||
addtempflag(lf->flags, F_IGNORECELL, c->x, c->y, NA, NULL, 20);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -97,6 +97,7 @@ int aiattack(lifeform_t *lf, lifeform_t *victim, int timelimit) {
|
|||
dblog(".oO { %s setting new target: %s }", lfname, vicname);
|
||||
}
|
||||
|
||||
killflagsofid(lf->flags, F_AIPATH);
|
||||
killflagsofid(lf->flags, F_TARGETLF);
|
||||
killflagsofid(lf->flags, F_TARGETCELL);
|
||||
|
||||
|
@ -146,6 +147,344 @@ int aiattack(lifeform_t *lf, lifeform_t *victim, int timelimit) {
|
|||
return B_FALSE;
|
||||
}
|
||||
|
||||
int calcheuristic(cell_t *c, cell_t *end) {
|
||||
int h,xd,yd;
|
||||
xd = abs(c->x - end->x);
|
||||
yd = abs(c->y - end->y);
|
||||
if (xd > yd) {
|
||||
h = (14*yd) + 10*(xd - yd);
|
||||
} else {
|
||||
h = (14*xd) + 10*(yd - xd);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
// inserts node 'n' into list 'list' (sorted by cost)
|
||||
// returns index of insert position.
|
||||
int insert(node_t *n, node_t *list, int *listcount) {
|
||||
int pos,i;
|
||||
// add it to open list, with parent = node[cur]
|
||||
pos = -1;
|
||||
for (pos = 0; pos < *listcount; pos++) {
|
||||
if (n->cost <= list[pos].cost) {
|
||||
// add here.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// shuffle others up
|
||||
for (i = *listcount; i > pos; i--) {
|
||||
list[i] = list[i-1];
|
||||
}
|
||||
(*listcount)++;
|
||||
// fill in .
|
||||
list[pos] = *n;
|
||||
return pos;
|
||||
}
|
||||
|
||||
int calcg(lifeform_t *lf, cell_t *thiscell, node_t *parent, int dirfromparent) {
|
||||
int fromstart;
|
||||
object_t *o;
|
||||
int dooropen;
|
||||
enum ATTRBRACKET wis = AT_EXHIGH;
|
||||
if (lf) {
|
||||
wis = getattrbracket(getattr(lf, A_WIS), A_WIS, NULL);
|
||||
}
|
||||
if (isorthogonal(dirfromparent)) {
|
||||
fromstart = parent->fromstart + 10;
|
||||
} else {
|
||||
fromstart = parent->fromstart + 14;
|
||||
}
|
||||
|
||||
// closed doors count for more.
|
||||
if (wis >= AT_AVERAGE) {
|
||||
o = hasdoor(thiscell);
|
||||
if (o && isdoor(o, &dooropen) && !dooropen) {
|
||||
fromstart += 10;
|
||||
}
|
||||
}
|
||||
|
||||
// lf's wisdom will affect what is the "best" path
|
||||
if (wis >= AT_GTAVERAGE) {
|
||||
// avoid mud, etc
|
||||
o = hasobwithflag(thiscell->obpile, F_REDUCEMOVEMENT);
|
||||
if (o) {
|
||||
int howmuch;
|
||||
sumflags(o->flags, F_REDUCEMOVEMENT, &howmuch, NULL, NULL);
|
||||
if (howmuch > 0) {
|
||||
fromstart += (10*howmuch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fromstart;
|
||||
}
|
||||
|
||||
// A* algorithm. Returns F_AIPATH flag.
|
||||
flag_t *ai_createpathto(lifeform_t *lf, cell_t *targcell) {
|
||||
char *pathbuf;
|
||||
cell_t *pathcell[MAX_PATHFIND_STEPS];
|
||||
int pathlen = 0;
|
||||
int done = B_FALSE,i,n, first = B_TRUE;
|
||||
node_t open[MAX_PATHFIND_ADJ];
|
||||
node_t closed[MAX_PATHFIND_ADJ];
|
||||
node_t *cur;
|
||||
int nopen = 0,nclosed = 0;
|
||||
int db = B_FALSE;
|
||||
char lfname[BUFLEN];
|
||||
flag_t *newf;
|
||||
|
||||
if (!db && lfhasflag(lf, F_DEBUG)) db = B_TRUE;
|
||||
|
||||
real_getlfname(lf, lfname, NULL, B_SHOWALL, B_CURRACE);
|
||||
|
||||
if (lf->cell->map != targcell->map) {
|
||||
if (db) dblog("%s: pathfind destination on different level", lfname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (db) dblog("%s pathfind - finding path from %d,%d to %d,%d\n",lfname, lf->cell->x,lf->cell->y,
|
||||
targcell->x,targcell->y);
|
||||
|
||||
// add starting cell to open list
|
||||
open[0].c = lf->cell;
|
||||
open[0].fromstart = 0;
|
||||
open[0].heur = calcheuristic(lf->cell, targcell);
|
||||
open[0].cost = open[0].fromstart + open[0].cost;
|
||||
open[0].parent = NULL;
|
||||
nopen = 1;
|
||||
|
||||
// NEED: calccosts(node, parentcell, endcell);
|
||||
|
||||
while (!done) {
|
||||
// if open list empty?
|
||||
if (!nopen) {
|
||||
// if so, there is NO path. fail.
|
||||
if (db) dblog("%s pathfind - open list is empty. FAILED.",lfname);
|
||||
return NULL;
|
||||
}
|
||||
// find lowest COST in open list. this is cur.
|
||||
// move node[cur] to closed list
|
||||
closed[nclosed] = open[0];
|
||||
cur = &closed[nclosed];
|
||||
nclosed++;
|
||||
for (i = 0; i < nopen-1; i++) {
|
||||
open[i] = open[i+1];
|
||||
}
|
||||
nopen--;
|
||||
//if (db) dblog("%s pathfind - lowest cost node on openlist is %d,%d",lfname,cur->c->x, cur->c->y);
|
||||
// is node[cur] the target cell?
|
||||
if (cur->c == targcell) {
|
||||
// if so, we've found a path. now need to populate
|
||||
//if (db) dblog("%s pathfind - at target cell - success!",lfname);
|
||||
done = B_TRUE;
|
||||
} else {
|
||||
// for "adjcell" in 8 squares around it:
|
||||
for (i = DC_N; i <= DC_NW; i++) {
|
||||
cell_t *adjcell;
|
||||
int walkable,found = B_FALSE, ok = B_FALSE;
|
||||
enum ERROR whynot;
|
||||
adjcell = getcellindir(cur->c, i);
|
||||
if (!adjcell) continue;
|
||||
|
||||
//if (db) dblog("%s pathfind - checking %s",lfname, getdirnameshort(i));
|
||||
// already on closed list?
|
||||
for (n = 0; n < nclosed; n++) {
|
||||
if (closed[n].c == adjcell) {
|
||||
found = B_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
// already on closed list. ignore.
|
||||
//if (db) dblog(" %s (%d,%d): already on closed list. ignore.",getdirnameshort(i),
|
||||
// adjcell->x, adjcell->y);
|
||||
continue;
|
||||
}
|
||||
|
||||
walkable = cellwalkable(lf, adjcell, &whynot);
|
||||
|
||||
ok = B_FALSE;
|
||||
if (lfhasflagval(lf, F_IGNORECELL, adjcell->x, adjcell->y, NA, NULL)) {
|
||||
ok = B_FALSE;
|
||||
} else if (walkable) {
|
||||
ok = B_TRUE;
|
||||
} else if (celldangerous(lf, adjcell, B_TRUE, NULL) && haslos(lf, adjcell)) {
|
||||
// ignore dangerous cells only if we can see them.
|
||||
ok = B_FALSE;
|
||||
} else {
|
||||
if (whynot == E_LFINWAY) {
|
||||
if (isadjacent(adjcell, lf->cell)) {
|
||||
ok = B_FALSE;
|
||||
} else {
|
||||
ok = B_TRUE;
|
||||
}
|
||||
} else if (whynot == E_DOORINWAY) {
|
||||
if (canopendoors(lf)) {
|
||||
ok = B_TRUE;
|
||||
} else {
|
||||
ok = B_FALSE;
|
||||
}
|
||||
} else {
|
||||
ok = B_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
int openpos = -1;
|
||||
// adjcell is walkable.
|
||||
for (n = 0; n < nopen; n++) {
|
||||
if (open[n].c == adjcell) {
|
||||
openpos = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (openpos != -1) {
|
||||
int newfromstart;
|
||||
node_t temp;
|
||||
// adjcell is already on open list
|
||||
//if (db) dblog(" %s (%d,%d): on open list (position %d).",getdirnameshort(i),
|
||||
// adjcell->x, adjcell->y, openpos);
|
||||
|
||||
// recalc fromstart of adjcell using node[cur] as a parent.
|
||||
newfromstart = calcg(lf, open[openpos].c, cur, i);
|
||||
if (newfromstart < open[openpos].fromstart) {
|
||||
// path through node[cur] is better.
|
||||
//if (db) dblog(" %s (%d,%d): better cost - recalcing.",
|
||||
// getdirnameshort(i),
|
||||
// adjcell->x, adjcell->y);
|
||||
|
||||
// change parent of adjcell to node[cur]
|
||||
// and recalc new costings (and re-sort list)
|
||||
temp = open[openpos];
|
||||
temp.parent = cur;
|
||||
assert(isadjacent(temp.c, temp.parent->c));
|
||||
temp.fromstart = calcg(lf, temp.c, temp.parent, i);
|
||||
temp.heur = calcheuristic(temp.c, targcell);
|
||||
temp.cost = temp.fromstart + temp.heur;
|
||||
|
||||
// remove adjcell from open list.
|
||||
for (n = openpos; n < nopen; n++) {
|
||||
open[n] = open[n+1];
|
||||
}
|
||||
nopen--;
|
||||
// re-add adjcell at correct pos;
|
||||
insert(&temp, open, &nopen);
|
||||
}
|
||||
} else {
|
||||
// not on open list
|
||||
node_t temp;
|
||||
|
||||
//if (db) dblog(" %s (%d,%d): not on openlist. inserting.",
|
||||
// getdirnameshort(i),
|
||||
// adjcell->x, adjcell->y);
|
||||
// calc costs
|
||||
temp.c = adjcell;
|
||||
temp.parent = cur;
|
||||
assert(isadjacent(temp.c, temp.parent->c));
|
||||
temp.fromstart = calcg(lf, temp.c, temp.parent, i);
|
||||
temp.heur = calcheuristic(adjcell, targcell);
|
||||
temp.cost = temp.fromstart + temp.heur;
|
||||
|
||||
insert(&temp, open, &nopen);
|
||||
}
|
||||
} else {
|
||||
// !walkable - ignore it.
|
||||
//if (db) dblog(" %s (%d,%d): not walkable - ignoring.",
|
||||
// getdirnameshort(i),
|
||||
// adjcell->x, adjcell->y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// work backwards from node[cur] (ie. targcell) following parents.
|
||||
// populate path and return
|
||||
if (db) dblog("%s - found path!\n",lfname);
|
||||
while (cur) {
|
||||
pathcell[pathlen++] = cur->c;
|
||||
if (pathlen >= MAX_PATHFIND_STEPS) {
|
||||
if (db) dblog("%s pathfind - path too long (> %d). FAILED.",MAX_PATHFIND_STEPS);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cur = cur->parent;
|
||||
}
|
||||
|
||||
pathbuf = malloc(pathlen*6*sizeof(char));
|
||||
strcpy(pathbuf, "");
|
||||
|
||||
for (i = pathlen-1; i >= 0 ; i--) {
|
||||
char smallbuf[BUFLENTINY];
|
||||
// don't include starting cell
|
||||
if (pathcell[i] == lf->cell) continue;
|
||||
|
||||
sprintf(smallbuf, "%s%d,%d",first ? "" : "-", pathcell[i]->x, pathcell[i]->y);
|
||||
first = B_FALSE;
|
||||
strcat(pathbuf, smallbuf);
|
||||
}
|
||||
if (db) dblog("* %s - path takes %d steps. ", lfname, pathlen);
|
||||
if (db) dblog("* %s - pathbuf: [%s] ", lfname, pathbuf);
|
||||
newf = addflag(lf->flags, F_AIPATH, targcell->x, targcell->y, NA, pathbuf);
|
||||
free(pathbuf);
|
||||
return newf;
|
||||
}
|
||||
|
||||
// f is a flag of type F_AIPATH
|
||||
//
|
||||
// returns the next cell in the path, and removes next cell
|
||||
// from the list.
|
||||
//
|
||||
// if there are no more cells in the path, remove the path.
|
||||
cell_t *ai_getnextcellinpath(lifeform_t *lf) {
|
||||
cell_t *c;
|
||||
flag_t *f;
|
||||
char *loctext;
|
||||
char *p,buf[BUFLEN];
|
||||
int x,y;
|
||||
|
||||
f = lfhasflag(lf, F_AIPATH);
|
||||
if (!f) return NULL;
|
||||
|
||||
loctext = strdup(f->text);
|
||||
p = loctext;
|
||||
|
||||
p = readuntil(buf, loctext,',');
|
||||
x = atoi(buf);
|
||||
p = readuntil(buf, p,'-');
|
||||
y = atoi(buf);
|
||||
|
||||
free(loctext);
|
||||
|
||||
c = getcellat(lf->cell->map, x,y);
|
||||
return c;
|
||||
}
|
||||
|
||||
// returns TRUE on error
|
||||
int ai_popnextcellinpath(lifeform_t *lf) {
|
||||
flag_t *f;
|
||||
char *loctext;
|
||||
char *p,buf[BUFLEN];
|
||||
|
||||
f = lfhasflag(lf, F_AIPATH);
|
||||
if (!f) return B_TRUE;
|
||||
|
||||
loctext = strdup(f->text);
|
||||
p = loctext;
|
||||
p = readuntil(buf, loctext,',');
|
||||
p = readuntil(buf, p,'-');
|
||||
|
||||
if (strlen(p)) {
|
||||
free(f->text);
|
||||
f->text = strdup(p);
|
||||
} else {
|
||||
killflag(f);
|
||||
}
|
||||
|
||||
free(loctext);
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
enum OBTYPE aigetattackspell(lifeform_t *lf, lifeform_t *victim) {
|
||||
flag_t *retflag[MAXCANDIDATES];
|
||||
int nretflags = 0;
|
||||
|
@ -304,6 +643,14 @@ cell_t *aigetlastknownpos(lifeform_t *lf, lifeform_t *target, int *lastx, int *l
|
|||
if (lasty) *lasty = NA;
|
||||
if (lastdir) *lastdir = D_NONE;
|
||||
|
||||
// if within scent range... we 'magically' know their location.
|
||||
if (getcelldist(lf->cell, target->cell) <= getsmellrange(lf)) {
|
||||
if (lastx) *lastx = target->cell->x;
|
||||
if (lasty) *lasty = target->cell->y;
|
||||
if (lastdir) *lastdir = D_NONE;
|
||||
return target->cell;
|
||||
}
|
||||
|
||||
// do we remember the player's last known location ?
|
||||
f = ispetortarget(lf, target);
|
||||
if (f) {
|
||||
|
@ -782,6 +1129,7 @@ flag_t *aigoto(lifeform_t *lf, cell_t *c, enum MOVEREASON why, void *data, int t
|
|||
|
||||
|
||||
// kill previous target flags.
|
||||
killflagsofid(lf->flags, F_AIPATH);
|
||||
killflagsofid(lf->flags, F_TARGETLF);
|
||||
killflagsofid(lf->flags, F_TARGETCELL);
|
||||
|
||||
|
@ -1488,8 +1836,7 @@ int ai_movement(lifeform_t *lf) {
|
|||
}
|
||||
|
||||
if (valid) {
|
||||
aimovetotargetcell(lf, f);
|
||||
return B_TRUE;
|
||||
return aimovetotargetcell(lf, f);
|
||||
} else {
|
||||
killflag(f);
|
||||
}
|
||||
|
@ -1788,7 +2135,6 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) {
|
|||
// try to get to our ideal range from them.
|
||||
if (db) dblog(".oO { i am at distance %d, want to be at %d-%d }", dist, wantdistmin, wantdistmax);
|
||||
if (dist > wantdistmax) {
|
||||
|
||||
// want to move but our race doesn't move?
|
||||
if (lfhasflag(lf, F_DOESNTMOVE)) {
|
||||
if (db) dblog(".oO { want to move towards target but have f_doesntmove - abandoning target. }");
|
||||
|
@ -1796,9 +2142,7 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) {
|
|||
return B_TRUE;
|
||||
}
|
||||
|
||||
if (db) {
|
||||
dblog(".oO { moving towards target. }");
|
||||
}
|
||||
if (db) dblog(".oO { moving towards target. }");
|
||||
|
||||
// do we need to sprint got catch up?
|
||||
if (lfhasflag(target, F_SPRINTING) && !lfhasflag(lf, F_SPRINTING) && cancast(lf, OT_A_SPRINT, NULL)) {
|
||||
|
@ -1806,7 +2150,7 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) {
|
|||
}
|
||||
|
||||
if (!movetowards(lf, target->cell, DT_ORTH, B_FALSE)) {
|
||||
dblog(".oO { successfully moved towards target. }");
|
||||
if (db) dblog(".oO { successfully moved towards target. }");
|
||||
turntoface(lf, target->cell);
|
||||
// success
|
||||
return B_FALSE;
|
||||
|
@ -1948,7 +2292,7 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) {
|
|||
}
|
||||
|
||||
|
||||
void aimovetotargetcell(lifeform_t *lf, flag_t *f) {
|
||||
int aimovetotargetcell(lifeform_t *lf, flag_t *f) {
|
||||
int x,y;
|
||||
cell_t *c,*origc;
|
||||
int db = B_FALSE;
|
||||
|
@ -1963,55 +2307,92 @@ void aimovetotargetcell(lifeform_t *lf, flag_t *f) {
|
|||
origc = lf->cell;
|
||||
c = getcellat(lf->cell->map, x, y);
|
||||
if (c) {
|
||||
// try to move towards the cell
|
||||
if (movetowards(lf, c, DT_ORTH, B_FALSE )) {
|
||||
// couldn't move towards it for some reason.
|
||||
// so stop trying.
|
||||
if (db) dblog(".oO { couldn't walk towards f_targetcell. abandoning it. }");
|
||||
killflag(f);
|
||||
// remember NOT to target this one.
|
||||
addignorecell(lf, c);
|
||||
} else {
|
||||
int turned = B_FALSE;
|
||||
if (lf->cell == origc) {
|
||||
if (db) dblog(".oO { turned to face f_targetcell. (still at %d,%d) }",lf->cell->x, lf->cell->y);
|
||||
turned = B_TRUE;
|
||||
} else {
|
||||
if (db) dblog(".oO { successfully walked towards f_targetcell. arrived at %d,%d }",lf->cell->x, lf->cell->y);
|
||||
flag_t *pathf = NULL;
|
||||
if (!haslof(lf->cell, c, LOF_WALLSTOP, NULL)) {
|
||||
// if we DONT have LOF to the target cell, use
|
||||
// a pathfinding algorithm.
|
||||
// do we ahv an existing path?
|
||||
pathf = lfhasflag(lf, F_AIPATH);
|
||||
if (!pathf) {
|
||||
// if we DONT have a direct path, then pathfind.
|
||||
pathf = ai_createpathto(lf, c);
|
||||
}
|
||||
// moved towards it.
|
||||
// reset lifetime
|
||||
f->lifetime = aigetchasetime(lf);
|
||||
|
||||
// are we there yet?
|
||||
if (lf->cell == c) {
|
||||
// yes. remove target cell
|
||||
if (db) dblog(".oO { arrived at f_targetcell. removing. }");
|
||||
if (f->val[2] == MR_LF) {
|
||||
lifeform_t *targlf;
|
||||
// if we were chasing someone, keep looking
|
||||
// for them.
|
||||
targlf = findlf(lf->cell->map, atoi(f->text));
|
||||
if (targlf) {
|
||||
if (db) dblog(".oO { resuming pursuit of %s }", targlf->race->name);
|
||||
addflag(lf->flags, F_TARGETLF, targlf->id, NA, NA, NULL);
|
||||
}
|
||||
|
||||
}
|
||||
killflag(f);
|
||||
if (pathf) {
|
||||
c = ai_getnextcellinpath(lf);
|
||||
} else {
|
||||
if (!turned) {
|
||||
turntoface(lf, c);
|
||||
}
|
||||
// couldn't find a path there...
|
||||
// just try to move directly towards it.
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (db) dblog(".oO { f_targetcell doesn't exist. abandoning. }");
|
||||
// if we _DO_ have lof to the cell, we'll just walk direclty towards it.
|
||||
|
||||
if (c) {
|
||||
// try to move towards the cell
|
||||
if (movetowards(lf, c, DT_ORTH, B_FALSE )) {
|
||||
// couldn't move towards it for some reason.
|
||||
// so stop trying.
|
||||
if (db) dblog(".oO { couldn't walk towards f_targetcell. abandoning it. }");
|
||||
killflag(f);
|
||||
// remember NOT to target this one.
|
||||
addignorecell(lf, c);
|
||||
c = NULL;
|
||||
} else {
|
||||
int turned = B_FALSE;
|
||||
if (lf->cell == origc) {
|
||||
if (db) dblog(".oO { turned to face f_targetcell. (still at %d,%d) }",lf->cell->x, lf->cell->y);
|
||||
turned = B_TRUE;
|
||||
} else {
|
||||
if (db) dblog(".oO { successfully walked towards f_targetcell. arrived at %d,%d }",lf->cell->x, lf->cell->y);
|
||||
}
|
||||
|
||||
if (pathf && (lf->cell == c)) {
|
||||
ai_popnextcellinpath(lf);
|
||||
}
|
||||
|
||||
// moved towards it.
|
||||
// reset lifetime
|
||||
f->lifetime = aigetchasetime(lf);
|
||||
|
||||
// are we there yet?
|
||||
if (lf->cell == c) {
|
||||
// yes. remove target cell
|
||||
if (db) dblog(".oO { arrived at f_targetcell. removing. }");
|
||||
if (f->val[2] == MR_LF) {
|
||||
lifeform_t *targlf;
|
||||
// if we were chasing someone, keep looking
|
||||
// for them.
|
||||
targlf = findlf(lf->cell->map, atoi(f->text));
|
||||
if (targlf) {
|
||||
if (db) dblog(".oO { resuming pursuit of %s }", targlf->race->name);
|
||||
addflag(lf->flags, F_TARGETLF, targlf->id, NA, NA, NULL);
|
||||
}
|
||||
|
||||
}
|
||||
killflag(f);
|
||||
} else {
|
||||
if (!turned) {
|
||||
turntoface(lf, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// !c
|
||||
}
|
||||
}
|
||||
|
||||
if (!c) {
|
||||
if (db) dblog(".oO { f_targetcell doesn't exist anymore. moving randomly. }");
|
||||
// destination doesn't exist!
|
||||
killflag(f);
|
||||
// remember NOT to target this one.
|
||||
addignorecell(lf, c);
|
||||
loseaitargets(lf);
|
||||
|
||||
// move randomly now.
|
||||
dorandommove(lf, B_NOBADMOVES, B_TRUE, B_FALSE); // this function will call rest() if we cant move
|
||||
}
|
||||
// success
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
int aipickup(lifeform_t *lf, object_t *o) {
|
||||
|
@ -3130,6 +3511,7 @@ int lookforobs(lifeform_t *lf) {
|
|||
|
||||
int loseaitargets(lifeform_t *lf) {
|
||||
int donesomething = B_FALSE;
|
||||
if (killflagsofid(lf->flags, F_AIPATH)) donesomething = B_TRUE;
|
||||
if (killflagsofid(lf->flags, F_TARGETLF)) donesomething = B_TRUE;
|
||||
if (killflagsofid(lf->flags, F_TARGETCELL)) donesomething = B_TRUE;
|
||||
return donesomething;
|
||||
|
|
7
ai.h
7
ai.h
|
@ -2,6 +2,11 @@
|
|||
|
||||
void addignorecell(lifeform_t *lf, cell_t *c);
|
||||
int aiattack(lifeform_t *lf, lifeform_t *victim, int timelimit);
|
||||
int calcheuristic(cell_t *c, cell_t *end);
|
||||
int calcg(lifeform_t *lf, cell_t *thiscell, node_t *parent, int dirfromparent);
|
||||
flag_t *ai_createpathto(lifeform_t *lf, cell_t *targcell);
|
||||
cell_t *ai_getnextcellinpath(lifeform_t *lf);
|
||||
int ai_popnextcellinpath(lifeform_t *lf);
|
||||
enum OBTYPE aigetattackspell(lifeform_t *lf, lifeform_t *victim);
|
||||
enum OBTYPE aigetfleespell(lifeform_t *lf);
|
||||
int aigetchasetime(lifeform_t *lf);
|
||||
|
@ -21,7 +26,7 @@ int ai_movement(lifeform_t *lf);
|
|||
int ai_premovement(lifeform_t *lf);
|
||||
flag_t *aihastarget(lifeform_t *lf);
|
||||
int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack);
|
||||
void aimovetotargetcell(lifeform_t *lf, flag_t *f);
|
||||
int aimovetotargetcell(lifeform_t *lf, flag_t *f);
|
||||
int aipickup(lifeform_t *lf, object_t *o);
|
||||
int aipickupok(lifeform_t *lf, object_t *o);
|
||||
int aiobok(lifeform_t *lf, object_t *o, lifeform_t *target);
|
||||
|
|
13
attack.c
13
attack.c
|
@ -201,6 +201,7 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
|
|||
}
|
||||
|
||||
stoprunning(lf);
|
||||
stoppathfinding(lf);
|
||||
|
||||
// anyone there? if so just attack.
|
||||
if (c->lf) {
|
||||
|
@ -330,7 +331,7 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
|
|||
real_getobname(priwep, wepname, priwep->amt, B_NOPREMODS,
|
||||
B_NOCONDITION, B_BLINDADJUST,
|
||||
B_NOBLESSINGS, B_NOUSED, B_NOSHOWALL);
|
||||
snprintf(buf, BUFLEN, "Attacking %s might rust your %s - proceed anyway?",victimname, wepname);
|
||||
snprintf(buf, BUFLEN, "Attacking %s might rust your %s - proceed anyway?",victimname, noprefix(wepname));
|
||||
if (!warnabout(buf)) {
|
||||
return B_TRUE;
|
||||
}
|
||||
|
@ -1545,7 +1546,12 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
|
|||
}
|
||||
|
||||
// make noise
|
||||
noise(lf->cell, lf, NC_FIGHTING, SV_SHOUT, "fighting.", NULL);
|
||||
// UNLESS this fighting involved the player.
|
||||
// This is a hack - should really move this check into noise(), and
|
||||
// implement some way to tell whether a lf is currently fighting the player.
|
||||
if (!isplayer(lf) && !isplayer(victim)) {
|
||||
noise(lf->cell, lf, NC_FIGHTING, SV_SHOUT, "fighting.", NULL);
|
||||
}
|
||||
|
||||
if (backstab) {
|
||||
practice(lf, SK_BACKSTAB, 1);
|
||||
|
@ -2165,6 +2171,9 @@ int check_for_block(lifeform_t *lf, lifeform_t *victim, int dam, enum DAMTYPE da
|
|||
int nshields,i;
|
||||
|
||||
if (lf && !cansee(victim, lf)) return B_FALSE;
|
||||
if (lfhasflag(victim, F_STUNNED) || !hasfreeaction(victim)) {
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
// need stamina to block
|
||||
if (!getstamina(victim)) return B_FALSE;
|
||||
|
|
40
data.c
40
data.c
|
@ -165,9 +165,11 @@ void initcommands(void) {
|
|||
addcommand(CMD_TURN_SW, CH_TURN_SW, "Turn to face Southwest.");
|
||||
addcommand(CMD_TURN_W, CH_TURN_W, "Turn to face West.");
|
||||
addcommand(CMD_TURN_NW, CH_TURN_NW, "Turn to face Northwest.");
|
||||
// Actions
|
||||
addcommand(CMD_UP, '<', "Go up stairs.");
|
||||
addcommand(CMD_DOWN, '>', "Go down stairs, enter a shop/portal.");
|
||||
addcommand(CMD_GO, 'G', "Go to a set position (pathfind).");
|
||||
// Actions
|
||||
addcommand(CMD_AGAIN, 'g', "Repeat last action.");
|
||||
addcommand(CMD_REST, '.', "Rest once.");
|
||||
addcommand(CMD_PICKUP, ',', "Pick up something from the ground.");
|
||||
addcommand(CMD_CLOSE, 'c', "Close a door.");
|
||||
|
@ -4604,11 +4606,13 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL);
|
||||
// l2
|
||||
addot(OT_S_ABSORBWOOD, "absorb metal", "Destroys nearby wooden objects to boost caster's mana. Does NOT affect carried or equipped items.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
|
||||
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines the maximum amount of wood which can be absorbed.");
|
||||
addot(OT_S_WARPWOOD, "warp wood", "Causes ^bpower^nd4 damage to all wooden creatures or objects in the target area.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
|
||||
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_MPCOST, 0, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_TARGETTEDSPELL, TT_OBJECT, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
|
||||
addot(OT_S_BARKSKIN, "barkskin", "Covers the caster with a skin of bark, reducing damage but making them vulnerable to fire.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
|
||||
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
|
||||
|
@ -4650,13 +4654,11 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_MAXPOWER, 5, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL);
|
||||
addot(OT_S_WARPWOOD, "warp wood", "Causes damage to all wooden objects in the target area.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
|
||||
addot(OT_S_ABSORBWOOD, "absorb wood", "Destroys nearby wooden objects to boost caster's mana. Does NOT affect carried or equipped items.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
|
||||
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines the maximum amount of wood which can be absorbed.");
|
||||
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_TARGETTEDSPELL, TT_OBJECT, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
|
||||
addflag(lastot->flags, F_MPCOST, 0, NA, NA, NULL);
|
||||
// l3
|
||||
addot(OT_S_EVAPORATE, "evaporate", "Instantly converts all water in the given area into scalding steam (including potions).", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
|
||||
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The spell's power determines the amount of water affected.");
|
||||
|
@ -5441,6 +5443,10 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
|
||||
addot(OT_A_LEVELUP, "levelup", "Bestow the given xp level.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY);
|
||||
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
|
||||
addot(OT_A_PATHFIND, "pathfind", "Find a path to the given cell.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY);
|
||||
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
|
||||
addot(OT_A_PETIFY, "petify", "Make a monster into your pet.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY);
|
||||
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
|
||||
addot(OT_S_WISH, "wish", "Grants the caster any item of their choice. Beware - casting this powerful spell will reduce the caster's hit points by 50%.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
|
||||
addflag(lastot->flags, F_SPELLLEVEL, 6, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINE, NA, NA, NULL);
|
||||
|
@ -5547,7 +5553,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJSELF, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_STAMCOST, 4, NA, NA, NULL);
|
||||
addot(OT_A_INSPECT, "inspect item", "Try to identify an unknown scroll, book, wand or ring from your pack.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY);
|
||||
addot(OT_A_INSPECT, "inspect item", "Use your Lore skills to identify an unknown item from your pack.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY);
|
||||
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
|
||||
addot(OT_A_IRONFIST, "iron fist", "Channel all your remaining stamina into one almighty blow.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY);
|
||||
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
|
||||
|
@ -6972,7 +6978,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_GLYPH, C_WHITE, ',', NA, NULL);
|
||||
addflag(lastot->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL);
|
||||
addflag(lastot->flags, F_RARITY, H_CAVE, NA, RR_COMMON, NULL);
|
||||
addflag(lastot->flags, F_DIMONWALK, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_DIMONDISTURB, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_PRODUCESLIGHT, 3, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
||||
|
||||
|
@ -6980,7 +6986,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_GLYPH, C_YELLOW, ',', NA, NULL);
|
||||
addflag(lastot->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL);
|
||||
addflag(lastot->flags, F_RARITY, H_CAVE, NA, RR_UNCOMMON, NULL);
|
||||
addflag(lastot->flags, F_DIMONWALK, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_DIMONDISTURB, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_PRODUCESLIGHT, 5, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
||||
|
||||
|
@ -11700,6 +11706,7 @@ void initrace(void) {
|
|||
addflag(lastrace->flags, F_STARTSKILL, SK_THIEVERY, PR_SKILLED, NA, NULL);
|
||||
addflag(lastrace->flags, F_STAYINROOM, NA, B_NOCHASE, NA, NULL); // stay in our starting room
|
||||
addflag(lastrace->flags, F_MORALE, 2, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_GENDER, G_FEMALE, NA, NA, NULL);
|
||||
|
||||
addrace(R_DJINNI, "genie", 65, 'Y', C_YELLOW, MT_FLESH, RC_MAGIC, "Genies are powerful air spirits. They resemble richly dressed humans floating on a cone of whirling air.");
|
||||
setbodytype(lastrace, BT_HUMANOID);
|
||||
|
@ -12174,7 +12181,7 @@ void initrace(void) {
|
|||
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 4, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTATT, A_STR, AT_AVERAGE, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_LTAVERAGE, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTATT, A_AGI, AT_GTAVERAGE, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTATT, A_AGI, AT_AVERAGE, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTATT, A_CON, AT_RANDOM, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTATT, A_WIS, AT_LOW, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTATT, A_CHA, AT_LOW, NA, NULL);
|
||||
|
@ -14897,7 +14904,7 @@ void initrace(void) {
|
|||
addflag(lastrace->flags, F_MAXATTACKS, 1, 2, NA, NULL);
|
||||
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 2, NA, NULL);
|
||||
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 2, NA, NULL);
|
||||
addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 6, NA, NULL);
|
||||
addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 4, NA, NULL);
|
||||
addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 2, NA, "growls^growling");
|
||||
addflag(lastrace->flags, F_SEEINDARK, 5, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_MORALE, 6, NA, NA, NULL);
|
||||
|
@ -19155,6 +19162,7 @@ void initskills(void) {
|
|||
addskilldesc(SK_LORE_ARCANA, PR_EXPERT, "^gYou can now recognise uncommon wands.", B_TRUE);
|
||||
addskilldesc(SK_LORE_ARCANA, PR_MASTER, "^gYou can now recognise rare wands.", B_TRUE);
|
||||
addskill(SK_LORE_CHEMISTRY, "Lore:Chemistry", "Allows you a chance of recognising potions.", 5);
|
||||
free(lastskill->shortname); lastskill->shortname = strdup("Lore:Chem");
|
||||
addskilldesc(SK_LORE_CHEMISTRY, PR_NOVICE, "^gYou can attempt to identify potions with the 'inspect' ability.^n", B_FALSE);
|
||||
addskillabil(SK_LORE_CHEMISTRY, PR_NOVICE, OT_A_INSPECT, NA, NULL, B_FALSE);
|
||||
addskilldesc(SK_LORE_CHEMISTRY, PR_BEGINNER, "^gYou can now recognise very common potions.", B_TRUE);
|
||||
|
@ -19167,7 +19175,7 @@ void initskills(void) {
|
|||
addskilldesc(SK_LORE_DEMONS, PR_SKILLED, "^gEvery 50 turns you can summon demons.", B_FALSE);
|
||||
addskillabil(SK_LORE_DEMONS, PR_SKILLED, OT_S_SUMMONDEMON, 50, "pw:1", B_FALSE);
|
||||
addskill(SK_LORE_HUMANOID, "Lore:Humanoid", "Determines your knowledge about humanoid (bipedal) creatures.", 5);
|
||||
addskill(SK_LORE_LANGUAGE, "Lore:Linguistics", "Allows you a chance of recognising scrolls and books.", 5);
|
||||
addskill(SK_LORE_LANGUAGE, "Lore:Language", "Allows you a chance of recognising scrolls and books.", 5);
|
||||
addskilldesc(SK_LORE_LANGUAGE, PR_NOVICE, "^gYou can attempt to identify scrolls/books with the 'inspect' ability.^n", B_FALSE);
|
||||
addskillabil(SK_LORE_LANGUAGE, PR_NOVICE, OT_A_INSPECT, NA, NULL, B_FALSE);
|
||||
addskillabil(SK_LORE_LANGUAGE, PR_ADEPT, OT_A_STUDYSCROLL, NA, NULL, B_TRUE);
|
||||
|
@ -19318,7 +19326,7 @@ void initskills(void) {
|
|||
|
||||
snprintf(buf, BUFLEN, "^gYou now have common knowledge about %s.^n", rc->pluralname);
|
||||
addskilldesc(sk->id, PR_NOVICE, buf, B_TRUE);
|
||||
snprintf(buf, BUFLEN, "^gYou now know about the powers/abilities of %s.^n", rc->pluralname);
|
||||
snprintf(buf, BUFLEN, "^gYou now know about the abilities of %s.^n", rc->pluralname);
|
||||
addskilldesc(sk->id, PR_BEGINNER, buf, B_TRUE);
|
||||
snprintf(buf, BUFLEN, "^gYou have now comprehensively studied %s.^n", rc->pluralname);
|
||||
addskilldesc(sk->id, PR_ADEPT, buf, B_TRUE);
|
||||
|
|
BIN
data/hiscores.db
BIN
data/hiscores.db
Binary file not shown.
29
defs.h
29
defs.h
|
@ -223,6 +223,9 @@
|
|||
|
||||
#define MAX_MAPW 80
|
||||
#define MAX_MAPH 30
|
||||
#define MAX_PATHFIND_ADJ (MAX_MAPW*MAX_MAPH*10)
|
||||
#define MAX_PATHFIND_STEPS (MAX_MAPW*MAX_MAPH)
|
||||
|
||||
|
||||
#define MAXPILEOBS 52
|
||||
#define MAXRANDOMOBCANDIDATES 100
|
||||
|
@ -1913,6 +1916,8 @@ enum OBTYPE {
|
|||
OT_A_BLINDALL,
|
||||
OT_S_CONFISCATE,
|
||||
OT_A_DEBUG,
|
||||
OT_A_PATHFIND,
|
||||
OT_A_PETIFY,
|
||||
OT_A_ENHANCE,
|
||||
OT_A_LEARN,
|
||||
OT_A_LEVELUP,
|
||||
|
@ -2686,10 +2691,12 @@ enum FLAG {
|
|||
F_CAUSESCOUGH, // being in this ob's cell will make you cough unless
|
||||
// immune to gas.
|
||||
// v0 = con skillcheck difficulty.
|
||||
F_DIMONWALK, // when a lf walks on this ob, its f_produceslight
|
||||
F_DIMONDISTURB, // when a lf walks on this ob, its f_produceslight
|
||||
// flag v0 reduces by one.
|
||||
// if it gets to 0 (or doesnt have produceslight),
|
||||
// the object will vanish.
|
||||
//
|
||||
// same happens if object is removed from the ground.
|
||||
F_BLOCKSVIEW, // if v0 = true, cannot see past this
|
||||
// if v0 > 0, reduces your vision by v0.
|
||||
// if v1 = true then don't block sight if you are
|
||||
|
@ -3482,6 +3489,11 @@ enum FLAG {
|
|||
// from pet's master
|
||||
F_FEIGNFOOLEDBY, // lf shouldn't attack lf id v0 because they
|
||||
// are feigning death
|
||||
F_AIPATH, // text = list of coordinates for ai path,
|
||||
// in form:
|
||||
// x,y-x,y-x,y-x,y...
|
||||
//
|
||||
// v0/v1 = x/y of end cell
|
||||
F_TARGETLF, // lf will attack lfid v0. lastknown x/y is v1/v2
|
||||
// optional text is last known movement dir.
|
||||
F_IGNORECELL, // won't accept targetcells of v0=x v1=y
|
||||
|
@ -3498,7 +3510,7 @@ enum FLAG {
|
|||
// this lf run away.
|
||||
|
||||
// TEMP FLAGS
|
||||
F_KILLEDBYPLAYER, // did the player kill this lf?
|
||||
F_KILLEDBYPLAYER, // did the player (or an ally) kill this lf?
|
||||
// monster noise flags
|
||||
F_WALKVERB, // text is verb for moving. 'walk' 'slither'
|
||||
// 'bounce' 'hop' etc
|
||||
|
@ -3856,6 +3868,8 @@ enum FLAG {
|
|||
F_XRAYVIS, //val0=num of walls we can see through
|
||||
F_CANSEETHROUGHMAT, //val0=kind of material you can see through
|
||||
F_CANSEETHROUGHLF, // larger lifeforms don't block los for us
|
||||
F_PATHFINDING, // you are following a path via 'G'
|
||||
// to coords v0,v1 on mapid v2
|
||||
F_SPRINTING, // you are sprinting.
|
||||
F_WINDSHIELD,// has a windshield protecting against missiles of speed
|
||||
// v0 or lower.
|
||||
|
@ -4202,6 +4216,7 @@ enum COMMAND {
|
|||
CMD_TURN_W,
|
||||
CMD_TURN_NW,
|
||||
//
|
||||
CMD_AGAIN,
|
||||
CMD_AIM,
|
||||
CMD_CLOSE,
|
||||
CMD_COMMS,
|
||||
|
@ -4212,6 +4227,7 @@ enum COMMAND {
|
|||
CMD_FIRE,
|
||||
CMD_FIRENEW,
|
||||
CMD_FORCEATTACK,
|
||||
CMD_GO,
|
||||
CMD_GUNRELOAD,
|
||||
CMD_HELP,
|
||||
CMD_INFOARMOUR,
|
||||
|
@ -5003,6 +5019,7 @@ typedef struct choice_s {
|
|||
char *longdesc; // what to display once you've selected this
|
||||
void *data;
|
||||
int heading;
|
||||
int hilite;
|
||||
int shortcutslot; // used when selecting spells/abilities
|
||||
int valid; // used in askchoicestr
|
||||
} choice_t;
|
||||
|
@ -5050,8 +5067,16 @@ typedef struct prompt_s {
|
|||
int selection;
|
||||
int nchoices;
|
||||
int maycancel;
|
||||
int hilite;
|
||||
} prompt_t;
|
||||
|
||||
// for a* pathfinding
|
||||
typedef struct node_s {
|
||||
struct cell_s *c;
|
||||
struct node_s *parent;
|
||||
int fromstart, heur, cost;
|
||||
} node_t;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
14
flag.c
14
flag.c
|
@ -73,6 +73,10 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
|
|||
known = B_KNOWN;
|
||||
}
|
||||
|
||||
if (fp->owner && (id == F_VAULTISPLAYERSTART)) {
|
||||
dblog("added vaultisplayerstart");
|
||||
}
|
||||
|
||||
if (id == F_INTERRUPTED) {
|
||||
if (fp->owner == player) {
|
||||
dblog("player got interrupted");
|
||||
|
@ -562,6 +566,16 @@ int countflagsofid(flagpile_t *fp, enum FLAG fid) {
|
|||
return count;
|
||||
}
|
||||
|
||||
void dumpflags(flagpile_t *fp) {
|
||||
flag_t *f;
|
||||
dblog("START FLAGDUMP");
|
||||
for (f = fp->first ; f ; f = f->next) {
|
||||
dblog("fid=%d, v0=%d v1=%d v2=%d text=[%s]",
|
||||
f->id, f->val[0], f->val[1], f->val[2], f->text);
|
||||
}
|
||||
dblog("END FLAGDUMP");
|
||||
}
|
||||
|
||||
// returns TRUE if knowingly gaining/losing this flag will
|
||||
// interrupt player actions like resting, training or eating.
|
||||
int flagcausesinterrupt(flag_t *f, enum GAINORLOSS gol ) {
|
||||
|
|
1
flag.h
1
flag.h
|
@ -18,6 +18,7 @@ int copyflag(flagpile_t *dst, flagpile_t *src, enum FLAG id);
|
|||
void copyflags(flagpile_t *dst, flagpile_t *src, int lifetime);
|
||||
int countflags(flagpile_t *fp);
|
||||
int countflagsofid(flagpile_t *fp, enum FLAG fid );
|
||||
void dumpflags(flagpile_t *fp);
|
||||
int flagcausesinterrupt(flag_t *f, enum GAINORLOSS gol);
|
||||
int flagcausesloscalc(enum FLAG fid);
|
||||
int flagcausesredraw(lifeform_t *lf, enum FLAG fid);
|
||||
|
|
43
god.c
43
god.c
|
@ -562,7 +562,7 @@ void dooffer(void) {
|
|||
}
|
||||
|
||||
// which god?
|
||||
god = askgod("To whom will you sacrifice?", B_TRUE);
|
||||
god = askgod("To whom will you sacrifice?", B_TRUE, B_FALSE);
|
||||
if (!god) {
|
||||
msg("Cancelled.");
|
||||
return;
|
||||
|
@ -911,6 +911,9 @@ void givegodbonus(enum RACE rid, flag_t *bf) {
|
|||
}
|
||||
more();
|
||||
|
||||
// increment piety so that it doesn't keep bouncing around the border.
|
||||
modpiety(rid, PIETYPRAYLOSS);
|
||||
|
||||
// parse regular rags
|
||||
parsegodbonusargs(bf, &bonuslev, &bonusid, &arg, targ);
|
||||
|
||||
|
@ -969,31 +972,31 @@ void removegodbonus(enum RACE rid, flag_t *bf) {
|
|||
// god announcement.
|
||||
switch (rid) {
|
||||
case R_GODPURITY:
|
||||
godsay(rid, B_TRUE, "I am not impressed, mortal.");
|
||||
godsay(rid, B_TRUE, "Your service is lacking, mortal.");
|
||||
break;
|
||||
case R_GODTHIEVES:
|
||||
godsay(rid, B_TRUE, "Disloyalty deserves punishment.");
|
||||
godsay(rid, B_TRUE, "I expect more results, mortal.");
|
||||
break;
|
||||
case R_GODDEATH:
|
||||
godsay(rid, B_TRUE, "Disobediant servants can easily be removed...");
|
||||
godsay(rid, B_TRUE, "Lazy servants can easily be removed...");
|
||||
break;
|
||||
case R_GODFIRE:
|
||||
godsay(rid, B_TRUE, "WRONG!");
|
||||
godsay(rid, B_TRUE, "PAY ATTENTION!");
|
||||
break;
|
||||
case R_GODLIFE:
|
||||
godsay(rid, B_TRUE, "No, no, no...");
|
||||
godsay(rid, B_TRUE, "You must be more proactive, my child.");
|
||||
break;
|
||||
case R_GODMERCY:
|
||||
godsay(rid, B_TRUE, "You disappoint me...");
|
||||
godsay(rid, B_TRUE, "You lack of proactiveness is disappointing...");
|
||||
break;
|
||||
case R_GODNATURE:
|
||||
godsay(rid, B_TRUE, "Nature will not tolerate your transgressions.");
|
||||
godsay(rid, B_TRUE, "Nature will not tolerate the lazy.");
|
||||
break;
|
||||
case R_GODBATTLE:
|
||||
godsay(rid, B_TRUE, "You have earned yourself a demotion, soldier.");
|
||||
godsay(rid, B_TRUE, "Your slothfulness has earned you a demotion, soldier.");
|
||||
break;
|
||||
case R_GODMAGIC:
|
||||
godsay(rid, B_TRUE, "One is deviating from the path!");
|
||||
godsay(rid, B_TRUE, "One must always strive towards the path!");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -1985,7 +1988,7 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
|
|||
taketime(lf, getactspeed(lf));
|
||||
|
||||
if (godblocked(god->race->id)) {
|
||||
msg("%s ignores you.", god->race->name);
|
||||
msg("%s doesn't respond.", god->race->name);
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
|
@ -1999,13 +2002,6 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
|
|||
// god before
|
||||
piety = getpiety(god->race->id);
|
||||
|
||||
// remember that we have now prayed to this god.
|
||||
// ie. player is expected to follow the god's rules.
|
||||
if (!hasflag(god->flags, F_PRAYEDTO)) {
|
||||
addflag(god->flags, F_PRAYEDTO, B_TRUE, NA, NA, NULL);
|
||||
newgod = B_TRUE;
|
||||
}
|
||||
|
||||
if (godisangry(god->race->id)) {
|
||||
// get even more angry
|
||||
angergod(god->race->id, PIETYPRAYLOSS, GA_PRAY);
|
||||
|
@ -2015,7 +2011,7 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
|
|||
if (piety <= 99) {
|
||||
// piety between 0 and 99 = ignored
|
||||
//godsay(god->race->id, "Stop pestering me!");
|
||||
msg("%s doesn't respond.", god->race->name);
|
||||
msg("%s ignores you.", god->race->name);
|
||||
angergod(god->race->id, 0, GA_PRAY);
|
||||
modpiety(god->race->id, -30);
|
||||
return B_FALSE;
|
||||
|
@ -2059,6 +2055,15 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
|
|||
}
|
||||
godsay(god->race->id, B_TRUE, assisttext);
|
||||
|
||||
|
||||
// at this point, remember that we have now prayed to
|
||||
// this god. ie. player is expected to follow the god's rules.
|
||||
if (!hasflag(god->flags, F_PRAYEDTO)) {
|
||||
addflag(god->flags, F_PRAYEDTO, B_TRUE, NA, NA, NULL);
|
||||
newgod = B_TRUE;
|
||||
}
|
||||
|
||||
|
||||
switch (god->race->id) {
|
||||
lifeform_t *l;
|
||||
int dist;
|
||||
|
|
88
io.c
88
io.c
|
@ -109,6 +109,7 @@ choice_t *addchoice(prompt_t *p, char ch, char *text, char *desc, void *data, ch
|
|||
else p->choice[p->nchoices].longdesc = strdup("");
|
||||
p->choice[p->nchoices].data = data;
|
||||
p->choice[p->nchoices].heading = B_FALSE;
|
||||
p->choice[p->nchoices].hilite = B_FALSE;
|
||||
p->choice[p->nchoices].valid = B_TRUE;
|
||||
p->choice[p->nchoices].shortcutslot = -1;
|
||||
p->nchoices++;
|
||||
|
@ -3075,7 +3076,7 @@ int confirm_injury_action(enum BODYPART bp, enum DAMTYPE dt, char *actionname) {
|
|||
return B_TRUE;
|
||||
}
|
||||
|
||||
lifeform_t *askgod(char *prompttext, int onlyprayed) {
|
||||
lifeform_t *askgod(char *prompttext, int onlyprayed, int forpray) {
|
||||
lifeform_t *lf = NULL;
|
||||
int i;
|
||||
char *longdesc;
|
||||
|
@ -3087,6 +3088,7 @@ lifeform_t *askgod(char *prompttext, int onlyprayed) {
|
|||
|
||||
for (i = 0 ; i < ngodlfs; i++) {
|
||||
flag_t *f;
|
||||
choice_t *chc;
|
||||
char godof[BUFLEN],buf[BUFLEN];
|
||||
lf = godlf[i];
|
||||
if (!lf) continue;
|
||||
|
@ -3094,14 +3096,28 @@ lifeform_t *askgod(char *prompttext, int onlyprayed) {
|
|||
if (onlyprayed && !lfhasflag(lf, F_PRAYEDTO)) {
|
||||
continue;
|
||||
}
|
||||
if (forpray && godblocked(lf->race->id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
real_getlfname(lf, buf, NULL, B_NOSHOWALL, B_REALRACE);
|
||||
f = hasflag(lf->flags, F_GODOF);
|
||||
snprintf(godof, BUFLEN, " (%s of %s)", (getgender(lf) == G_FEMALE) ? "goddess" : "god", f->text);
|
||||
if (godblocked(lf->race->id)) {
|
||||
strcat(godof, " [exiled]");
|
||||
} else if (godprayedto(lf->race->id)) {
|
||||
strcat(godof, " [worshipped]");
|
||||
}
|
||||
strcat(buf, godof);
|
||||
|
||||
makedesc_god(lf, longdesc);
|
||||
addchoice(&prompt, tolower(buf[0]), buf, NULL, lf, longdesc);
|
||||
chc = addchoice(&prompt, tolower(buf[0]), buf, NULL, lf, longdesc);
|
||||
if (godblocked(lf->race->id)) {
|
||||
chc->hilite = C_RED;
|
||||
} else if (godprayedto(lf->race->id)) {
|
||||
chc->hilite = C_GREEN;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
free(longdesc);
|
||||
|
@ -8814,7 +8830,7 @@ void dohelp(char helpmode) {
|
|||
centre(mainwin,C_WHITE, 0, "GOD REFERENCE");
|
||||
y = 2;
|
||||
|
||||
god = askgod("Describe which god (ESC when done)?", B_FALSE);
|
||||
god = askgod("Describe which god (ESC when done)?", B_FALSE, B_FALSE);
|
||||
if (!god) {
|
||||
done = B_TRUE;
|
||||
} else {
|
||||
|
@ -9868,7 +9884,9 @@ char getchoice(prompt_t *prompt) {
|
|||
mvwprintw(mainwin, y, 0, "%s", prompt->choice[i].desc);
|
||||
wattroff(mainwin, A_REVERSE);
|
||||
} else {
|
||||
if (prompt->choice[i].hilite) setcol(mainwin, prompt->choice[i].hilite);
|
||||
mvwprintw(mainwin, y, 0, "%s%c - %s", indenttext, prompt->choice[i].ch, prompt->choice[i].desc);
|
||||
if (prompt->choice[i].hilite) unsetcol(mainwin, prompt->choice[i].hilite);
|
||||
}
|
||||
y++;
|
||||
}
|
||||
|
@ -10516,7 +10534,7 @@ void handleinput(void) {
|
|||
}
|
||||
gotcmd = B_FALSE;
|
||||
break;
|
||||
case 'g': // repeat last command
|
||||
case CMD_AGAIN: // repeat last command
|
||||
f = hasflag(player->flags, F_LASTCMD);
|
||||
if (f) {
|
||||
ch = f->text[0];
|
||||
|
@ -10618,12 +10636,15 @@ void handleinput(void) {
|
|||
doattackcell('\0');
|
||||
}
|
||||
break;
|
||||
case CMD_INV: // inventory
|
||||
doinventory(player->pack);
|
||||
case CMD_GO: // go somewhere (pathfind)
|
||||
startpathfind();
|
||||
break;
|
||||
case CMD_HELP: // help
|
||||
dohelp('?');
|
||||
break;
|
||||
case CMD_INV: // inventory
|
||||
doinventory(player->pack);
|
||||
break;
|
||||
case CMD_INFOPLAYER: // display player stats
|
||||
showlfstats(player, B_FALSE);
|
||||
break;
|
||||
|
@ -13896,6 +13917,11 @@ void showlfstats(lifeform_t *lf, int showall) {
|
|||
mvwprintw(mainwin, y, 0, "%s do not forget your surroundings.", you(lf));
|
||||
y++;
|
||||
}
|
||||
f = hasflag_real(lf->flags, F_PLANTFRIEND, NA, NULL, FROMRACE);
|
||||
if (f) {
|
||||
mvwprintw(mainwin, y, 0, "Plants are friendly towards %s.", you(lf));
|
||||
y++;
|
||||
}
|
||||
f = hasflag_real(lf->flags, F_POLYIMMUNE, NA, NULL, FROMRACE);
|
||||
if (f) {
|
||||
mvwprintw(mainwin, y, 0, "%s cannot be polymorphed.", you(lf));
|
||||
|
@ -14019,7 +14045,7 @@ void showlfstats(lifeform_t *lf, int showall) {
|
|||
wattroff(mainwin, A_UNDERLINE);
|
||||
y = 2;
|
||||
|
||||
snprintf(line, BUFLEN, "%-30s Prayed? %-22s %s","God","Piety", "Happiness");
|
||||
snprintf(line, BUFLEN, "%-29s Worship? %-22s %s","God","Piety", "Happiness");
|
||||
|
||||
doheading(mainwin, &y, 0, line);
|
||||
|
||||
|
@ -14055,7 +14081,7 @@ void showlfstats(lifeform_t *lf, int showall) {
|
|||
|
||||
if (blocked) {
|
||||
col = C_RED;
|
||||
strcpy(happiness, "Ignored");
|
||||
strcpy(happiness, "Exiled");
|
||||
} else {
|
||||
plev = getpietylev(god->race->id, &col, happiness);
|
||||
}
|
||||
|
@ -14161,6 +14187,52 @@ void showlfstats(lifeform_t *lf, int showall) {
|
|||
//redraw();
|
||||
}
|
||||
|
||||
void showpath(lifeform_t *lf) {
|
||||
flag_t *f;
|
||||
char buf[BUFLEN];
|
||||
cell_t *c;
|
||||
real_getlfname(lf, buf, NULL, B_SHOWALL, B_CURRACE);
|
||||
cls();
|
||||
wmove(mainwin, 0, 0);
|
||||
f = lfhasflag(lf, F_AIPATH);
|
||||
wprintw(mainwin, "flagtext is: [%s]\n", f->text);
|
||||
|
||||
wprintw(mainwin, "Path for %s (%d,%d -> %d,%d) is:\n", buf,
|
||||
lf->cell->x, lf->cell->y, f->val[0], f->val[1]);
|
||||
|
||||
c = ai_getnextcellinpath(lf);
|
||||
while (c) {
|
||||
wprintw(mainwin, "%d,%d ->\n", c->x, c->y);
|
||||
ai_popnextcellinpath(lf);
|
||||
c = ai_getnextcellinpath(lf);
|
||||
}
|
||||
wprintw(mainwin, "END. (press key to exit)");
|
||||
getch();
|
||||
restoregamewindows();
|
||||
}
|
||||
|
||||
void startpathfind(void) {
|
||||
cell_t *c = NULL;
|
||||
c = askcoords("Go to where?", "Goto->", TT_NONE, player, UNLIMITED, LOF_DONTNEED, B_FALSE);
|
||||
if (!c) {
|
||||
msg("Cancelled.");
|
||||
return;
|
||||
}
|
||||
if (!c->known ||
|
||||
(c->map != player->cell->map) ||
|
||||
(haslos(player, c) && !cellwalkable(player, c, NULL))) {
|
||||
msg("You don't know how to get there.");
|
||||
return;
|
||||
|
||||
}
|
||||
// try to find path.
|
||||
if (ai_createpathto(player, c)) {
|
||||
addflag(player->flags, F_PATHFINDING, c->x, c->y, player->cell->map->id, NULL);
|
||||
} else {
|
||||
msg("You don't know how to get there.");
|
||||
}
|
||||
}
|
||||
|
||||
void textwithcol(WINDOW *win, char *buf) {
|
||||
textwithcol_real(win, buf, B_TRUE);
|
||||
}
|
||||
|
|
4
io.h
4
io.h
|
@ -20,7 +20,7 @@ void announceobflagloss(object_t *o, flag_t *f);
|
|||
void announcetime(int h, int m, int s, int showfull);
|
||||
int confirm_badfeeling(object_t *o);
|
||||
int confirm_injury_action(enum BODYPART bp, enum DAMTYPE dt, char *actionname);
|
||||
lifeform_t *askgod(char *prompt, int onlyprayed);
|
||||
lifeform_t *askgod(char *prompt, int onlyprayed, int forpray);
|
||||
object_t *askobject(obpile_t *op, char *title, char *noobtext, int *count, char action, long opts);
|
||||
object_t *askobjectwithflag(obpile_t *op, char *title, char *noobtext,int *count, char action, long opts, enum FLAG withflag);
|
||||
object_t *doaskobject(obpile_t *op, char *prompt, char *noobtext, int *count, int showlong, int forpickup, int showpoints, char action, object_t *sellshop, enum SHOPACTION sellaction, int wantmaterial, long opts, ...);
|
||||
|
@ -141,6 +141,8 @@ void setobcolour(WINDOW *win, object_t *o, int set);
|
|||
int showhiscoreline(void *hilitescore, int ncols, char **argv, char **colname);
|
||||
void showlfarmour(lifeform_t *lf);
|
||||
void showlfstats(lifeform_t *lf, int showall);
|
||||
void showpath(lifeform_t *lf);
|
||||
void startpathfind(void);
|
||||
void textwithcol(WINDOW *win, char *buf);
|
||||
void textwithcol_real(WINDOW *win, char *buf, int resetcolatend);
|
||||
void tombstone(lifeform_t *lf);
|
||||
|
|
54
lf.c
54
lf.c
|
@ -2050,8 +2050,8 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
|
|||
}
|
||||
} else {
|
||||
if (hasflag(sp->flags, F_CASTINGTIME)) {
|
||||
} else {
|
||||
msg("%s starts casting a spell.", lfname);
|
||||
} else {
|
||||
}
|
||||
}
|
||||
} else { // player can't see them
|
||||
|
@ -2375,9 +2375,13 @@ int charmedaction(lifeform_t *lf, flag_t *charmflag) {
|
|||
} else {
|
||||
if (isplayer(lf)) {
|
||||
char obname[BUFLEN];
|
||||
char mastername[BUFLEN];
|
||||
sprintf(mastername, "your new %s",
|
||||
(getgender(charmer) == G_FEMALE) ?
|
||||
"mistress" : "master");
|
||||
getobname(o, obname, o->amt);
|
||||
msg("^wYou hand over your %s to %s.", noprefix(obname),
|
||||
cansee(lf, charmer) ? charmername : "your new master");
|
||||
cansee(lf, charmer) ? charmername : mastername);
|
||||
} else if (cansee(player, lf)) {
|
||||
char lfname[BUFLEN];
|
||||
char obname[BUFLEN];
|
||||
|
@ -4128,10 +4132,6 @@ void generatealignment(lifeform_t *lf) {
|
|||
initprompt(&prompt, buf);
|
||||
|
||||
|
||||
if (isplayer(lf)) {
|
||||
dblog("xx");
|
||||
}
|
||||
|
||||
if (nposs == 0) {
|
||||
if (isplayer(lf)) {
|
||||
assert("Error - no possible alignment for player." == 0);
|
||||
|
@ -4764,6 +4764,8 @@ int eat(lifeform_t *lf, object_t *o) {
|
|||
if (strlen(taste)) msg("%s", taste);
|
||||
} else if (cansee(player, lf)) {
|
||||
msg("%s finishes %s.", lfname, drinking ? "drinking" : "eating");
|
||||
} else {
|
||||
noise(lf->cell, lf, NC_OTHER, SV_TALK, drinking ? "something being quaffed." : "something being eaten.", NULL);
|
||||
}
|
||||
} else {
|
||||
if (isplayer(lf)) {
|
||||
|
@ -4771,6 +4773,8 @@ int eat(lifeform_t *lf, object_t *o) {
|
|||
if (strlen(taste)) msg("%s", taste);
|
||||
} else if (cansee(player, lf)) {
|
||||
msg("%s %s %s.", lfname, drinking ? "drinks" : "eats", obname);
|
||||
} else {
|
||||
noise(lf->cell, lf, NC_OTHER, SV_TALK, drinking ? "something being quaffed." : "something being eaten.", NULL);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -4779,6 +4783,8 @@ int eat(lifeform_t *lf, object_t *o) {
|
|||
msg("You continue %s.", drinking ? "drinking" : "eating");
|
||||
} else if (cansee(player, lf)) {
|
||||
msg("%s continues %s.", lfname, drinking ? "drinking" : "eating");
|
||||
} else {
|
||||
noise(lf->cell, lf, NC_OTHER, SV_TALK, drinking ? "something being quaffed." : "something being eaten.", NULL);
|
||||
}
|
||||
} else {
|
||||
if (isplayer(lf)) {
|
||||
|
@ -4786,6 +4792,8 @@ int eat(lifeform_t *lf, object_t *o) {
|
|||
|
||||
} else if (cansee(player, lf)) {
|
||||
msg("%s starts %s %s.", lfname, drinking ? "drinking" : "eating", obname);
|
||||
} else {
|
||||
noise(lf->cell, lf, NC_OTHER, SV_TALK, drinking ? "something being quaffed." : "something being eaten.", NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11110,7 +11118,7 @@ void givejob(lifeform_t *lf, enum JOB jobid) {
|
|||
spell = getrandomspellfromschool(SS_NATURE, 1);
|
||||
}
|
||||
// you can now cast it.
|
||||
addflag(lf->flags, F_CANCAST, spell, NA, NA, NULL);
|
||||
addtempflag(lf->flags, F_CANCAST, spell, NA, NA, NULL, FROMJOB);
|
||||
}
|
||||
// druids always worship ekrub
|
||||
if (isplayer(lf)) {
|
||||
|
@ -11180,7 +11188,7 @@ void givejob(lifeform_t *lf, enum JOB jobid) {
|
|||
}
|
||||
// all starting gear is blessed
|
||||
for (o = lf->pack->first ; o ; o = o->next) {
|
||||
if (isequipped(o)) {
|
||||
if (isweapon(o) || isarmour(o) || isshield(o)) {
|
||||
blessob(o);
|
||||
}
|
||||
}
|
||||
|
@ -11243,7 +11251,7 @@ void givejob(lifeform_t *lf, enum JOB jobid) {
|
|||
char pwbuf[BUFLEN];
|
||||
pow = MINOF((gettr(lf)/2), getspellmaxpower(o->type->id));
|
||||
sprintf(pwbuf, "pw:%d;", pow);
|
||||
addflag(lf->flags, F_CANCAST, o->type->id, NA, NA, pwbuf);
|
||||
addtempflag(lf->flags, F_CANCAST, o->type->id, NA, NA, pwbuf, FROMJOB);
|
||||
}
|
||||
}
|
||||
// chance of spellbook vanishing
|
||||
|
@ -11282,6 +11290,11 @@ void givejob(lifeform_t *lf, enum JOB jobid) {
|
|||
}
|
||||
*/
|
||||
|
||||
// call this again, for cases like the paladin.
|
||||
if ((gamemode != GM_GAMESTARTED)) {
|
||||
autoweild(lf);
|
||||
}
|
||||
|
||||
if (isplayer(lf)) {
|
||||
generatealignment(lf);
|
||||
}
|
||||
|
@ -11728,7 +11741,7 @@ void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp) {
|
|||
object_t *o = NULL;
|
||||
flag_t *f;
|
||||
char buf[BUFLEN],buf2[BUFLEN];
|
||||
int db = B_TRUE;
|
||||
int db = B_FALSE;
|
||||
obpile_t *op;
|
||||
map_t *targmap;
|
||||
enum LFSIZE maxobsize = SZ_MAX;
|
||||
|
@ -13581,7 +13594,11 @@ void killlf(lifeform_t *lf) {
|
|||
// shouldn't need this...
|
||||
lf->cell = NULL;
|
||||
|
||||
// remove impossible flags...
|
||||
// remove impossible stuff
|
||||
if (getstamina(lf) > getmaxstamina(lf)) {
|
||||
setstamina(lf, getmaxstamina(lf));
|
||||
}
|
||||
|
||||
// check if anyone is targetting us.
|
||||
// if so, stop targetting us now that
|
||||
// we are dead.
|
||||
|
@ -18544,12 +18561,12 @@ int startclimbing(lifeform_t *lf) {
|
|||
}
|
||||
} else {
|
||||
// you need to climbing skill to climb walls
|
||||
if (!getskill(lf, SK_CLIMBING)) {
|
||||
if (!getskill(lf, SK_CLIMBING) && !lfhasflag(lf, F_SPIDERCLIMB)) {
|
||||
if (isplayer(lf)) {
|
||||
msg("You are not sufficiently skilled to climb walls.");
|
||||
}
|
||||
return B_TRUE;
|
||||
} if (skillcheck(lf, SC_CLIMB, getcellclimbdifficulty(where), 0)) {
|
||||
} else if (skillcheck(lf, SC_CLIMB, getcellclimbdifficulty(where), 0)) {
|
||||
// announce
|
||||
if (isplayer(lf)) {
|
||||
msg("You climb onto %s %s.", needan(where->type->name) ? "an" : "a", where->type->name);
|
||||
|
@ -19932,6 +19949,7 @@ void interrupt(lifeform_t *lf) {
|
|||
stopeating(lf);
|
||||
stopresting(lf);
|
||||
stoprunning(lf);
|
||||
stoppathfinding(lf);
|
||||
killflagsofid(lf->flags, F_AUTOCMD);
|
||||
killflagsofid(lf->flags, F_DIGGING);
|
||||
}
|
||||
|
@ -20913,7 +20931,7 @@ void startlfturn(lifeform_t *lf) {
|
|||
} else {
|
||||
msg("^wAll of your items are missing!^n"); more();
|
||||
}
|
||||
} else {
|
||||
} else if (cantalk(lf)) {
|
||||
sayphrase(lf, SP_ROBBED, SV_SHOUT, NA, NULL, NULL);
|
||||
}
|
||||
killflagsofid(lf->flags, F_WASROBBED);
|
||||
|
@ -21160,8 +21178,12 @@ void startlfturn(lifeform_t *lf) {
|
|||
// the further away from neutral you are, the less chance
|
||||
// piety/anger has of 'expiring'
|
||||
if (pctchance(chance)) {
|
||||
enum PIETYLEV newplev,oldplev;
|
||||
// slowly move towards normal
|
||||
oldplev = getpietylev(godlf[i]->race->id, NULL, NULL);
|
||||
modpiety(godlf[i]->race->id, dir);
|
||||
newplev = getpietylev(godlf[i]->race->id, NULL, NULL);
|
||||
checkgodbonus(godlf[i]->race->id,newplev, oldplev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22590,6 +22612,10 @@ int stopclimbing(lifeform_t *lf, int onpurpose) {
|
|||
return B_FALSE;
|
||||
}
|
||||
|
||||
void stoppathfinding(lifeform_t *lf) {
|
||||
killflagsofid(lf->flags, F_PATHFINDING);
|
||||
}
|
||||
|
||||
void stopresting(lifeform_t *lf) {
|
||||
flag_t *f;
|
||||
|
||||
|
|
1
lf.h
1
lf.h
|
@ -493,6 +493,7 @@ int steal(lifeform_t *lf, obpile_t *op, enum FLAG wantflag);
|
|||
int stone(lifeform_t *lf);
|
||||
int stopclimbing(lifeform_t *lf, int onpurpose);
|
||||
void stopeating(lifeform_t *lf);
|
||||
void stoppathfinding(lifeform_t *lf);
|
||||
void stopresting(lifeform_t *lf);
|
||||
void stoprunning(lifeform_t *lf);
|
||||
void stopsprinting(lifeform_t *lf);
|
||||
|
|
3
map.c
3
map.c
|
@ -6426,7 +6426,7 @@ void finalisemonster(lifeform_t *lf, lifeform_t *leader, flagpile_t *wantflags,
|
|||
// if monster is in a vault, check its flags...
|
||||
v = getcellvault(lf->cell);
|
||||
if (v) {
|
||||
copyflags(lf->flags, v->flags, F_STAYINROOM);
|
||||
copyflag(lf->flags, v->flags, F_STAYINROOM);
|
||||
}
|
||||
|
||||
if (lf->race->id == R_HYDRA) {
|
||||
|
@ -6460,6 +6460,7 @@ void finalisemonster(lifeform_t *lf, lifeform_t *leader, flagpile_t *wantflags,
|
|||
}
|
||||
}
|
||||
*/
|
||||
autoskill(lf);
|
||||
}
|
||||
|
||||
celltype_t *findcelltype(enum CELLTYPE cid) {
|
||||
|
|
86
move.c
86
move.c
|
@ -1486,7 +1486,7 @@ int movelf(lifeform_t *lf, cell_t *newcell, int onpurpose) {
|
|||
}
|
||||
continue;
|
||||
}
|
||||
if (hasflag(o->flags, F_DIMONWALK)) {
|
||||
if (hasflag(o->flags, F_DIMONDISTURB)) {
|
||||
f = hasflag(o->flags, F_PRODUCESLIGHT);
|
||||
getobname(o, obname, o->amt);
|
||||
if (f) f->val[0]--;
|
||||
|
@ -1505,7 +1505,7 @@ int movelf(lifeform_t *lf, cell_t *newcell, int onpurpose) {
|
|||
didmsg = B_TRUE;
|
||||
}
|
||||
}
|
||||
} // end if dimonwalk
|
||||
} // end if dimondisturb
|
||||
} // end if crushable
|
||||
|
||||
if ((o->type->id == OT_VINE) && !hasjob(lf, J_DRUID)) {
|
||||
|
@ -1913,7 +1913,11 @@ int movetowards(lifeform_t *lf, cell_t *dst, int dirtype, int strafe) {
|
|||
}
|
||||
|
||||
// move towards them
|
||||
dir = getdirtowards(lf->cell, dst, lf, B_TRUE, dirtype);
|
||||
if (isadjacent(lf->cell, dst)) {
|
||||
dir = whichwayto(lf->cell, dst, lf, B_TRUE);
|
||||
} else {
|
||||
dir = getdirtowards(lf->cell, dst, lf, B_TRUE, dirtype);
|
||||
}
|
||||
if (dir != D_NONE) {
|
||||
if (db) {
|
||||
dblog(".oO { dir from %d,%d -> %d,%d is %s }", lf->cell->x, lf->cell->y, dst->x, dst->y, getdirname(dir));
|
||||
|
@ -2073,6 +2077,7 @@ int opendoor(lifeform_t *lf, object_t *o) {
|
|||
// trapped?
|
||||
if (lf && hasflag(o->flags, F_TRAPPED)) {
|
||||
if (doobtraps(o, lf)) {
|
||||
if (isplayer(lf)) stoppathfinding(lf);
|
||||
return B_TRUE;
|
||||
}
|
||||
}
|
||||
|
@ -2095,8 +2100,9 @@ int opendoor(lifeform_t *lf, object_t *o) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (isplayer(lf)) stoppathfinding(lf);
|
||||
return B_TRUE;
|
||||
} else {// ie. door not locked, but it might be jammed
|
||||
} else { // ie. door not locked, but it might be jammed
|
||||
int openit = B_TRUE;
|
||||
f = hasflag(o->flags, F_JAMMED);
|
||||
if (f && lf) {
|
||||
|
@ -2156,6 +2162,7 @@ int opendoor(lifeform_t *lf, object_t *o) {
|
|||
}
|
||||
} // end if jammedknown
|
||||
} // end if jammed
|
||||
|
||||
if (openit) {
|
||||
cell_t *where;
|
||||
// open it
|
||||
|
@ -2171,7 +2178,6 @@ int opendoor(lifeform_t *lf, object_t *o) {
|
|||
if (isplayer(lf)) {
|
||||
msg("You force %s open!",obname);
|
||||
} else {
|
||||
//if (cansee(player, lf) && isadjacent(lf->cell, doorcell)) {
|
||||
if (cansee(player, lf)) {
|
||||
getlfname(lf, buf);
|
||||
capitalise(buf);
|
||||
|
@ -2202,9 +2208,8 @@ int opendoor(lifeform_t *lf, object_t *o) {
|
|||
noise(doorcell, NULL, NC_OTHER, SV_TALK, noisebuf, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} // end if wasjammed
|
||||
} // end if lf
|
||||
where = getoblocation(o);
|
||||
|
||||
if (player) {
|
||||
|
@ -2220,10 +2225,16 @@ int opendoor(lifeform_t *lf, object_t *o) {
|
|||
noise(where, NULL, NC_OTHER, SV_TALK, "a door opening.", NULL);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// !openit
|
||||
if (isplayer(lf)) {
|
||||
stoppathfinding(lf);
|
||||
}
|
||||
}
|
||||
return B_FALSE;
|
||||
} // end if door locked
|
||||
}
|
||||
}
|
||||
|
||||
} // end if door locked
|
||||
|
||||
return B_FALSE;
|
||||
}
|
||||
|
@ -3217,7 +3228,10 @@ int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe) {
|
|||
if (isplayer(lf)) {
|
||||
if (cell->known) {
|
||||
// try to open it
|
||||
if (!opendoor(lf, inway)) {
|
||||
if (opendoor(lf, inway)) {
|
||||
// failed.
|
||||
if (isplayer(lf)) stoppathfinding(lf);
|
||||
} else {
|
||||
// opening a door counts as a successful move.
|
||||
reason = E_OK;
|
||||
}
|
||||
|
@ -3227,6 +3241,7 @@ int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe) {
|
|||
snprintf(buf, BUFLEN, "%sing into a door", getmoveverb(lf));
|
||||
losehp(lf, 1, DT_BASH, NULL, buf);
|
||||
if (onpurpose || fleeing) taketime(lf, getmovespeed(lf));
|
||||
if (isplayer(lf)) stoppathfinding(lf);
|
||||
}
|
||||
} else {
|
||||
if (cansee(player, lf)) {
|
||||
|
@ -3238,14 +3253,18 @@ int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe) {
|
|||
snprintf(buf, BUFLEN, "%sing into a door", getmoveverb(lf));
|
||||
losehp(lf, 1, DT_BASH, NULL, buf);
|
||||
if (onpurpose || fleeing) taketime(lf, getmovespeed(lf));
|
||||
if (isplayer(lf)) stoppathfinding(lf);
|
||||
}
|
||||
} else {
|
||||
if (lfhasflag(lf, F_RAGE)) {
|
||||
if (lfhasflag(lf, F_RAGE) || !canopendoors(lf)) {
|
||||
// attack it
|
||||
return attackcell(lf, cell, B_FALSE);
|
||||
} else {
|
||||
// try to open it
|
||||
if (!opendoor(lf, inway)) {
|
||||
if (opendoor(lf, inway)) {
|
||||
// fail
|
||||
if (isplayer(lf)) stoppathfinding(lf);
|
||||
} else {
|
||||
// opening a door counts as a successful move.
|
||||
reason = E_OK;
|
||||
}
|
||||
|
@ -3584,6 +3603,47 @@ int walkoffmap(lifeform_t *lf, int dir, int onpurpose) {
|
|||
return B_FALSE;
|
||||
}
|
||||
|
||||
// returns direction to an adjacent cell
|
||||
int whichwayto(cell_t *start, cell_t *end, lifeform_t *srclf, int wantcheck) {
|
||||
int i;
|
||||
cell_t *c;
|
||||
for (i = DC_N; i <= DC_NW; i++) {
|
||||
c = getcellindir(start, i);
|
||||
if (c == end) {
|
||||
int ok = B_FALSE;
|
||||
enum ERROR error = E_OK;
|
||||
if (wantcheck) {
|
||||
if (srclf) {
|
||||
if (canandwillmove(srclf, i, &error)) {
|
||||
ok = B_TRUE;
|
||||
} else if (error == E_DOORINWAY) {
|
||||
ok = B_TRUE;
|
||||
}
|
||||
} else {
|
||||
ok = B_TRUE;
|
||||
}
|
||||
} else {
|
||||
if (srclf) {
|
||||
if (cellwalkable(srclf, c, &error)) {
|
||||
ok = B_TRUE;
|
||||
} else if (error == E_DOORINWAY) {
|
||||
ok = B_TRUE;
|
||||
}
|
||||
} else {
|
||||
ok = B_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
return i;
|
||||
} else {
|
||||
return getdirtowards(start, end, srclf, wantcheck, DT_ORTH);
|
||||
}
|
||||
}
|
||||
}
|
||||
return D_NONE;
|
||||
}
|
||||
|
||||
int willmove(lifeform_t *lf, int dir, enum ERROR *error) {
|
||||
cell_t *cell;
|
||||
enum ATTRBRACKET iq;
|
||||
|
|
1
move.h
1
move.h
|
@ -38,4 +38,5 @@ int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe);
|
|||
int tryrun(lifeform_t *lf, int dir);
|
||||
int trysneak(lifeform_t *lf, int dir);
|
||||
int walkoffmap(lifeform_t *lf, int dir, int onpurpose);
|
||||
int whichwayto(cell_t *start, cell_t *end, lifeform_t *srclf, int wantcheck);
|
||||
int willmove(lifeform_t *lf, int dir, enum ERROR *error);
|
||||
|
|
44
nexus.c
44
nexus.c
|
@ -418,6 +418,11 @@ int main(int argc, char **argv) {
|
|||
|
||||
// create pet, in view of player if possible.
|
||||
c = real_getrandomadjcell(player->cell, WE_WALKABLE, B_ALLOWEXPAND, LOF_NEED, &avoidob, NULL, player, MT_NOTHING);
|
||||
if (!c) {
|
||||
c = real_getrandomadjcell(player->cell, WE_SOLID, B_NOEXPAND, LOF_DONTNEED, &avoidob, NULL, player, MT_NOTHING);
|
||||
assert(c);
|
||||
setcelltype(c, getmapempty(player->cell->map));
|
||||
}
|
||||
assert(c);
|
||||
pet = addlf(c, r->id, 1);
|
||||
// mark us as its master
|
||||
|
@ -1007,6 +1012,45 @@ void donextturn(map_t *map) {
|
|||
}
|
||||
}
|
||||
|
||||
// pathfinding?
|
||||
if (donormalmove && isplayer(who)) {
|
||||
if (lfhasflag(who, F_PATHFINDING)) {
|
||||
cell_t *c;
|
||||
// follow.....
|
||||
c = ai_getnextcellinpath(who);
|
||||
if (c) {
|
||||
if (c->map != who->cell->map) {
|
||||
msg("Destination is on different level. Aborting.");
|
||||
stoppathfinding(who);
|
||||
} else {
|
||||
int dir,ok;
|
||||
enum ERROR errcode;
|
||||
donormalmove = B_FALSE;
|
||||
dir = whichwayto(who->cell, c, who, B_TRUE);
|
||||
ok = moveclear(who, dir, &errcode);
|
||||
if (!ok && (errcode != E_DOORINWAY)) {
|
||||
// something other than a door in the way?
|
||||
msg("Stopped pathfinding.");
|
||||
stoppathfinding(who);
|
||||
} else {
|
||||
if (trymove(who, dir, B_TRUE, B_FALSE)) {
|
||||
msg("Can't move towards target cell.");
|
||||
stoppathfinding(who);
|
||||
}
|
||||
if (who->cell == c) {
|
||||
// success
|
||||
ai_popnextcellinpath(who);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
msg("Arrived at destination.");
|
||||
stoppathfinding(who);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// casting a spell?
|
||||
if (donormalmove) {
|
||||
f = lfhasflag(who, F_CASTINGSPELL);
|
||||
|
|
27
objects.c
27
objects.c
|
@ -475,7 +475,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum
|
|||
char numstringmax[BUFLEN];
|
||||
int howmany = 1;
|
||||
int i;
|
||||
int db = B_TRUE;
|
||||
int db = B_FALSE;
|
||||
flag_t *f;
|
||||
char *localname = NULL;
|
||||
int wantblessed = B_UNCURSED;
|
||||
|
@ -3964,9 +3964,6 @@ void genhiddennames(void) {
|
|||
objecttype_t *ot;
|
||||
flag_t *f;
|
||||
for (ot = objecttype ; ot ; ot = ot->next) {
|
||||
if (ot->obclass->id == OC_BOOK) {
|
||||
dblog("xx");
|
||||
}
|
||||
f = hasflag(ot->flags, F_HASHIDDENNAME);
|
||||
if (f) {
|
||||
char *thisname;
|
||||
|
@ -14541,6 +14538,28 @@ void timeeffectsob(object_t *o) {
|
|||
}
|
||||
}
|
||||
|
||||
if (owner && !onground) {
|
||||
if (hasflag(o->flags, F_DIMONDISTURB)) {
|
||||
f = hasflag(o->flags, F_PRODUCESLIGHT);
|
||||
getobname(o, obname, o->amt);
|
||||
if (f) f->val[0]--;
|
||||
if (!f || (f->val[0] <= 0)) {
|
||||
if (isplayer(owner)) {
|
||||
msg("Your %s dim%s and crumbles.",noprefix(obname),
|
||||
(o->amt == 1) ? "s" : "");
|
||||
}
|
||||
removeob(o, ALL);
|
||||
return;
|
||||
} else {
|
||||
if (isplayer(owner)) {
|
||||
msg("Your %s dim%s slightly.",noprefix(obname),
|
||||
(o->amt == 1) ? "s" : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (location && !owner) {
|
||||
lifeform_t *who;
|
||||
who = location->lf;
|
||||
|
|
78
spell.c
78
spell.c
|
@ -2865,10 +2865,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
|
|||
}
|
||||
|
||||
// ask for which god
|
||||
initprompt(&prompt, "To whom will you pray?");
|
||||
prompt.maycancel = B_TRUE;
|
||||
|
||||
god = askgod("To whom will you pray?", B_FALSE);
|
||||
god = askgod("To whom will you pray?", B_FALSE, B_TRUE);
|
||||
if (!god) {
|
||||
msg("Cancelled.");
|
||||
return B_TRUE;
|
||||
|
@ -3122,6 +3119,26 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
|
|||
if (where && where->lf) {
|
||||
debug(where->lf);
|
||||
}
|
||||
} else if (abilid == OT_A_PATHFIND) {
|
||||
cell_t *where;
|
||||
where = askcoords("Pathfind to where?", "Pathfind->",TT_NONE, user, UNLIMITED, LOF_DONTNEED, B_FALSE);
|
||||
if (where) {
|
||||
if (ai_createpathto(user, where)) {
|
||||
msg("Success!"); more();
|
||||
showpath(user);
|
||||
killflagsofid(user->flags, F_AIPATH);
|
||||
} else {
|
||||
msg("PATHFIND FAILED.");
|
||||
}
|
||||
|
||||
}
|
||||
} else if (abilid == OT_A_PETIFY) {
|
||||
cell_t *where;
|
||||
where = askcoords("Petify who?", "Petify->",TT_MONSTER, user, UNLIMITED, LOF_DONTNEED, B_FALSE);
|
||||
if (where && where->lf) {
|
||||
petify(where->lf, user);
|
||||
msg("Petified %s.", where->lf->race->name);
|
||||
}
|
||||
} else if (abilid == OT_A_EMPLOY) {
|
||||
cell_t *where;
|
||||
where = askcoords("Assign job to who?", "Assignjob->",TT_MONSTER, user, UNLIMITED, LOF_DONTNEED, B_FALSE);
|
||||
|
@ -12024,11 +12041,16 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
|
||||
|
||||
if (lfhasflag(caster, F_CONTROL)) {
|
||||
/*
|
||||
if (power < 5) {
|
||||
power = 5;
|
||||
} else if (power < 8) {
|
||||
power = 8;
|
||||
}
|
||||
*/
|
||||
if (power < 8) {
|
||||
power = 8;
|
||||
}
|
||||
}
|
||||
|
||||
if ((power < 5) || !isplayer(caster)) {
|
||||
|
@ -12847,7 +12869,6 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
}
|
||||
} else if (spellid == OT_S_WARPWOOD) {
|
||||
object_t *o,*nexto;
|
||||
flag_t *f;
|
||||
int ndone = 0;
|
||||
|
||||
if (!targcell) {
|
||||
|
@ -12862,11 +12883,13 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
if ((o->type->material->id == MT_WOOD) || (o->type->material->id == MT_DRAGONWOOD)) {
|
||||
if (isequipped(o)) {
|
||||
int dam;
|
||||
f = hasflag(o->flags, F_OBHP);
|
||||
if (f) {
|
||||
dam = rnd(f->val[0]/2,f->val[0]);
|
||||
} else {
|
||||
dam = roll("1d6");
|
||||
dam = rolldie(power, 4);
|
||||
if (haslos(player, targcell)) {
|
||||
char obname[BUFLEN];
|
||||
getobname(o, obname, o->amt);
|
||||
msg("%s twist%s and writhe%s!",obname,
|
||||
(o->amt == 1) ? "s" : "",
|
||||
(o->amt == 1) ? "s" : "");
|
||||
}
|
||||
takedamage(o, dam, DT_DECAY, caster);
|
||||
if (haslos(player, targcell)) {
|
||||
|
@ -12883,12 +12906,15 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
nexto = o->next;
|
||||
if ((o->type->material->id == MT_WOOD) || (o->type->material->id == MT_DRAGONWOOD)) {
|
||||
int dam;
|
||||
f = hasflag(o->flags, F_OBHP);
|
||||
if (f) {
|
||||
dam = rnd(1,f->val[0]);
|
||||
} else {
|
||||
dam = roll("1d6");
|
||||
dam = rolldie(power, 4);
|
||||
if (haslos(player, targcell)) {
|
||||
char obname[BUFLEN];
|
||||
getobname(o, obname, o->amt);
|
||||
msg("%s twist%s and writhe%s!",obname,
|
||||
(o->amt == 1) ? "s" : "",
|
||||
(o->amt == 1) ? "s" : "");
|
||||
}
|
||||
|
||||
takedamage(o, dam, DT_DIRECT, caster);
|
||||
if (haslos(player, targcell)) {
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
|
@ -12896,6 +12922,28 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
ndone++;
|
||||
}
|
||||
}
|
||||
if (targcell->lf) {
|
||||
if ((targcell->lf->material->id == MT_WOOD) ||
|
||||
(targcell->lf->material->id == MT_DRAGONWOOD)) {
|
||||
int dam;
|
||||
char dambuf[BUFLEN];
|
||||
dam = rolldie(power, 4);
|
||||
if (haslos(player, targcell)) {
|
||||
char lfname[BUFLEN];
|
||||
getlfname(targcell->lf, lfname);
|
||||
msg("%s twist%s and writhe%s!",lfname,
|
||||
isplayer(targcell->lf) ? "" : "s",
|
||||
isplayer(targcell->lf) ? "" : "s");
|
||||
}
|
||||
|
||||
sprintf(dambuf, "%s%s warp wood spell", castername, getpossessive(castername));
|
||||
losehp(targcell->lf, dam, DT_DIRECT, caster, dambuf);
|
||||
if (haslos(player, targcell)) {
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
ndone++;
|
||||
}
|
||||
}
|
||||
if (!ndone) {
|
||||
fizzle(caster);
|
||||
return B_TRUE;
|
||||
|
|
Loading…
Reference in New Issue