* [+] why did i get a gift from yumi in the middle of a battle?

- [+] need alignment. f_alignment.  default neutral.
- [+] slight change to armour damage calc
- [+] thrown poisoned weapons don't work!
- [+] holy aura spell. lv3 cleric.
* [+] are kobolds working properly??  seem buggy
* [+] calmed down a war hound with a mushroom.
- [+] use wisdom for checks for unwise things, not iq.
* [+] hecta should only care about attacking evil creatures if they
      were NOT hostile.
- [+] optimise:
    - [+] use getflags() more often.
    - [+] lookforobs() - redo code for ai wanting things.
    * [+] precalclos - 28%
    * [+] hasbetterweapon()
    - [+] haslos - 27.3%
- [+] when you move now, you don't have los to your previous cell on
      the first drawscreen when your turn starts!!!!!
- [+] ai is coming too close before firing ranged weapons. allow them
      to stay within 2 - maxrange if they have a weapon.
- [+] also let them fire form furhter away!
* [+] give healing potion to hurt (intelligent) lf to calm them down?
* [+] Amberon (m) purity, righteousness
* [+] Hecta - female, death, undead, evil, night
* [+] Felix -  male, thieves, greed
* [+] bug - i found jimbo dead!
- [+] cave vault (different wall types, boulder at the entrance, lots of
      food, bears)
This commit is contained in:
Rob Pearce 2011-08-10 02:40:29 +00:00
parent 00f9d4e0bf
commit cdd7d69532
18 changed files with 1683 additions and 960 deletions

240
ai.c
View File

@ -18,6 +18,9 @@
extern lifeform_t *player; extern lifeform_t *player;
extern enum ERROR reason; extern enum ERROR reason;
extern flag_t *retflag[];
extern int nretflags;
int wantdb = B_TRUE; int wantdb = B_TRUE;
void addignorecell(lifeform_t *lf, cell_t *c) { void addignorecell(lifeform_t *lf, cell_t *c) {
@ -124,9 +127,11 @@ enum OBTYPE aigetattackspell(lifeform_t *lf, lifeform_t *victim) {
castok = B_FALSE; castok = B_FALSE;
} }
for (f = lf->flags->first ; f ; f = f->next) { if (castok) {
if ( (castok && (f->id == F_CANCAST)) || int i;
(f->id == F_CANWILL)) { getflags(lf->flags, F_CANCAST, F_CANWILL, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (aispellok(lf, f->val[0], victim, F_AICASTTOATTACK)) { if (aispellok(lf, f->val[0], victim, F_AICASTTOATTACK)) {
poss[nposs] = f->val[0]; poss[nposs] = f->val[0];
nposs++; nposs++;
@ -152,7 +157,7 @@ enum OBTYPE aigetattackspell(lifeform_t *lf, lifeform_t *victim) {
enum OBTYPE aigetfleespell(lifeform_t *lf) { enum OBTYPE aigetfleespell(lifeform_t *lf) {
flag_t *f; flag_t *f;
enum OBTYPE poss[MAXPILEOBS]; enum OBTYPE poss[MAXPILEOBS];
int nposs = 0; int nposs = 0,i;
int db = B_FALSE; int db = B_FALSE;
lifeform_t *fleefrom; lifeform_t *fleefrom;
@ -166,14 +171,14 @@ enum OBTYPE aigetfleespell(lifeform_t *lf) {
} }
for (f = lf->flags->first ; f ; f = f->next) { getflags(lf->flags, F_CANCAST, F_CANWILL, F_NONE);
if ((f->id == F_CANCAST) || (f->id == F_CANWILL)) { for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (aispellok(lf, f->val[0], fleefrom, F_AICASTTOFLEE)) { if (aispellok(lf, f->val[0], fleefrom, F_AICASTTOFLEE)) {
poss[nposs] = f->val[0]; poss[nposs] = f->val[0];
nposs++; nposs++;
} }
} }
}
// select a random one // select a random one
if (nposs > 0) { if (nposs > 0) {
@ -241,7 +246,7 @@ cell_t *aigetlastknownpos(lifeform_t *lf, lifeform_t *target, int *lastx, int *l
return NULL; return NULL;
} }
object_t *aigetrangedattack(lifeform_t *lf, enum RANGEATTACK *ra) { object_t *aigetrangedattack(lifeform_t *lf, enum RANGEATTACK *ra, int *range) {
int db = B_FALSE; int db = B_FALSE;
enum ATTRBRACKET iqb; enum ATTRBRACKET iqb;
object_t *o; object_t *o;
@ -256,7 +261,6 @@ object_t *aigetrangedattack(lifeform_t *lf, enum RANGEATTACK *ra) {
return NULL; return NULL;
} }
o = getfirearm(lf); o = getfirearm(lf);
if (o && getammo(o)) { if (o && getammo(o)) {
if (db) { if (db) {
@ -265,6 +269,7 @@ object_t *aigetrangedattack(lifeform_t *lf, enum RANGEATTACK *ra) {
if (db) dblog(".oO { will fire my gun (%s) at target. }",gunname); if (db) dblog(".oO { will fire my gun (%s) at target. }",gunname);
} }
*ra = RA_GUN; *ra = RA_GUN;
*range = getfirearmrange(o);
return o; return o;
} }
@ -280,6 +285,7 @@ object_t *aigetrangedattack(lifeform_t *lf, enum RANGEATTACK *ra) {
if (db) dblog(".oO { will zap %s instead of moving }", o->type->name); if (db) dblog(".oO { will zap %s instead of moving }", o->type->name);
*ra = RA_WAND; *ra = RA_WAND;
*range = getvisrange(lf); // ie unlimited
return o; return o;
} }
} }
@ -290,12 +296,14 @@ object_t *aigetrangedattack(lifeform_t *lf, enum RANGEATTACK *ra) {
if (o) { if (o) {
if (db) dblog(".oO { will throw %s at my target }", o->type->name); if (db) dblog(".oO { will throw %s at my target }", o->type->name);
*ra = RA_THROW; *ra = RA_THROW;
*range = getmaxthrowrange(lf, o);
return o; return o;
} }
} }
if (db) dblog(".oO { found no ranged attack. }"); if (db) dblog(".oO { found no ranged attack. }");
*ra = RA_NONE; *ra = RA_NONE;
*range = 0;
return NULL; return NULL;
} }
@ -360,6 +368,7 @@ void aigetspelltarget(lifeform_t *lf, objecttype_t *spelltype, lifeform_t *victi
nposs = 0; nposs = 0;
for (i = 0; i < lf->nlos; i++) { for (i = 0; i < lf->nlos; i++) {
if (lf->los[i] != lf->cell) {
object_t *o; object_t *o;
for (o = lf->los[i]->obpile->first ; o ; o = o->next) { for (o = lf->los[i]->obpile->first ; o ; o = o->next) {
if (!hasflag(o->flags, F_NOPICKUP) && if (!hasflag(o->flags, F_NOPICKUP) &&
@ -371,6 +380,7 @@ void aigetspelltarget(lifeform_t *lf, objecttype_t *spelltype, lifeform_t *victi
} }
if (nposs >= MAXPILEOBS) break; if (nposs >= MAXPILEOBS) break;
} }
}
// should always be true since we check this in aispellok // should always be true since we check this in aispellok
if (nposs > 0) { if (nposs > 0) {
if (spellob) *spellob = poss[rnd(0,nposs-1)]; if (spellob) *spellob = poss[rnd(0,nposs-1)];
@ -491,6 +501,7 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) {
enum OBTYPE spell; enum OBTYPE spell;
object_t *rangedob = NULL; object_t *rangedob = NULL;
enum RANGEATTACK rangedattack = RA_NONE; enum RANGEATTACK rangedattack = RA_NONE;
int shootrange = 0;
int movefailed = B_FALSE; int movefailed = B_FALSE;
// pet movement // pet movement
@ -575,6 +586,7 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) {
nposs = 0; nposs = 0;
for (i = 0; i < lf->nlos; i++) { for (i = 0; i < lf->nlos; i++) {
if (lf->los[i] != lf->cell) {
object_t *o; object_t *o;
for (o = lf->los[i]->obpile->first ; o ; o = o->next) { for (o = lf->los[i]->obpile->first ; o ; o = o->next) {
if (!hasflag(o->flags, F_NOPICKUP) && if (!hasflag(o->flags, F_NOPICKUP) &&
@ -586,6 +598,7 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) {
} }
if (nposs >= MAXPILEOBS) break; if (nposs >= MAXPILEOBS) break;
} }
}
if (nposs > 0) { if (nposs > 0) {
spellob = poss[rnd(0,nposs-1)]; spellob = poss[rnd(0,nposs-1)];
} else { } else {
@ -625,11 +638,13 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) {
// see if we have a ranged attack. if so, adjust wantdist // see if we have a ranged attack. if so, adjust wantdist
// to maintain distance. // to maintain distance.
rangedob = aigetrangedattack(lf, &rangedattack); rangedob = aigetrangedattack(lf, &rangedattack, &shootrange);
if (rangedattack != RA_NONE) { if (rangedattack != RA_NONE) { // ie if we found a ranged attack
// stay out of target's attack range
if (wantdistmin < 2) wantdistmin = 2; if (wantdistmin < 2) wantdistmin = 2;
if (wantdistmax < wantdistmin) wantdistmax = wantdistmin; // and stay within range for our ranged attack
if (wantdistmax < wantdistmin) wantdistmax = shootrange;
} }
} // end if attackok } // end if attackok
@ -648,8 +663,8 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) {
movefailed = B_TRUE; movefailed = B_TRUE;
} }
} else if (dist < wantdistmin) { } else if (dist < wantdistmin) {
if (db) dblog(".oO { moving away from target. }"); if (db) dblog(".oO { moving away from target to maintain mindist %d. }", wantdistmin);
if (!moveawayfrom(lf, target->cell, DT_ORTH)) { if (!moveawayfrom(lf, target->cell, DT_ORTH, B_KEEPLOF)) { // maintain LOF
// success // success
return B_FALSE; return B_FALSE;
} else { } else {
@ -868,6 +883,12 @@ int aipickupok(lifeform_t *lf, object_t *o) {
} }
int aiobok(lifeform_t *lf, object_t *o, lifeform_t *target) { int aiobok(lifeform_t *lf, object_t *o, lifeform_t *target) {
// non-humanoids can only use food.
if (!lfhasflag(lf, F_HUMANOID)) {
if (o->type->obclass->id != OC_FOOD) {
return B_FALSE;
}
}
switch (o->type->id) { switch (o->type->id) {
case OT_POT_INVIS: case OT_POT_INVIS:
case OT_WAND_INVIS: case OT_WAND_INVIS:
@ -964,7 +985,7 @@ void aiturn(lifeform_t *lf) {
if (isoutdoors(lf->cell->map) && pctchance(20)) { if (isoutdoors(lf->cell->map) && pctchance(20)) {
object_t *o; object_t *o;
say(lf, "Thanks for getting me out!", SV_TALK); say(lf, "Thanks for getting me out!", SV_TALK);
o = addob(master->pack, "manual"); o = addobfast(master->pack, OT_MANUAL);
if (o) { if (o) {
char obname[BUFLEN]; char obname[BUFLEN];
say(lf, "Here, let me teach you something as a reward.", SV_TALK); say(lf, "Here, let me teach you something as a reward.", SV_TALK);
@ -1012,11 +1033,11 @@ void aiturn(lifeform_t *lf) {
if (f) { if (f) {
if (pctchance(f->val[0])) { if (pctchance(f->val[0])) {
flag_t *poss[MAXCANDIDATES]; flag_t *poss[MAXCANDIDATES];
int nposs = 0; int nposs = 0,i;
for (f = lf->flags->first ;f ; f = f->next) {
if (f->id == F_RANDOMTALK) { getflags(lf->flags, F_RANDOMTALK, F_NONE);
poss[nposs++] = f; for (i = 0; i < nretflags; i++) {
} poss[nposs++] = retflag[i];
} }
if (nposs) { if (nposs) {
int vol; int vol;
@ -1186,7 +1207,7 @@ void aiturn(lifeform_t *lf) {
if ( hasobwithflag(lf->cell->obpile, F_DEEPWATER) && if ( hasobwithflag(lf->cell->obpile, F_DEEPWATER) &&
!hasobwithflag(target->cell->obpile, F_DEEPWATER)) { !hasobwithflag(target->cell->obpile, F_DEEPWATER)) {
// move away! // move away!
if (!moveawayfrom(lf, target->cell, DT_ORTH)) { if (!moveawayfrom(lf, target->cell, DT_ORTH, B_FALSE)) {
return; return;
} }
} }
@ -1326,6 +1347,7 @@ void aiturn(lifeform_t *lf) {
newtarget = NULL; newtarget = NULL;
for (n = 0; n < lf->nlos; n++) { for (n = 0; n < lf->nlos; n++) {
lifeform_t *who; lifeform_t *who;
if (lf->los[n] != lf->cell) {
who = lf->los[n]->lf; who = lf->los[n]->lf;
if (who && cansee(lf, who)) { if (who && cansee(lf, who)) {
if (lfhasflagval(lf, F_HATESRACE, who->race->id, NA, NA, NULL) || if (lfhasflagval(lf, F_HATESRACE, who->race->id, NA, NA, NULL) ||
@ -1336,9 +1358,11 @@ void aiturn(lifeform_t *lf) {
} }
} }
} }
}
if (!newtarget) { if (!newtarget) {
// now look for enemies // now look for enemies
for (n = 0; n < lf->nlos; n++) { for (n = 0; n < lf->nlos; n++) {
if (lf->los[n] != lf->cell) {
lifeform_t *who; lifeform_t *who;
who = lf->los[n]->lf; who = lf->los[n]->lf;
if (who && cansee(lf, who)) { if (who && cansee(lf, who)) {
@ -1350,6 +1374,7 @@ void aiturn(lifeform_t *lf) {
} }
} }
} }
}
if (newtarget) { if (newtarget) {
if (aiattack(lf, newtarget, AI_FOLLOWTIME)) { if (aiattack(lf, newtarget, AI_FOLLOWTIME)) {
@ -1588,6 +1613,7 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
nposs = 0; nposs = 0;
for (i = 0; i < lf->nlos; i++) { for (i = 0; i < lf->nlos; i++) {
if (lf->los[i] != lf->cell) {
object_t *o; object_t *o;
for (o = lf->los[i]->obpile->first ; o ; o = o->next) { for (o = lf->los[i]->obpile->first ; o ; o = o->next) {
if (!hasflag(o->flags, F_NOPICKUP) && if (!hasflag(o->flags, F_NOPICKUP) &&
@ -1598,6 +1624,7 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
if (ok) break; if (ok) break;
} }
} }
}
} else if (ot->id == OT_S_CHARM) { } else if (ot->id == OT_S_CHARM) {
if (getnearbypeaceful(lf)) { if (getnearbypeaceful(lf)) {
ok = B_TRUE; ok = B_TRUE;
@ -1683,6 +1710,12 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
if ((ot->id == OT_S_SLOW) && (lfhasflag(victim, F_SLOWACT) || lfhasflag(victim, F_SLOWACTMOVE)) ) { if ((ot->id == OT_S_SLOW) && (lfhasflag(victim, F_SLOWACT) || lfhasflag(victim, F_SLOWACTMOVE)) ) {
specificcheckok = B_FALSE; specificcheckok = B_FALSE;
} }
if ((ot->id == OT_S_SMITEGOOD) && (getalignment(victim) != AL_GOOD)) {
specificcheckok = B_FALSE;
}
if ((ot->id == OT_S_SMITEEVIL) && (getalignment(victim) != AL_EVIL)) {
specificcheckok = B_FALSE;
}
if ((ot->id == OT_A_SPRINT) && lfhasflag(lf, F_SPRINTING)) { if ((ot->id == OT_A_SPRINT) && lfhasflag(lf, F_SPRINTING)) {
specificcheckok = B_FALSE; specificcheckok = B_FALSE;
} }
@ -1749,6 +1782,40 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
return B_TRUE; return B_TRUE;
} }
int aiwants(lifeform_t *lf, object_t *o, int *covets) {
enum OBTYPE oid[MAXPILEOBS];
int oidcovet[MAXPILEOBS];
int noids = 0;
enum FLAG wantflag[MAXPILEOBS];
int wantflagcovet[MAXPILEOBS];
int nwantflags = 0;
makewantedoblist(lf, &noids, oid, oidcovet, &nwantflags, wantflag, wantflagcovet);
return aiwants_real(lf, o, covets, &noids, oid, oidcovet, &nwantflags, wantflag, wantflagcovet);
}
int aiwants_real(lifeform_t *lf, object_t *o, int *covets, int *noids, enum OBTYPE *oid, int *oidcovet,int *nwantflags, enum FLAG *wantflag, int *wantflagcovet) {
int i;
for (i = 0; i < *noids; i++) {
if (oid[i] == o->type->id) {
if (covets) {
*covets = oidcovet[i];
}
return B_TRUE;
}
}
for (i = 0; i < *nwantflags; i++) {
if (hasflag(o->flags, wantflag[i])) {
if ((wantflag[i] == F_EDIBLE) && !caneat(lf, o)) { // special case
} else {
if (covets) {
*covets = wantflagcovet[i];
}
return B_TRUE;
}
}
}
return B_FALSE;
}
lifeform_t *gettargetlf(lifeform_t *lf) { lifeform_t *gettargetlf(lifeform_t *lf) {
flag_t *f; flag_t *f;
@ -1794,9 +1861,10 @@ object_t *hasbetterweapon(lifeform_t *lf, obpile_t *op) {
} }
// returns B_TRUE if we did something // returns B_TRUE if we did something
int lookforobs(lifeform_t *lf) { int lookforobs(lifeform_t *lf) {
object_t *o; object_t *o,*nexto;
enum OBTYPE oid[MAXPILEOBS]; enum OBTYPE oid[MAXPILEOBS];
int oidcovet[MAXPILEOBS]; int oidcovet[MAXPILEOBS];
int noids = 0; int noids = 0;
@ -1805,11 +1873,11 @@ int lookforobs(lifeform_t *lf) {
int nwantflags = 0; int nwantflags = 0;
flag_t *f; flag_t *f;
cell_t *c; cell_t *c;
int n;
int i; int i;
int db = B_FALSE; int db = B_FALSE;
lifeform_t *target; lifeform_t *target;
int targdist = 999; int targdist = 999;
int covets = B_FALSE;
target = gettargetlf(lf); target = gettargetlf(lf);
if (target) { if (target) {
@ -1822,41 +1890,16 @@ int lookforobs(lifeform_t *lf) {
db = B_FALSE; db = B_FALSE;
} }
// construct a list of objects which we want makewantedoblist(lf, &noids, oid, oidcovet, &nwantflags, wantflag, wantflagcovet);
noids = 0;
for (f = lf->flags->first ; f ; f = f->next) {
if (f->id == F_WANTS) {
oid[noids] = f->val[0];
oidcovet[noids] = (f->val[1] == B_COVETS) ? B_TRUE : B_FALSE;
noids++;
} else if (f->id == F_WANTSOBFLAG) {
wantflag[nwantflags] = f->val[0];
wantflagcovet[noids] = (f->val[1] == B_COVETS) ? B_TRUE : B_FALSE;
nwantflags++;
}
}
if (hasflag(lf->flags, F_HUNGER)) {
// monsters dont normaly need to eat. if they have hunger, it's due
// to a spell.
wantflag[nwantflags] = F_EDIBLE;
wantflagcovet[nwantflags] = B_TRUE;
nwantflags++;
}
// current cell has an object we want? // current cell has an object we want?
o = hasobmulti(lf->cell->obpile, oid, noids); for (o = lf->cell->obpile->first ; o ; o = nexto) {
if (o && !isdangerousob(o, lf, B_TRUE) && aipickupok(lf, o)) { nexto = o->next;
if (aiwants_real(lf, o, &covets, &noids, oid, oidcovet, &nwantflags, wantflag, wantflagcovet)) {
int getit = B_TRUE; int getit = B_TRUE;
// if we are in battle only go for it if we covet it // if we are in battle only go for it if we covet it
if (target) { if (target && !covets) getit = B_FALSE;
int nn; if (isdangerousob(o, lf, B_TRUE) || !aipickupok(lf, o)) getit = B_FALSE;
for (nn = 0; nn < noids; nn++) {
if (oid[nn] == o->id) break;
}
if (!oidcovet[nn]) getit = B_FALSE;
}
if (getit) { if (getit) {
if (db) dblog(".oO { current cell has ob i want (%s) }",o->type->name); if (db) dblog(".oO { current cell has ob i want (%s) }",o->type->name);
// try to pick it up // try to pick it up
@ -1866,23 +1909,8 @@ int lookforobs(lifeform_t *lf) {
if (db) dblog(".oO { eating %s failed }",o->type->name); if (db) dblog(".oO { eating %s failed }",o->type->name);
} }
} }
// has an object with a flag we want?
for (n = 0; n < nwantflags; n++) {
o = hasobwithflag(lf->cell->obpile, wantflag[n]);
// if we are in battle only go for it if we covet it
if (target && !wantflagcovet[n]) continue;
if (o && !isdangerousob(o, lf, B_TRUE) && aipickupok(lf, o) && (canpickup(lf, o, 1) || caneat(lf,o)) ) {
if (db) dblog(".oO { current cell has ob with flag i want (%s) }",o->type->name);
// try to pick it up
if (!aipickup(lf, o)) return B_TRUE;
if (db) dblog(".oO { pickup of %s with wantflag failed, trying to eat! }",o->type->name);
if (!eat(lf, o)) return B_TRUE;
if (db) dblog(".oO { eating %s with wantflag failed }",o->type->name);
}
} }
// current cell has better weapon? // current cell has better weapon?
if (lfhasflag(lf, F_HUMANOID) && hasbp(lf, BP_WEAPON)) { if (lfhasflag(lf, F_HUMANOID) && hasbp(lf, BP_WEAPON)) {
f = hasflag(lf->flags, F_WANTSBETTERWEP); f = hasflag(lf->flags, F_WANTSBETTERWEP);
@ -1924,44 +1952,30 @@ int lookforobs(lifeform_t *lf) {
int gothere = B_FALSE; int gothere = B_FALSE;
c = lf->los[i]; c = lf->los[i];
if (!c->lf && !lfhasflagval(lf, F_IGNORECELL, c->x, c->y, NA, NULL)) { if ((c != lf->cell) && !c->lf && !lfhasflagval(lf, F_IGNORECELL, c->x, c->y, NA, NULL)) {
int celldist; int celldist;
celldist = getcelldist(lf->cell, c); celldist = getcelldist(lf->cell, c);
o = hasobmulti(c->obpile, oid, noids); for (o = c->obpile->first ; o ; o = nexto) {
if (o && !isdangerousob(o, lf, B_TRUE) && aipickupok(lf, o)) { nexto = o->next;
if (aiwants_real(lf, o, &covets, &noids, oid, oidcovet, &nwantflags, wantflag, wantflagcovet)) {
gothere = B_TRUE;
// if we are in battle only go for it if we covet it and // if we are in battle only go for it if we covet it and
// it's closer than our target // it's closer than our target
if (target) { if (target) {
int nn; if (!covets || (celldist > targdist)) {
for (nn = 0; nn < noids; nn++) { gothere = B_FALSE;
if (oid[nn] == o->id) break;
}
if (oidcovet[nn]) {
if (celldist <= targdist) {
if (db) dblog(".oO { remote cell has ob i want (%s). setting f_targetcell. }",o->type->name);
gothere = B_TRUE;
}
}
} else {
if (db) dblog(".oO { remote cell has ob i want (%s). setting f_targetcell. }",o->type->name);
gothere = B_TRUE;
} }
} }
if (!gothere) { if (gothere) {
// has an object with a flag we want? if (db) dblog(".oO { remote cell has ob i want (%s). setting f_targetcell. }",o->type->name);
for (n = 0; n < nwantflags; n++) { break;
// if we are in battle only go for it if we covet it }
if (target && !wantflagcovet[n]) continue; } // end if aiwantsthisob
} // end foreach ob in cell
o = hasobwithflag(c->obpile, wantflag[n]);
if (o && !isdangerousob(o, lf, B_TRUE) && aipickupok(lf, o)) {
if (db) dblog(".oO { remote cell has ob with flag i want (%s) }", o->type->name);
gothere = B_TRUE;
}
}
}
if (!gothere) { if (!gothere) {
if (lfhasflag(lf, F_HUMANOID) && hasbp(lf, BP_WEAPON)) { if (lfhasflag(lf, F_HUMANOID) && hasbp(lf, BP_WEAPON)) {
// remote cell has better weapon? // remote cell has better weapon?
@ -1999,7 +2013,6 @@ int lookforobs(lifeform_t *lf) {
} }
} }
if (gothere) { if (gothere) {
// cast a spell? // cast a spell?
if (cancast(lf, OT_S_CALLWIND, NULL) && haslof(lf->cell, c, LOF_NEED, NULL)) { if (cancast(lf, OT_S_CALLWIND, NULL) && haslof(lf->cell, c, LOF_NEED, NULL)) {
@ -2020,6 +2033,35 @@ int lookforobs(lifeform_t *lf) {
return B_FALSE; return B_FALSE;
} }
void makewantedoblist(lifeform_t *lf, int *noids, enum OBTYPE *oid, int *oidcovet,int *nwantflags, enum FLAG *wantflag, int *wantflagcovet) {
int i;
flag_t *f;
// construct a list of objects which we want
*noids = 0;
getflags(lf->flags, F_WANTS, F_WANTSOBFLAG, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f->id == F_WANTS) {
oid[*noids] = f->val[0];
oidcovet[*noids] = (f->val[1] == B_COVETS) ? B_TRUE : B_FALSE;
(*noids)++;
} else if (f->id == F_WANTSOBFLAG) {
wantflag[*nwantflags] = f->val[0];
wantflagcovet[*nwantflags] = (f->val[1] == B_COVETS) ? B_TRUE : B_FALSE;
(*nwantflags)++;
}
}
if (hasflag(lf->flags, F_HUNGER)) {
// monsters dont normaly need to eat. if they have hunger, it's due
// to a spell.
wantflag[*nwantflags] = F_EDIBLE;
wantflagcovet[*nwantflags] = B_TRUE;
(*nwantflags)++;
}
}
// try to use an item with the given flag on ourself. // try to use an item with the given flag on ourself.
// returns B_FALSE if successful // returns B_FALSE if successful
int useitemwithflag(lifeform_t *lf, enum FLAG whichflag) { int useitemwithflag(lifeform_t *lf, enum FLAG whichflag) {

5
ai.h
View File

@ -5,7 +5,7 @@ int aiattack(lifeform_t *lf, lifeform_t *victim, int timelimit);
enum OBTYPE aigetattackspell(lifeform_t *lf, lifeform_t *victim); enum OBTYPE aigetattackspell(lifeform_t *lf, lifeform_t *victim);
enum OBTYPE aigetfleespell(lifeform_t *lf); enum OBTYPE aigetfleespell(lifeform_t *lf);
cell_t *aigetlastknownpos(lifeform_t *lf, lifeform_t *target, int *lastx, int *lasty, int *lastdir); cell_t *aigetlastknownpos(lifeform_t *lf, lifeform_t *target, int *lastx, int *lasty, int *lastdir);
object_t *aigetrangedattack(lifeform_t *lf, enum RANGEATTACK *ra); object_t *aigetrangedattack(lifeform_t *lf, enum RANGEATTACK *ra, int *range);
void aigetspelltarget(lifeform_t *lf, objecttype_t *spelltype, lifeform_t *victim, lifeform_t **spelllf, cell_t **spellcell, object_t **spellob, enum FLAG purpose); 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); object_t *aigetwand(lifeform_t *lf, enum FLAG purpose);
flag_t *aigoto(lifeform_t *lf, cell_t *c, enum MOVEREASON why, void *data, int timelimit); flag_t *aigoto(lifeform_t *lf, cell_t *c, enum MOVEREASON why, void *data, int timelimit);
@ -17,8 +17,11 @@ int aipickupok(lifeform_t *lf, object_t *o);
int aiobok(lifeform_t *lf, object_t *o, lifeform_t *target); int aiobok(lifeform_t *lf, object_t *o, lifeform_t *target);
int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG purpose); int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG purpose);
void aiturn(lifeform_t *lf); void aiturn(lifeform_t *lf);
int aiwants(lifeform_t *lf, object_t *o, int *covets);
int aiwants_real(lifeform_t *lf, object_t *o, int *covets, int *noids, enum OBTYPE *oid, int *oidcovet,int *nwantflags, enum FLAG *wantflag, int *wantflagcovet);
lifeform_t *gettargetlf(lifeform_t *lf); lifeform_t *gettargetlf(lifeform_t *lf);
object_t *hasbetterarmour(lifeform_t *lf, obpile_t *op); object_t *hasbetterarmour(lifeform_t *lf, obpile_t *op);
object_t *hasbetterweapon(lifeform_t *lf, obpile_t *op); object_t *hasbetterweapon(lifeform_t *lf, obpile_t *op);
int lookforobs(lifeform_t *lf); int lookforobs(lifeform_t *lf);
void makewantedoblist(lifeform_t *lf, int *noids, enum OBTYPE *oid, int *oidcovet,int *nwantflags, enum FLAG *wantflag, int *wantflagcovet);
int useitemwithflag(lifeform_t *lf, enum FLAG whichflag); int useitemwithflag(lifeform_t *lf, enum FLAG whichflag);

View File

@ -24,6 +24,9 @@ int applyarmourdamage(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damty
object_t *armour = NULL; object_t *armour = NULL;
int damtaken = 0; int damtaken = 0;
// first of all, only apply some of the damage
dam /= 2;
// figure out what bit of armour was hit // figure out what bit of armour was hit
if (dam == 0) { if (dam == 0) {
return 0; return 0;
@ -99,22 +102,30 @@ int applyarmourdamage(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damty
void applyarmourdamreduction(lifeform_t *lf, object_t *wep, int reduceamt, int *dam, enum DAMTYPE damtype) { void applyarmourdamreduction(lifeform_t *lf, object_t *wep, int reduceamt, int *dam, enum DAMTYPE damtype) {
int db = B_FALSE; int db = B_FALSE;
int newdam = 0;
// armour can't stop armour-piercing weapons // armour can't stop armour-piercing weapons
if (hasflag(wep->flags, F_ARMOURPIERCE)) { if (hasflag(wep->flags, F_ARMOURPIERCE)) {
reduceamt = 0; reduceamt = 0;
} }
// figure out reduced damage value
if (dam) {
newdam = *dam;
if ((*dam >= 1) && (reduceamt >= 0)) {
newdam -= reduceamt;
limit(&newdam, 1, NA); // don't reduce to <1 damage
}
if (db) { if (db) {
if (reduceamt > 0) { if ((*dam >= 1) && (reduceamt > 0)) {
dblog("Armour reduces dam by %d to %d.",reduceamt,dam); dblog("Armour reduces dam=%d by %d to %d.",*dam,reduceamt,newdam);
} else { } else {
dblog("No armour dam reduction."); dblog("No armour dam reduction.");
} }
} }
if (dam && (reduceamt >= 0)) {
*dam -= reduceamt; *dam = newdam;
if (*dam < 0) *dam = 0;
} }
} }
@ -267,7 +278,7 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
ot = findot(f->val[0]); ot = findot(f->val[0]);
if (ot) { if (ot) {
wep[nweps] = addob(op, ot->name); wep[nweps] = addobfast(op, ot->id);
validwep[nweps] = B_TRUE; validwep[nweps] = B_TRUE;
damflag[nweps] = f; damflag[nweps] = f;
nweps++; nweps++;
@ -681,6 +692,12 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
} }
} }
if (i == 0) {
if (lfhasflag(lf, F_HOLYAURA) && isvulnto(victim->flags, DT_HOLY)) {
damtype[i] = DT_HOLY;
}
}
// modify based on resistances // modify based on resistances
adjustdamlf(victim, &dam[i], damtype[i]); adjustdamlf(victim, &dam[i], damtype[i]);
//dblog("adjusted for lf to dam[%d] = %d",i,dam[i]); //dblog("adjusted for lf to dam[%d] = %d",i,dam[i]);
@ -706,6 +723,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
fatal = B_TRUE; fatal = B_TRUE;
} }
// monsters feigning death? // monsters feigning death?
if (lfhasflag(victim, F_FEIGNINGDEATH)) { if (lfhasflag(victim, F_FEIGNINGDEATH)) {
killflagsofid(victim->flags, F_FEIGNINGDEATH); killflagsofid(victim->flags, F_FEIGNINGDEATH);
@ -846,12 +864,11 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
} else { } else {
strcpy(buf, attackername2); strcpy(buf, attackername2);
} }
losehp_real(victim, dam[i], damtype[i], lf, buf, B_FALSE, NULL); losehp_real(victim, dam[i], damtype[i], lf, buf, B_FALSE, NULL);
// victim's armour loses hp // victim's armour loses hp
if (reduceamt) { if (reduceamt) {
applyarmourdamage(victim, wep, reduceamt, damtype[i]); applyarmourdamage(victim, wep, dam[i], damtype[i]);
// train armour // train armour
practice(victim, SK_ARMOUR, 1); practice(victim, SK_ARMOUR, 1);
} }
@ -1078,11 +1095,31 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
if (isplayer(lf)) { if (isplayer(lf)) {
if (attackedfriend) { if (attackedfriend) {
angergodmaybe(R_GODMERCY, 100); angergodmaybe(R_GODMERCY, 100);
} else if (attackedhelpless) { angergodmaybe(R_GODPURITY, 100);
angergodmaybe(R_GODMERCY, 50); switch (getalignment(victim)) {
} else if (lfhasflag(lf, F_USEDPOISON)) { case AL_EVIL:
angergodmaybe(R_GODDEATH, 20); // even more
break;
case AL_GOOD:
angergodmaybe(R_GODPURITY, 20); // even more
break;
default:
break;
}
}
if (attackedhelpless) {
angergodmaybe(R_GODMERCY, 100);
angergodmaybe(R_GODPURITY, 100);
if (getalignment(victim) != AL_EVIL) {
pleasegodmaybe(R_GODTHIEVES, 5);
pleasegodmaybe(R_GODDEATH, 10);
}
}
if (lfhasflag(lf, F_USEDPOISON)) {
killflagsofid(lf->flags, F_USEDPOISON); killflagsofid(lf->flags, F_USEDPOISON);
angergodmaybe(R_GODPURITY, 100);
angergodmaybe(R_GODMERCY, 50); angergodmaybe(R_GODMERCY, 50);
pleasegodmaybe(R_GODDEATH, 3);
} }
} }
@ -1199,6 +1236,9 @@ int attackob(lifeform_t *lf, object_t *o, object_t *wep, flag_t *damflag) {
// object loses hp // object loses hp
takedamage(o, dam[i], damtype[i]); takedamage(o, dam[i], damtype[i]);
if (isplayer(lf) && hasflag(o->flags, F_LOCKED)) {
angergodmaybe(R_GODTHIEVES, 25);
}
} // end foreach damtype } // end foreach damtype
@ -1389,11 +1429,13 @@ char *getattackverb(lifeform_t *lf, object_t *wep, enum DAMTYPE damtype, int dam
return "incinerate"; return "incinerate";
} }
} else if (damtype == DT_HOLY) { } else if (damtype == DT_HOLY) {
switch (rnd(1,2)) { switch (rnd(1,3)) {
case 1: case 1:
return "smite"; return "smite";
case 2: case 2:
return "cleanse"; return "cleanse";
case 3:
return "purify";
} }
} else if (damtype == DT_PIERCE) { } else if (damtype == DT_PIERCE) {
if (pct <= 5) { if (pct <= 5) {
@ -1962,7 +2004,7 @@ void wepeffects(flagpile_t *fp, cell_t *where, flag_t *damflag, int dam) {
if (f->id == F_FLAMESTRIKE) { if (f->id == F_FLAMESTRIKE) {
if (!hasob(where->obpile, OT_FIRESMALL)) { if (!hasob(where->obpile, OT_FIRESMALL)) {
// ignite! // ignite!
addob(where->obpile, "small fire"); addobfast(where->obpile, OT_FIRESMALL);
// announce // announce
if (haslos(player, where)) { if (haslos(player, where)) {
msg("^wA column of fire erupts from the ground!"); msg("^wA column of fire erupts from the ground!");

29
defs.h
View File

@ -661,7 +661,7 @@ enum RACECLASS {
RC_UNDEAD, RC_UNDEAD,
}; };
#define MAXGODS 3 #define MAXGODS 4
enum RACE { enum RACE {
R_NONE = 0, R_NONE = 0,
@ -677,9 +677,10 @@ enum RACE {
R_PRISONER, R_PRISONER,
R_TOWNGUARD, R_TOWNGUARD,
// gods // gods
R_GODDEATH, R_GODPURITY, // amberon
R_GODGREED, R_GODTHIEVES, // felix
R_GODMERCY, R_GODDEATH, // hecta
R_GODMERCY, // yumi
// monsters // monsters
R_BEHOLDER, R_BEHOLDER,
R_BUGBEAR, R_BUGBEAR,
@ -992,6 +993,7 @@ enum OBTYPE {
OT_S_BLINDNESS, OT_S_BLINDNESS,
OT_S_POISONBOLT, OT_S_POISONBOLT,
OT_S_POSSESSION, OT_S_POSSESSION,
OT_S_SMITEGOOD,
OT_S_STENCH, OT_S_STENCH,
// -- divination // -- divination
OT_S_DETECTAURA, OT_S_DETECTAURA,
@ -1038,10 +1040,12 @@ enum OBTYPE {
OT_S_SLOW, OT_S_SLOW,
OT_S_LEVITATION, OT_S_LEVITATION,
OT_S_FLIGHT, OT_S_FLIGHT,
// -- life // -- life / cleric
OT_S_HEALING, OT_S_HEALING,
OT_S_HEALINGMIN, OT_S_HEALINGMIN,
OT_S_HEALINGMAJ, OT_S_HEALINGMAJ,
OT_S_HOLYAURA,
OT_S_SMITEEVIL,
OT_S_SPEAKDEAD, OT_S_SPEAKDEAD,
OT_S_TURNUNDEAD, OT_S_TURNUNDEAD,
// -- mental / psionic // -- mental / psionic
@ -1174,6 +1178,7 @@ enum OBTYPE {
OT_WAND_POLYMORPH, OT_WAND_POLYMORPH,
OT_WAND_REVEALHIDDEN, OT_WAND_REVEALHIDDEN,
OT_WAND_SLOW, OT_WAND_SLOW,
OT_WAND_TURNUNDEAD,
OT_WAND_WEAKNESS, OT_WAND_WEAKNESS,
OT_WAND_WONDER, OT_WAND_WONDER,
// tools - unique // tools - unique
@ -1514,6 +1519,13 @@ enum ALLEGIENCE {
AL_FRIENDLY, // will help you fight AL_FRIENDLY, // will help you fight
}; };
enum ALIGNMENT {
AL_NONE,
AL_GOOD,
AL_NEUTRAL,
AL_EVIL,
};
enum POISONSEVERITY { enum POISONSEVERITY {
PS_DISEASE, PS_DISEASE,
PS_POISON, PS_POISON,
@ -1858,8 +1870,11 @@ enum FLAG {
F_DONEDARKMSG, // tells the game not to say 'it is very dark here' F_DONEDARKMSG, // tells the game not to say 'it is very dark here'
F_DONELISTEN, // supress further 'you hear xx' messages this turn. F_DONELISTEN, // supress further 'you hear xx' messages this turn.
// lifeform flags / lf flags // lifeform flags / lf flags
F_ALIGNMENT, // v0 = al_good, al_neutral, al_evil. default neutral.
F_PIETY, // for god lifeforms - tracks player's piety with them F_PIETY, // for god lifeforms - tracks player's piety with them
F_PRAYEDTO, // player has prayed to this god before. F_PRAYEDTO, // player has prayed to this god before.
F_GAVEMONEY, // v0 tracks how much money we gave away this turn
// used for r_godgreed anger effects.
F_COUNTER, // generic counter flag for race abilities. F_COUNTER, // generic counter flag for race abilities.
F_DEBUG, // debugging enabled F_DEBUG, // debugging enabled
F_ACCURACYMOD, // modify your accuracy by val0 F_ACCURACYMOD, // modify your accuracy by val0
@ -2166,6 +2181,8 @@ enum FLAG {
F_PARALYZED,// cannot do anything F_PARALYZED,// cannot do anything
F_PRONE, // lying on the ground F_PRONE, // lying on the ground
F_FROZEN, // made of ice F_FROZEN, // made of ice
F_HOLYAURA, // holy aura - attacks deal holy damage to vulnerable
// enemies.
F_LEVITATING, // like flying but uncontrolled F_LEVITATING, // like flying but uncontrolled
F_MAGSHIELD,// magnetic shield F_MAGSHIELD,// magnetic shield
F_NAUSEATED, // lf has a stench penalty of v0 (-v0*10 to hit). F_NAUSEATED, // lf has a stench penalty of v0 (-v0*10 to hit).
@ -2335,6 +2352,8 @@ enum PIETYLEV {
#define B_FALSE (0) #define B_FALSE (0)
#define B_TRUE (-1) #define B_TRUE (-1)
#define B_KEEPLOF (-1)
#define B_MALE (0) #define B_MALE (0)
#define B_FEMALE (-1) #define B_FEMALE (-1)

39
flag.c
View File

@ -19,6 +19,8 @@ extern int statdirty;
extern lifeform_t *player; extern lifeform_t *player;
int flagdb = B_FALSE;
altflagval_t *addaltval(flag_t *f, enum FLAG id, int val1, int val2, int val3, char *text) { altflagval_t *addaltval(flag_t *f, enum FLAG id, int val1, int val2, int val3, char *text) {
f->altval = malloc(sizeof(altflagval_t)); f->altval = malloc(sizeof(altflagval_t));
f->altval->id = id; f->altval->id = id;
@ -441,37 +443,40 @@ flag_t *hasflag_real(flagpile_t *fp, int id, int wantknown, flag_t *exception) {
owner = fp->owner; owner = fp->owner;
int pos; int pos;
int l,r; int l,r;
int iter = 0; int iter = 0,subiter = 0;
int db = B_FALSE; int db = B_FALSE;
if (flagdb) db = B_TRUE;
if (db) dblog("hasflag %d in flagpile with %d entries", id, fp->nitems); if (db) dblog("hasflag %d in flagpile with %d entries", id, fp->nitems);
// binary search for this flag id. // binary search for this flag id.
l = 0; l = 0;
r = fp->nitems-1; r = fp->nitems-1;
while (!searchfrom) { while (!searchfrom) {
if (db) dblog(" iter#%d: l=%d,r=%d", iter, l, r); //if (db) dblog(" iter#%d: l=%d,r=%d", iter, l, r);
if (r < l) { if (r < l) {
// NOT FOUND. // NOT FOUND.
if (db) dblog(" r < l: not found!"); //if (db) dblog(" r < l: not found!");
break; break;
} else if (fp->item[l]->id > id) { } else if (fp->item[l]->id > id) {
// NOT FOUND. // NOT FOUND.
if (db) dblog(" leftid %d > wantid %d. not found!",fp->item[l]->id, id); //if (db) dblog(" leftid %d > wantid %d. not found!",fp->item[l]->id, id);
break; break;
} else if (fp->item[r]->id < id) { } else if (fp->item[r]->id < id) {
// NOT FOUND. // NOT FOUND.
if (db) dblog(" rightid %d > wantid %d. not found!",fp->item[r]->id, id); //if (db) dblog(" rightid %d > wantid %d. not found!",fp->item[r]->id, id);
break; break;
} }
// half way inbetween l and r // half way inbetween l and r
pos = ((l+r)/2); pos = ((l+r)/2);
f = fp->item[pos]; f = fp->item[pos];
if (db) dblog(" iter#%d: pos=%d. item here is %d (looking for %d)", iter, pos, f->id, id); //if (db) dblog(" iter#%d: pos=%d. item here is %d (looking for %d)", iter, pos, f->id, id);
if (f->id == id) { if (f->id == id) {
// go back to first occurence // go back to first occurence
while (f->prev && (f->prev->id == id)) { while (f->prev && (f->prev->id == id)) {
f = f->prev; f = f->prev;
iter++;
} }
searchfrom = f; searchfrom = f;
break; break;
@ -482,6 +487,7 @@ flag_t *hasflag_real(flagpile_t *fp, int id, int wantknown, flag_t *exception) {
// go right // go right
l = pos+1; l = pos+1;
} }
iter++;
} }
@ -499,10 +505,11 @@ flag_t *hasflag_real(flagpile_t *fp, int id, int wantknown, flag_t *exception) {
break; break;
} else { } else {
f = f->next; f = f->next;
subiter++;
} }
} }
if (db) dblog("finished - %s", foundflag ? "found it" : "NOT FOUND"); if (db) dblog("finished - %s - iter=%d, subiter=%d", foundflag ? "found it" : "NOT FOUND",iter,subiter);
return foundflag; return foundflag;
/* /*
@ -553,33 +560,36 @@ flag_t *hasflagval_real(flagpile_t *fp, int id, int val1, int val2, int val3, ch
int iter = 0; int iter = 0;
int db = B_FALSE; int db = B_FALSE;
if (db) dblog("hasflag %d in flagpile with %d entries", id, fp->nitems); if (flagdb) db = B_TRUE;
//if (db) dblog("hasflag %d in flagpile with %d entries", id, fp->nitems);
// binary search for this flag id. // binary search for this flag id.
l = 0; l = 0;
r = fp->nitems-1; r = fp->nitems-1;
while (!searchfrom) { while (!searchfrom) {
if (db) dblog(" iter#%d: l=%d,r=%d", iter, l, r); //if (db) dblog(" iter#%d: l=%d,r=%d", iter, l, r);
if (r < l) { if (r < l) {
// NOT FOUND. // NOT FOUND.
if (db) dblog(" r < l: not found!"); //if (db) dblog(" r < l: not found!");
break; break;
} else if (fp->item[l]->id > id) { } else if (fp->item[l]->id > id) {
// NOT FOUND. // NOT FOUND.
if (db) dblog(" leftid %d > wantid %d. not found!",fp->item[l]->id, id); //if (db) dblog(" leftid %d > wantid %d. not found!",fp->item[l]->id, id);
break; break;
} else if (fp->item[r]->id < id) { } else if (fp->item[r]->id < id) {
// NOT FOUND. // NOT FOUND.
if (db) dblog(" rightid %d > wantid %d. not found!",fp->item[r]->id, id); //if (db) dblog(" rightid %d > wantid %d. not found!",fp->item[r]->id, id);
break; break;
} }
// half way inbetween l and r // half way inbetween l and r
pos = ((l+r)/2); pos = ((l+r)/2);
f = fp->item[pos]; f = fp->item[pos];
if (db) dblog(" iter#%d: pos=%d. item here is %d (looking for %d)", iter, pos, f->id, id); //if (db) dblog(" iter#%d: pos=%d. item here is %d (looking for %d)", iter, pos, f->id, id);
if (f->id == id) { if (f->id == id) {
// go back to first occurence // go back to first occurence
while (f->prev && (f->prev->id == id)) { while (f->prev && (f->prev->id == id)) {
iter++;
f = f->prev; f = f->prev;
} }
searchfrom = f; searchfrom = f;
@ -591,6 +601,7 @@ flag_t *hasflagval_real(flagpile_t *fp, int id, int val1, int val2, int val3, ch
// go right // go right
l = pos+1; l = pos+1;
} }
iter++;
} }
@ -612,7 +623,7 @@ flag_t *hasflagval_real(flagpile_t *fp, int id, int val1, int val2, int val3, ch
f = f->next; f = f->next;
} }
if (db) dblog("finished - %s", foundflag ? "found it" : "NOT FOUND"); if (db) dblog("finished - %s - iter=%d", foundflag ? "found it" : "NOT FOUND", iter );
return foundflag; return foundflag;

235
god.c
View File

@ -75,6 +75,7 @@ void angergod(enum RACE rid, int amt) {
nposs++; nposs++;
} }
} }
for (f = player->flags->first ; f ; f = f->next) { for (f = player->flags->first ; f ; f = f->next) {
if ((f->lifetime == FROMGODGIFT) && (f->obfrom == god->race->id)) { if ((f->lifetime == FROMGODGIFT) && (f->obfrom == god->race->id)) {
poss[nposs] = f; poss[nposs] = f;
@ -95,13 +96,14 @@ void angergod(enum RACE rid, int amt) {
// then... // then...
if (piety > -100) { if (piety > -100) {
int i,n;
// minor bad stuff // minor bad stuff
switch (rid) { switch (rid) {
case R_GODDEATH: case R_GODDEATH:
castspell(god, OT_S_DRAINLIFE, player, NULL, player->cell); castspell(god, OT_S_DRAINLIFE, player, NULL, player->cell);
castspell(god, OT_S_PAIN, player, NULL, player->cell); castspell(god, OT_S_PAIN, player, NULL, player->cell);
break; break;
case R_GODGREED: case R_GODTHIEVES:
// take a random object // take a random object
msg("\"Yoink!\""); msg("\"Yoink!\"");
castspell(god, OT_S_CONFISCATE, player, NULL, player->cell); castspell(god, OT_S_CONFISCATE, player, NULL, player->cell);
@ -112,11 +114,32 @@ void angergod(enum RACE rid, int amt) {
a = rnd(0,MAXATTS-1); a = rnd(0,MAXATTS-1);
modattr(player, a, -1); modattr(player, a, -1);
break; break;
case R_GODPURITY:
// remove blessings
msg("\"Your actions do not befit the bearer of blessed objects!\"");
nposs = 0;
for (o = player->pack->first ; o ; o = o->next) {
if (isblessed(o)) {
poss[nposs++] = o;
}
}
n = rnd(1,3);
if (nposs < n) n = nposs;
for (i = 0; i < n; i++) {
o = (object_t *)poss[rnd(0,nposs-1)];
while (!isblessed(o)) {
// pick again...
o = (object_t *)poss[rnd(0,nposs-1)];
}
curseob(o);
}
break;
default: default:
break; break;
} }
} else if (piety > -200) { } else if (piety > -200) {
object_t *o; object_t *o;
int n,i;
// major bad stuff // major bad stuff
switch (god->race->id) { switch (god->race->id) {
case R_GODDEATH: case R_GODDEATH:
@ -134,11 +157,11 @@ void angergod(enum RACE rid, int amt) {
case 2: case 2:
// summon undead // summon undead
msg("\"Destroy him, my pets!\""); msg("\"Destroy him, my pets!\"");
summonlfs(god, player->cell, RC_UNDEAD, SZ_ANY, 3, PERMENANT); summonlfs(god, player->cell, RC_UNDEAD, SZ_ANY, AL_EVIL, 3, PERMENANT);
break; break;
} }
break; break;
case R_GODGREED: case R_GODTHIEVES:
o = getweapon(player); o = getweapon(player);
msg("\"Allow me to lighten your load a little...\""); msg("\"Allow me to lighten your load a little...\"");
if (o) { // take player's weapon if (o) { // take player's weapon
@ -159,6 +182,36 @@ void angergod(enum RACE rid, int amt) {
modattr(player, a, -1); modattr(player, a, -1);
} }
break;
case R_GODPURITY:
switch (rnd(1,2)) {
case 1:
// break objects
msg("\"Time for a lesson in materialism!\"");
nposs = 0;
for (o = player->pack->first ; o ; o = o->next) {
if (hasflag(o->flags, F_DAMAGABLE) && !hasflag(o->flags, F_DEAD)) {
poss[nposs++] = o;
}
}
n = rnd(1,3);
if (nposs < n) n = nposs;
for (i = 0; i < n; i++) {
char obname[BUFLEN];
o = (object_t *)poss[rnd(0,nposs-1)];
// damage it
getobname(o, obname, o->amt);
msg("Your %s %s struck by divine force!", (o->amt == 1) ? "is" : "are",
noprefix(obname));
takedamage(o, roll("2d4"), DT_DIRECT);
}
break;
case 2:
// summon holy creautes
msg("\"Destroy him, my pets!\"");
summonlfs(god, player->cell, RC_ANY, SZ_ANY, AL_GOOD, 3, PERMENANT);
break;
}
break; break;
default: default:
break; break;
@ -289,9 +342,9 @@ int godgiftmaybe(enum RACE rid) {
god = findgod(rid); god = findgod(rid);
piety = getpiety(rid); piety = getpiety(rid);
if (piety >= 100) { if (piety >= 200) {
int chance; int chance;
// ie. 100 -> 2% // ie. 200 -> 4%
// ie. 500 -> 10% // ie. 500 -> 10%
chance = piety / 50; chance = piety / 50;
if (pctchance(chance)) { // if this is true, you get a gift. if (pctchance(chance)) { // if this is true, you get a gift.
@ -302,6 +355,61 @@ int godgiftmaybe(enum RACE rid) {
godsay(god->race->id, "I bestow a gift upon you, mortal!"); godsay(god->race->id, "I bestow a gift upon you, mortal!");
strcpy(obtogive, ""); strcpy(obtogive, "");
switch (god->race->id) { switch (god->race->id) {
case R_GODPURITY:
while (rollagain) {
int n,nposs,i;
object_t *poss[MAXCANDIDATES],*o;
flag_t *f;
object_t *wep;
rollagain = B_FALSE;
switch (rnd(1,6)) {
case 1:
sprintf(obtogive, "2-4 blessed potions of water");
break;
case 2:
sprintf(obtogive, "blessed great weapon");
break;
case 3:
sprintf(obtogive, "wand of turn undead");
break;
case 4: // bless your weapon
wep = getweapon(player);
if (wep && !isblessed(wep)) {
blessob(wep);
} else {
rollagain = B_TRUE;
}
break;
case 5: // holy aura
if (lfhasflag(player, F_HOLYAURA)) {
rollagain = B_TRUE;
} else {
f = addtempflag(player->flags, F_PRODUCESLIGHT, 3, NA, NA, NULL, FROMGODGIFT);
f->obfrom = god->race->id;
f = addtempflag(player->flags, F_HOLYAURA, NA, NA, NA, NULL, FROMGODGIFT);
f->obfrom = god->race->id;
}
break;
case 6: // bless 1-3 obs
nposs = 0;
n = rnd(1,3); // num to bless
for (o = player->pack->first ; o ; o = o->next) {
if (!isblessed(o)) {
poss[nposs++] = o;
}
}
if (nposs < n) n = nposs;
for (i = 0; i < n; i++) {
o = poss[rnd(0,nposs-1)];
while (isblessed(o)) {
o = poss[rnd(0,nposs-1)];
}
blessob(o);
}
break;
}
}
break;
case R_GODDEATH: case R_GODDEATH:
while (rollagain) { while (rollagain) {
flag_t *f; flag_t *f;
@ -343,7 +451,41 @@ int godgiftmaybe(enum RACE rid) {
} }
} }
break; break;
case R_GODGREED: case R_GODTHIEVES:
while (rollagain) {
rollagain = B_FALSE;
switch (rnd(1,7)) {
case 1:
if (getskill(player, SK_TECHUSAGE) >= gettechlevel(OT_LOCKHACKER)) {
sprintf(obtogive, "lock hacker");
} else {
sprintf(obtogive, "3-6 blessed lockpicks");
}
break;
case 2:
if (onein(6)) {
sprintf(obtogive, "large bag of holding");
} else {
sprintf(obtogive, "bag of holding");
}
break;
case 3:
sprintf(obtogive, "safebox");
break;
case 4:
sprintf(obtogive, "wand of opening");
break;
case 5:
sprintf(obtogive, "wand of invisibility");
break;
case 6:
sprintf(obtogive, "3-6 potions of invisibility");
break;
case 7:
sprintf(obtogive, "leather boots of stealth");
break;
}
}
break; break;
case R_GODMERCY: case R_GODMERCY:
while (rollagain) { while (rollagain) {
@ -445,9 +587,27 @@ void pleasegod(enum RACE rid, int amt) {
modpiety(rid, amt); modpiety(rid, amt);
// announce // announce
if (hasflag(lf->flags, F_PRAYEDTO)) {
switch (rid) {
case R_GODDEATH:
msg("You feel a thrill of unholy ecstasy.");
break;
case R_GODMERCY:
msg("You feel a sense of peace.");
break;
case R_GODPURITY:
msg("You hear a distant choir singing.");
break;
case R_GODTHIEVES:
msg("You feel a guilty pleasure.");
break;
default:
msg("You feel like %s approves of your actions.", lfname); msg("You feel like %s approves of your actions.", lfname);
break;
}
godgiftmaybe(rid); godgiftmaybe(rid);
} }
}
void pleasegodmaybe(enum RACE rid, int amt) { void pleasegodmaybe(enum RACE rid, int amt) {
enum PIETYLEV modplev; enum PIETYLEV modplev;
@ -485,9 +645,30 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
if (godisangry(god->race->id)) { if (godisangry(god->race->id)) {
// get even more angry // get even more angry
angergod(god->race->id, PIETYPRAYLOSS); angergod(god->race->id, PIETYPRAYLOSS);
return B_FALSE; return B_FALSE;
} else if (piety <= 99) { }
// sacrifices if god isn't angry.
if (god->race->id == R_GODPURITY) {
object_t *o,*nexto;
int donesomething = B_FALSE;
for (o = lf->cell->obpile->first ; o ; o = nexto) {
nexto = o->next;
if (iscursed(o) && (o->blessknown)) {
char buf[BUFLEN];
getobname(o, buf, o->amt);
msg("%s explode%s in a shower of sparks!",buf, (o->amt == 1) ? "s" : "");
removeob(o,ALL);
donesomething = B_TRUE;
}
}
pleasegodmaybe(god->race->id, 5);
return B_FALSE;
}
if (piety <= 99) {
// piety between 0 and 99 = ignored // piety between 0 and 99 = ignored
//godsay(god->race->id, "Stop pestering me!"); //godsay(god->race->id, "Stop pestering me!");
angergod(god->race->id, 0); angergod(god->race->id, 0);
@ -501,6 +682,40 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
switch (god->race->id) { switch (god->race->id) {
lifeform_t *l; lifeform_t *l;
int donesomething = B_FALSE; int donesomething = B_FALSE;
cell_t *c;
object_t *o;
object_t *oposs[MAXPILEOBS];
int noposs = 0;
case R_GODPURITY:
msg("\"Witness the holy radiance of purity!\"");
c = getrandomadjcell(lf->cell, WE_WALKABLE, B_ALLOWEXPAND);
if (c) {
dospelleffects(god, OT_S_LIGHT, 10, NULL, NULL, c, B_BLESSED, NULL, B_TRUE);
}
// get list of cursed obs
noposs = 0;
for (o = lf->pack->first ; o ; o = o->next) {
if (iscursed(o)) {
oposs[noposs++] = o;
}
}
if (noposs) {
o = oposs[rnd(0,noposs-1)];
blessob(o);
}
// smite evil
for (l = lf->cell->map->lf ; l ; l = l->next) {
if (getalignment(l) == AL_EVIL) {
if (haslof(lf->cell, l->cell, LOF_WALLSTOP, NULL)) {
// smite them
castspell(god, OT_S_SMITEEVIL, l, NULL, l->cell);
}
}
}
// turn undead
castspell(god, OT_S_TURNUNDEAD, lf, NULL, NULL);
break;
case R_GODDEATH: case R_GODDEATH:
msg("\"Behold, the power of death!\""); msg("\"Behold, the power of death!\"");
for (l = lf->cell->map->lf ; l ; l = l->next) { for (l = lf->cell->map->lf ; l ; l = l->next) {
@ -511,7 +726,7 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
dospelleffects(god, OT_S_ANIMATEDEAD, 10, lf, NULL, lf->cell, B_UNCURSED, NULL, B_TRUE); dospelleffects(god, OT_S_ANIMATEDEAD, 10, lf, NULL, lf->cell, B_UNCURSED, NULL, B_TRUE);
dospelleffects(god, OT_S_DARKNESS, 10, lf, NULL, lf->cell, B_UNCURSED, NULL, B_TRUE); dospelleffects(god, OT_S_DARKNESS, 10, lf, NULL, lf->cell, B_UNCURSED, NULL, B_TRUE);
break; break;
case R_GODGREED: case R_GODTHIEVES:
if (isinbattle(lf)) { if (isinbattle(lf)) {
lifeform_t *l; lifeform_t *l;
int donesomething = B_FALSE; int donesomething = B_FALSE;
@ -551,6 +766,7 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
cell_t *c; cell_t *c;
object_t *o; object_t *o;
c = player->los[i]; c = player->los[i];
if (c != player->cell) {
o = hascloseddoor(c); o = hascloseddoor(c);
if (o && hasflag(o->flags, F_LOCKED)) { if (o && hasflag(o->flags, F_LOCKED)) {
if (first) { if (first) {
@ -562,6 +778,7 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
} }
} }
} }
}
break; break;
case R_GODMERCY: case R_GODMERCY:
if (ispoisoned(lf)) { if (ispoisoned(lf)) {

132
io.c
View File

@ -618,6 +618,7 @@ cell_t *askcoords(char *prompt, char *subprompt, int targettype, lifeform_t *src
// show what we are over in msg bar // show what we are over in msg bar
strcpy(buf, ""); strcpy(buf, "");
if (haslos(player, c)) { if (haslos(player, c)) {
int i;
// can see the cell... // can see the cell...
if (c->lf) { if (c->lf) {
if (cansee(player, c->lf)) { if (cansee(player, c->lf)) {
@ -780,18 +781,22 @@ cell_t *askcoords(char *prompt, char *subprompt, int targettype, lifeform_t *src
} }
} }
if (lfhasflag(c->lf, F_HOLYAURA)) {
if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, "holyaura");
}
if (lfhasflag(c->lf, F_RAGE)) { if (lfhasflag(c->lf, F_RAGE)) {
if (strlen(extrainfo)) strcat(extrainfo, ", "); if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, "enraged"); strcat(extrainfo, "enraged");
} }
for (f = c->lf->flags->first ; f ; f = f->next) { getflags(c->lf->flags, F_RETALIATE, F_NONE);
if (f->id == F_RETALIATE) { for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (strlen(extrainfo)) strcat(extrainfo, ", "); if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, f->text); strcat(extrainfo, f->text);
} }
}
wep = getweapon(c->lf); wep = getweapon(c->lf);
if (wep && (c->lf->race->id != R_DANCINGWEAPON)) { if (wep && (c->lf->race->id != R_DANCINGWEAPON)) {
@ -1425,6 +1430,10 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
donesomething = B_TRUE; donesomething = B_TRUE;
} }
break; break;
case F_HOLYAURA:
msg("%s %s surrounded by a holy aura!", lfname, isplayer(lf) ? "are" : "is");
donesomething = B_TRUE;
break;
case F_LEVITATING: case F_LEVITATING:
msg("%s begin%s to levitate in the air!",lfname, isplayer(lf) ? "" : "s"); msg("%s begin%s to levitate in the air!",lfname, isplayer(lf) ? "" : "s");
donesomething = B_TRUE; donesomething = B_TRUE;
@ -1937,6 +1946,10 @@ int announceflagloss(lifeform_t *lf, flag_t *f) {
donesomething = B_TRUE; donesomething = B_TRUE;
} }
break; break;
case F_HOLYAURA:
msg("%s%s holy aura vanishes.", lfname, getpossessive(lfname));
donesomething = B_TRUE;
break;
case F_LEVITATING: case F_LEVITATING:
msg("%s %s down to the ground.", lfname, isplayer(lf) ? "float" : "floats"); msg("%s %s down to the ground.", lfname, isplayer(lf) ? "float" : "floats");
donesomething = B_TRUE; donesomething = B_TRUE;
@ -3127,9 +3140,12 @@ void describeob(object_t *o) {
mvwprintw(mainwin, y, 0, " It can hold up to %d of the following kind(s) of ammo:",f->val[0]); mvwprintw(mainwin, y, 0, " It can hold up to %d of the following kind(s) of ammo:",f->val[0]);
y++; y++;
strcpy(buf, ""); strcpy(buf, "");
for (ff = o->flags->first; ff ; ff = ff->next) {
if (ff->id == F_AMMOOB) {
getflags(o->flags, F_AMMOOB, F_NONE);
for (i = 0; i < nretflags; i++) {
objecttype_t *ot; objecttype_t *ot;
ff = retflag[i];
ot = findot(ff->val[0]); ot = findot(ff->val[0]);
if (ot) { if (ot) {
if (streq(buf, "")) { if (streq(buf, "")) {
@ -3145,7 +3161,6 @@ void describeob(object_t *o) {
} }
} }
} }
}
if (strlen(buf)) { if (strlen(buf)) {
mvwprintw(mainwin, y, 0, "%s",buf); y++; mvwprintw(mainwin, y, 0, "%s",buf); y++;
} }
@ -3667,6 +3682,9 @@ void describeob(object_t *o) {
case F_DETECTAURAS: case F_DETECTAURAS:
mvwprintw(mainwin, y, 0, "%s allows you to detect blessings or curses.", buf); y++; mvwprintw(mainwin, y, 0, "%s allows you to detect blessings or curses.", buf); y++;
break; break;
case F_HOLYAURA:
mvwprintw(mainwin, y, 0, "%s surrounds you with a holy aura.", buf); y++;
break;
case F_LEVITATING: case F_LEVITATING:
mvwprintw(mainwin, y, 0, "%s causes you to levitate.", buf); y++; mvwprintw(mainwin, y, 0, "%s causes you to levitate.", buf); y++;
break; break;
@ -4116,8 +4134,8 @@ void docomms(lifeform_t *lf) {
} }
} }
if ((lf->race->id == R_BEGGAR) && countmoney(player)) { if (isadjacent(lf->cell, player->cell)) {
addchoice(&prompt, 'd', "(donate a gold coin)", NULL, NULL); addchoice(&prompt, 'd', "(donate an item)", NULL, NULL);
} }
f = lfhasflag(lf, F_OWNSSHOP); f = lfhasflag(lf, F_OWNSSHOP);
@ -4139,6 +4157,8 @@ void docomms(lifeform_t *lf) {
lifeform_t *lf2 = NULL; lifeform_t *lf2 = NULL;
char lfname2[BUFLEN]; char lfname2[BUFLEN];
char buf2[BUFLEN]; char buf2[BUFLEN];
int count;
object_t *o, *givenob = NULL;
case 'a': case 'a':
sprintf(buf, "Tell %s to attack who?",lfname); sprintf(buf, "Tell %s to attack who?",lfname);
sprintf(buf2, "%s->Attack->",lfname); sprintf(buf2, "%s->Attack->",lfname);
@ -4169,8 +4189,29 @@ void docomms(lifeform_t *lf) {
aigoto(lf, c, MR_OTHER, NULL, AI_FOLLOWTIME); aigoto(lf, c, MR_OTHER, NULL, AI_FOLLOWTIME);
} }
break; break;
case 'd': // donate to beggar case 'd': // donate
givemoney(player, lf, 1); // we already checked that we had enough.
// ask what to give
sprintf(buf, "What will you give to %s?",lfname);
o = askobject(player->pack, buf, &count, AO_NONE);
if (o) {
if (o->type->id == OT_GOLD) {
getobname(o, buf, count);
givemoney(player, lf, count);
msg("You give %s to %s.", buf, lfname);
} else {
givenob = moveob(o, lf->pack, count);
if (givenob) {
getobname(givenob, buf, givenob->amt);
// successful - announce
msg("You give %s to %s.", buf, lfname);
}
}
}
if (givenob) {
if ((lf->race->id == R_BEGGAR) && (givenob->type->id == OT_GOLD)) {
// begger effects
if (countmoney(lf) == 1) { if (countmoney(lf) == 1) {
i = rnd(1,100); i = rnd(1,100);
if (i <= 5) { // attack you if (i <= 5) { // attack you
@ -4178,9 +4219,9 @@ void docomms(lifeform_t *lf) {
fightback(lf, player); fightback(lf, player);
} else if (i <= 10) { // limited wish } else if (i <= 10) { // limited wish
// change to a god. // change to a god.
lf = godappears(R_GODGREED, lf->cell); lf = godappears(R_GODMERCY, lf->cell);
// behold! i am me! // behold! i am me!
say(lf, "Behold mortal! It is I, Avamon!", SV_SHOUT); say(lf, "Behold mortal! It is I, Yumi!", SV_SHOUT);
say(lf, "For your selfless act, I grant you a wish.", SV_TALK); say(lf, "For your selfless act, I grant you a wish.", SV_TALK);
// grant a wish. // grant a wish.
castspell(lf, OT_S_WISHLIMITED, player, NULL, NULL); castspell(lf, OT_S_WISHLIMITED, player, NULL, NULL);
@ -4219,6 +4260,44 @@ void docomms(lifeform_t *lf) {
// they already had some money // they already had some money
sayphrase(lf, SP_BEGTHANKS, SV_TALK, NA, NULL); sayphrase(lf, SP_BEGTHANKS, SV_TALK, NA, NULL);
} }
pleasegodmaybe(R_GODPURITY, 10);
pleasegodmaybe(R_GODMERCY, 20);
} else {
// not giving money to a begger
enum ATTRBRACKET iqb;
iqb = getattrbracket(getattr(lf, A_IQ), A_IQ, NULL);
// chance of calming hostile intelligen, monsters
if ((getallegiance(lf) == AL_HOSTILE) && (iqb >= IQ_ANIMAL) && cansee(lf, player)) {
int mod = 0;
int covets = B_FALSE;
// healing object and they were bleeding?
if (isbleeding(lf) && hasflag(givenob->flags, F_AIHEALITEM)) {
if (aiobok(lf, givenob, lf)) {
mod += 3;
}
}
// object which ai wants?
if (aiwants(lf, givenob, &covets)) {
if (covets) {
mod += 5;
} else {
mod += 3;
}
}
// TODO: only get speech bonus if humanoid+intelligent
mod += getskill(player, SK_SPEECH);
if (skillcheckvs(player, SC_MORALE, mod, lf, SC_MORALE, 0)) {
// TODO: if humanoid+intelligent, say thanks.
makepeaceful(lf);
// TODO: chance of becoming a pet?
pleasegodmaybe(R_GODMERCY, 5);
}
}
}
} // end if givenob
break; break;
case 'g': case 'g':
sprintf(buf, "Tell %s to go where?",lfname); sprintf(buf, "Tell %s to go where?",lfname);
@ -4248,6 +4327,7 @@ void docomms(lifeform_t *lf) {
// can't afford it // can't afford it
msg("You can't afford to pay $%d.", moneyowing); msg("You can't afford to pay $%d.", moneyowing);
} else { } else {
int angeramt = 0;
object_t *o; object_t *o;
// mark all items as paid for // mark all items as paid for
for (o = player->pack->first ; o ; o = o->next) { for (o = player->pack->first ; o ; o = o->next) {
@ -4256,6 +4336,7 @@ void docomms(lifeform_t *lf) {
killflag(f); killflag(f);
getobname(o, buf, o->amt); getobname(o, buf, o->amt);
msg("You buy %s.", buf); msg("You buy %s.", buf);
angeramt += 25;
// get it identified? // get it identified?
if (!isknown(o) && (countmoney(player) >= SHOPIDENTPRICE)) { if (!isknown(o) && (countmoney(player) >= SHOPIDENTPRICE)) {
char buf2[BUFLEN]; char buf2[BUFLEN];
@ -4264,6 +4345,7 @@ void docomms(lifeform_t *lf) {
ch2 = askchar(buf2, "yn","n", B_TRUE); ch2 = askchar(buf2, "yn","n", B_TRUE);
if (ch2 == 'y') { if (ch2 == 'y') {
if (givemoney(player, lf, SHOPIDENTPRICE)) { if (givemoney(player, lf, SHOPIDENTPRICE)) {
angeramt += 25;
identify(o); identify(o);
real_getobname(o, buf, 1, B_FALSE, B_TRUE, B_FALSE, B_FALSE, B_FALSE); // don't adjust for blindness real_getobname(o, buf, 1, B_FALSE, B_TRUE, B_FALSE, B_FALSE, B_FALSE); // don't adjust for blindness
msgnocap("%c - %s",o->letter, buf); msgnocap("%c - %s",o->letter, buf);
@ -5321,7 +5403,7 @@ void dohelp(char helpmode) {
} }
} else if (helpmode == 'g') { } else if (helpmode == 'g') {
int i; int i;
centre(mainwin,C_WHITE, 0, "SKILL REFERENCE"); centre(mainwin,C_WHITE, 0, "GOD REFERENCE");
y = 2; y = 2;
initprompt(&prompt, "Describe which god (ESC when done)?"); initprompt(&prompt, "Describe which god (ESC when done)?");
@ -5755,7 +5837,11 @@ void dothrow(obpile_t *op) {
} }
if (getcelldist(player->cell, where) > maxdist) { if (getcelldist(player->cell, where) > maxdist) {
if (maxdist < 1) {
msg("%s is too heavy to throw!",buf, (o->amt == 1) ? "is" : "are");
} else {
msg("You can't throw %s that far!",buf); msg("You can't throw %s that far!",buf);
}
} else { } else {
throwat(player, o, where); throwat(player, o, where);
} }
@ -6048,9 +6134,21 @@ void initgfx(void) {
// create windows // create windows
//msgwin = newwin(1, vieww, 0, 0); //msgwin = newwin(1, vieww, 0, 0);
msgwin = newwin(msgwinh, vieww, 0, 0); msgwin = newwin(msgwinh, vieww, 0, 0);
if (!msgwin) {
dblog("Error creating msgwin.");
exit(1);
}
gamewin = newwin(viewh, vieww, msgwinh, 0); gamewin = newwin(viewh, vieww, msgwinh, 0);
if (!gamewin) {
dblog("Error creating gamewin.");
exit(1);
}
//statwin = newwin(statwinh, vieww, msgwinh + viewh + statwinh - 2 ,0); //statwin = newwin(statwinh, vieww, msgwinh + viewh + statwinh - 2 ,0);
statwin = newwin(statwinh, vieww, SCREENH - statwinh,0); statwin = newwin(statwinh, vieww, SCREENH - statwinh,0);
if (!statwin) {
dblog("Error creating statwin.");
exit(1);
}
statdirty = B_TRUE; statdirty = B_TRUE;
redraw(); redraw();
@ -8053,12 +8151,11 @@ void showlfstats(lifeform_t *lf, int showall) {
// unarmed attacks // unarmed attacks
op = addobpile(NULL, NULL, NULL); op = addobpile(NULL, NULL, NULL);
for (f = lf->flags->first ; f ; f = f->next) { for (f = lf->flags->first ; f ; f = f->next) {
if (f->id == F_HASATTACK) { if (f->id == F_HASATTACK) {
object_t *o; object_t *o;
objecttype_t *ot; objecttype_t *ot;
ot = findot(f->val[0]); ot = findot(f->val[0]);
o = addob(op, ot->name); o = addobfast(op, ot->id);
if (o) { if (o) {
char dambuf[BUFLEN]; char dambuf[BUFLEN];
strcpy(dambuf, ""); strcpy(dambuf, "");
@ -9063,6 +9160,11 @@ void showlfstats(lifeform_t *lf, int showall) {
mvwprintw(mainwin, y, 0, buf); mvwprintw(mainwin, y, 0, buf);
y++; y++;
} }
f = lfhasknownflag(lf, F_HOLYAURA);
if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "%s %s surrounded by a holy aura.", you(lf), is(lf));
y++;
}
f = lfhasknownflag(lf, F_QUICKBITE); f = lfhasknownflag(lf, F_QUICKBITE);
if (f && (f->known)) { if (f && (f->known)) {
sprintf(buf,"%s can bite wounded enemies for extra damage.", you(lf)); sprintf(buf,"%s can bite wounded enemies for extra damage.", you(lf));

316
lf.c
View File

@ -948,7 +948,7 @@ int canwear(lifeform_t *lf, object_t *o, enum BODYPART where) {
return B_FALSE; return B_FALSE;
} }
if (gettechlevel(o) > getskill(lf, SK_TECHUSAGE)) { if (gettechlevel(o->type->id) > getskill(lf, SK_TECHUSAGE)) {
reason = E_NOTKNOWN; reason = E_NOTKNOWN;
return B_FALSE; return B_FALSE;
} }
@ -1297,6 +1297,20 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
// successful cast? // successful cast?
if (!rv) { if (!rv) {
practice(lf, SK_SPELLCASTING, 1); practice(lf, SK_SPELLCASTING, 1);
if (isplayer(lf)) {
switch (getschool(sid)) {
case SS_DEATH:
pleasegodmaybe(R_GODDEATH, getspelllevel(sid));
angergodmaybe(R_GODPURITY, getspelllevel(sid)*5);
break;
case SS_LIFE:
pleasegodmaybe(R_GODPURITY, getspelllevel(sid));
angergodmaybe(R_GODDEATH, getspelllevel(sid)*5);
break;
default:
break;
}
}
} }
return rv; return rv;
@ -1761,6 +1775,13 @@ void die(lifeform_t *lf) {
// award xp (but not if another monster killed it) // award xp (but not if another monster killed it)
if (hasflag(lf->flags, F_KILLEDBYPLAYER)) { if (hasflag(lf->flags, F_KILLEDBYPLAYER)) {
awardxpfor(lf,100); awardxpfor(lf,100);
if ((getalignment(lf) == AL_EVIL) || isundead(lf)) {
pleasegodmaybe(R_GODPURITY, 3);
} else if (getalignment(lf) == AL_GOOD) {
pleasegodmaybe(R_GODDEATH, 3);
} else { // ie. neutral
pleasegodmaybe(R_GODDEATH, 1);
}
} }
} }
@ -2133,7 +2154,7 @@ int digdown(lifeform_t *lf, object_t *o) {
msg("%s digs a hole in the floor."); msg("%s digs a hole in the floor.");
} }
addob(lf->cell->obpile, "hole in the ground"); addobfast(lf->cell->obpile, OT_HOLEINGROUND);
// takes a lot of time // takes a lot of time
if (o) { if (o) {
@ -2172,8 +2193,7 @@ int digup(lifeform_t *lf, object_t *o) {
// add some stones here // add some stones here
addob(lf->cell->obpile, "20-50 stones"); addob(lf->cell->obpile, "20-50 stones");
addobfast(lf->cell->obpile, OT_HOLEINROOF);
addob(lf->cell->obpile, "hole in the roof");
// takes a LOT of time since gravity is against us // takes a LOT of time since gravity is against us
if (o) { if (o) {
@ -2481,7 +2501,7 @@ int eat(lifeform_t *lf, object_t *o) {
// special case for bananas // special case for bananas
if (o->type->id == OT_BANANA) { if (o->type->id == OT_BANANA) {
object_t *skin; object_t *skin;
skin = addob(lf->pack, "banana skin"); skin = addobfast(lf->pack, OT_BANANASKIN);
if (skin) { if (skin) {
if (isplayer(lf)) { if (isplayer(lf)) {
char skinname[BUFLEN]; char skinname[BUFLEN];
@ -2489,7 +2509,7 @@ int eat(lifeform_t *lf, object_t *o) {
msgnocap("%c - %s", skin->letter, skinname); msgnocap("%c - %s", skin->letter, skinname);
} }
} else { } else {
skin = addob(lf->cell->obpile, "banana skin"); skin = addobfast(lf->cell->obpile, OT_BANANASKIN);
if (skin && cansee(player, lf)) { if (skin && cansee(player, lf)) {
char skinname[BUFLEN]; char skinname[BUFLEN];
getobname(skin, skinname, 1); getobname(skin, skinname, 1);
@ -2518,8 +2538,9 @@ int eat(lifeform_t *lf, object_t *o) {
} }
// eating your pet is very bad!
if (isplayer(lf) && hasflagval(o->flags, F_PETOF, player->id, NA, NA, NULL)) { if (isplayer(lf) && hasflagval(o->flags, F_PETOF, player->id, NA, NA, NULL)) {
angergodmaybe(R_GODMERCY, 150); angergodmaybe(R_GODPURITY, 150);
stopeating = B_TRUE; stopeating = B_TRUE;
} }
@ -3100,11 +3121,13 @@ void fightback(lifeform_t *lf, lifeform_t *attacker) {
int i, nposs = 0; int i, nposs = 0;
// darkjump // darkjump
for (i = 0; i < lf->nlos; i++) { for (i = 0; i < lf->nlos; i++) {
if (lf->los[i] != lf->cell) {
if (cellwalkable(lf, lf->los[i], NULL) && isdark(lf->los[i])) { if (cellwalkable(lf, lf->los[i], NULL) && isdark(lf->los[i])) {
poss[nposs] = lf->los[i]; poss[nposs] = lf->los[i];
nposs++; nposs++;
} }
} }
}
if (nposs) { if (nposs) {
//teleportto(lf, poss[rnd(0,nposs-1)], B_FALSE); // no smoke //teleportto(lf, poss[rnd(0,nposs-1)], B_FALSE); // no smoke
abilityeffects(lf, OT_A_DARKWALK, poss[rnd(0,nposs-1)], NULL, NULL); abilityeffects(lf, OT_A_DARKWALK, poss[rnd(0,nposs-1)], NULL, NULL);
@ -3286,8 +3309,10 @@ int flee(lifeform_t *lf) {
// if the flag is temporary, keep fleeing and wait for it to time out normally // if the flag is temporary, keep fleeing and wait for it to time out normally
fleefrom = thisone; fleefrom = thisone;
} }
// player let something flee?
if (isplayer(thisone)) { if (isplayer(thisone)) {
pleasegodmaybe(R_GODMERCY, 5); pleasegodmaybe(R_GODMERCY, 5);
angergodmaybe(R_GODDEATH, 25);
} }
} }
} }
@ -3341,7 +3366,7 @@ int flee(lifeform_t *lf) {
} }
} }
// move away from them // move away from them
if (!moveawayfrom(lf, fleefrom->cell, DT_ORTH)) { if (!moveawayfrom(lf, fleefrom->cell, DT_ORTH, B_FALSE)) {
return B_TRUE; return B_TRUE;
} }
} }
@ -3664,6 +3689,15 @@ void getadjallies(lifeform_t *lf, object_t *stairob, lifeform_t **adjally, int *
} }
} }
enum ALIGNMENT getalignment(lifeform_t *lf) {
flag_t *f;
f = lfhasflag(lf, F_ALIGNMENT);
if (!f) {
return AL_NONE;
}
return f->val[0];
}
enum ALLEGIENCE getallegiance(lifeform_t *lf) { enum ALLEGIENCE getallegiance(lifeform_t *lf) {
flag_t *f; flag_t *f;
f = lfhasflag(lf, F_CHARMEDBY); f = lfhasflag(lf, F_CHARMEDBY);
@ -3899,12 +3933,16 @@ int real_getattr(lifeform_t *lf, enum ATTRIB attr, int ignoreattrset) {
if ((f->id == F_ATTRMOD) && (f->val[0] == attr)) { if ((f->id == F_ATTRMOD) && (f->val[0] == attr)) {
val += f->val[1]; val += f->val[1];
} }
if ((f->id == F_DRUNK) && (attr == A_DEX)) { if (f->id == F_DRUNK) {
if (attr == A_DEX) {
if (hasjob(lf, J_PIRATE)) { if (hasjob(lf, J_PIRATE)) {
val += f->val[0]; val += f->val[0];
} else { } else {
val -= f->val[0]; val -= f->val[0];
} }
} else if (attr == A_WIS) {
val -= f->val[0];
}
} }
} }
@ -3937,7 +3975,7 @@ int getavgdam(lifeform_t *lf, int forxp) {
objecttype_t *ot; objecttype_t *ot;
ot = findot(f->val[0]); ot = findot(f->val[0]);
o = addob(op, ot->name); o = addobfast(op, ot->id);
getdamrange(f, &min,&max); getdamrange(f, &min,&max);
thisavg = ((float)min + (float)max) / 2.0; thisavg = ((float)min + (float)max) / 2.0;
@ -4132,7 +4170,7 @@ int getevasion(lifeform_t *lf) {
} }
// dexterity mod // dexterity mod
ev += (getstatmod(lf, A_DEX) / 2); ev += (getstatmod(lf, A_DEX) / 10);
// you are easier to hit if you're glowing // you are easier to hit if you're glowing
if (hasflag(lf->flags, F_PRODUCESLIGHT)) { if (hasflag(lf->flags, F_PRODUCESLIGHT)) {
@ -4221,7 +4259,7 @@ object_t *getbestweapon(lifeform_t *lf) {
ot = findot(retflag[i]->val[0]); ot = findot(retflag[i]->val[0]);
if (ot) { if (ot) {
o = addob(op, ot->name); o = addobfast(op, ot->id);
if (isweapon(o) && !isfirearm(o) && canweild(lf, o) && isbetterwepthan(o, bestwep)) { if (isweapon(o) && !isfirearm(o) && canweild(lf, o) && isbetterwepthan(o, bestwep)) {
bestwep = o; bestwep = o;
@ -5202,11 +5240,13 @@ lifeform_t *getnearbypeaceful(lifeform_t *lf) {
int nposs = 0; int nposs = 0;
// peaceful enemy in los ? // peaceful enemy in los ?
for (i = 0; i < lf->nlos; i++) { for (i = 0; i < lf->nlos; i++) {
if (lf->los[i] != lf->cell) {
l = lf->los[i]->lf; l = lf->los[i]->lf;
if (l && (getallegiance(l) == AL_PEACEFUL)) { if (l && (getallegiance(l) == AL_PEACEFUL)) {
poss[nposs] = l; poss[nposs] = l;
} }
} }
}
if (nposs) { if (nposs) {
return poss[rnd(0,nposs-1)]; return poss[rnd(0,nposs-1)];
} }
@ -6382,6 +6422,16 @@ int givemoney(lifeform_t *from, lifeform_t *to, int amt) {
togold += amt; togold += amt;
} }
if (isplayer(from)) {
flag_t *f;
f = lfhasflag(from, F_GAVEMONEY);
if (f) {
f->val[0] += amt;
} else {
addflag(from->flags, F_GAVEMONEY, amt, NA, NA, NULL);
}
}
return B_FALSE; return B_FALSE;
} }
@ -6712,7 +6762,7 @@ void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp) {
skill_t *sk; skill_t *sk;
object_t *o; object_t *o;
// give that weapon // give that weapon
o = addob(lf->pack, ot->name); o = addobfast(lf->pack, ot->id);
// give one extra rank of skill in this weapon // give one extra rank of skill in this weapon
sk = getobskill(o); sk = getobskill(o);
@ -6854,7 +6904,7 @@ void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp) {
region_t *r; region_t *r;
regionthing_t *rt = NULL; regionthing_t *rt = NULL;
int i; int i;
o = addob(lf->pack, "map"); o = addobfast(lf->pack, OT_MAP);
assert(o); assert(o);
// find first worldmap village // find first worldmap village
r = findregion(RG_WORLDMAP); r = findregion(RG_WORLDMAP);
@ -7157,6 +7207,7 @@ int lockpick(lifeform_t *lf, object_t *target, object_t *device) {
char obname[BUFLEN]; char obname[BUFLEN];
int faileffect; int faileffect;
int difficulty = 20; // default, never used though int difficulty = 20; // default, never used though
int bonus = 0;
lockflag = hasflag(target->flags, F_LOCKED); lockflag = hasflag(target->flags, F_LOCKED);
if (lockflag) { if (lockflag) {
@ -7174,13 +7225,15 @@ int lockpick(lifeform_t *lf, object_t *target, object_t *device) {
f = hasflag(device->flags, F_PICKLOCKS); f = hasflag(device->flags, F_PICKLOCKS);
assert(f); assert(f);
bonus = f->val[0];
if (isblessed(device)) bonus += 5;
faileffect = f->val[1]; faileffect = f->val[1];
// take time // take time
taketime(lf, getactspeed(lf) ); taketime(lf, getactspeed(lf) );
// TODO: different difficulty based on doors (maybe part of F_LOCKED flag)
if (skillcheck(lf, SC_OPENLOCKS, difficulty, f->val[0])) { if (skillcheck(lf, SC_OPENLOCKS, difficulty, bonus )) {
// success! // success!
// announce // announce
if (isplayer(lf) || cansee(player, lf)) { if (isplayer(lf) || cansee(player, lf)) {
@ -7198,6 +7251,8 @@ int lockpick(lifeform_t *lf, object_t *target, object_t *device) {
} }
// training // training
practice(lf, SK_LOCKPICKING, 1); practice(lf, SK_LOCKPICKING, 1);
// gods
if (isplayer(lf)) pleasegodmaybe(R_GODTHIEVES, 5);
} else { } else {
// failed! // failed!
if (faileffect == B_DIEONFAIL) { if (faileffect == B_DIEONFAIL) {
@ -7406,6 +7461,17 @@ int haslos(lifeform_t *viewer, cell_t *dest) {
if (viewer->cell->map != dest->map) return B_FALSE; if (viewer->cell->map != dest->map) return B_FALSE;
// can we use pre-calced los?
//
if ((viewer->cell->map->lf == viewer) && viewer->los) {
for (i = 0;i < viewer->nlos; i++) {
if (viewer->los[i] == dest) {
return B_TRUE;
}
}
return B_FALSE;
}
map = dest->map; map = dest->map;
x1 = viewer->cell->x; x1 = viewer->cell->x;
@ -7923,6 +7989,7 @@ void initjobs(void) {
addflag(lastjob->flags, F_CANLEARN, SK_STAVES, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_STAVES, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_SWIMMING, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_SWIMMING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_UNARMED, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_UNARMED, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_TECHUSAGE, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_TRACKING, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_TRACKING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_THROWING, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_THROWING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_TWOWEAPON, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_TWOWEAPON, NA, NA, NULL);
@ -8134,6 +8201,7 @@ void initrace(void) {
// human monsters... // human monsters...
addrace(R_BANDITLDR, "bandit leader", 75, '@', C_GREY, MT_FLESH, RC_HUMANOID); addrace(R_BANDITLDR, "bandit leader", 75, '@', C_GREY, MT_FLESH, RC_HUMANOID);
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_FOREST, 80, NA, NULL); addflag(lastrace->flags, F_RARITY, H_FOREST, 80, NA, NULL);
addflag(lastrace->flags, F_VARLEVEL, NA, NA, NA, NULL); addflag(lastrace->flags, F_VARLEVEL, NA, NA, NA, NULL);
addflag(lastrace->flags, F_DEMANDSBRIBE, NA, NA, NA, NULL); addflag(lastrace->flags, F_DEMANDSBRIBE, NA, NA, NA, NULL);
@ -8157,6 +8225,7 @@ void initrace(void) {
addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MINIONS, 100, 1, 3, "bandit"); addflag(lastrace->flags, F_MINIONS, 100, 1, 3, "bandit");
addrace(R_BANDIT, "bandit", 75, '@', C_GREY, MT_FLESH, RC_HUMANOID); addrace(R_BANDIT, "bandit", 75, '@', C_GREY, MT_FLESH, RC_HUMANOID);
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_FOREST, 80, NA, NULL); addflag(lastrace->flags, F_RARITY, H_FOREST, 80, NA, NULL);
addflag(lastrace->flags, F_VARLEVEL, NA, NA, NA, NULL); addflag(lastrace->flags, F_VARLEVEL, NA, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
@ -8254,8 +8323,98 @@ void initrace(void) {
addflag(lastrace->flags, F_WANTS, OT_GOLD, NA, NA, NULL); addflag(lastrace->flags, F_WANTS, OT_GOLD, NA, NA, NULL);
addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL);
// gods // gods - kep sorted alphabetically
addrace(R_GODPURITY, "Amberon", 90, '@', C_BOLDMAGENTA, MT_FLESH, RC_GOD);
addflag(lastrace->flags, F_ALIGNMENT, AL_GOOD, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, NA, NA, "20");
addflag(lastrace->flags, F_STARTATT, A_DEX, NA, NA, "10");
addflag(lastrace->flags, F_STARTATT, A_WIS, NA, NA, "18");
addflag(lastrace->flags, F_STARTATT, A_IQ, NA, NA, "16");
addflag(lastrace->flags, F_STARTATT, A_CON, NA, NA, "16");
addflag(lastrace->flags, F_STARTATT, A_CHA, NA, NA, "16");
addflag(lastrace->flags, F_STARTASLEEPPCT, 0, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 50, NA, NA, NULL);
addflag(lastrace->flags, F_UNIQUE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_FISTS, NA, NA, "1d2");
addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "blessed +3 flaming longsword");
addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "10 blessed potions of water");
//addflag(lastrace->flags, F_WANTS, OT_GOLD, NA, NA, NULL);
addflag(lastrace->flags, F_WANTSOBFLAG, F_RARITY, NA, NA, NULL); // ie. everything
addflag(lastrace->flags, F_STARTSKILL, SK_SS_LIFE, PR_MASTER, NA, NULL);
addflag(lastrace->flags, F_STARTSKILL, SK_FIRSTAID, PR_SKILLED, NA, NULL);
addflag(lastrace->flags, F_STARTSKILL, SK_SPELLCASTING, PR_SKILLED, NA, NULL);
addflag(lastrace->flags, F_SPELLCASTTEXT, NA, NA, NA, "gestures imperiously");
// god abilities
addflag(lastrace->flags, F_GODOF, NA, NA, NA, "Purity");
addflag(lastrace->flags, F_FLEEONHPPCT, 10, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_S_LIGHT, NA, NA, "pw:10;");
// may cast all life spells
for (ot = objecttype ; ot ; ot = ot->next) {
if ((ot->obclass->id == OC_SPELL) && (getspellschool(ot->id) == SS_LIFE)) {
addflag(lastrace->flags, F_CANWILL, ot->id, NA, NA, "pw:10;");
}
}
addflag(lastrace->flags, F_CANWILL, OT_S_WISHLIMITED, NA, NA, "pw:10;");
addflag(lastrace->flags, F_CANWILL, OT_S_PLANESHIFT, NA, NA, "pw:1;");
// likes/dislikes
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "destroying the undead");
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "killing evil creatures");
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "blessing objects");
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "acts of charity");
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "casting holy spells");
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "sacrificing cursed objects through prayer");
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "attacking good, peaceful or helpless creatures");
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "the use of poison");
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "cursing objects");
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "eating pets");
addrace(R_GODTHIEVES, "Felix", 300, '@', C_BOLDMAGENTA, MT_FLESH, RC_GOD);
addflag(lastrace->flags, F_ALIGNMENT, AL_NEUTRAL, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, NA, NA, "20");
addflag(lastrace->flags, F_STARTATT, A_DEX, NA, NA, "10");
addflag(lastrace->flags, F_STARTATT, A_WIS, NA, NA, "9");
addflag(lastrace->flags, F_STARTATT, A_IQ, NA, NA, "10");
addflag(lastrace->flags, F_STARTATT, A_CON, NA, NA, "8");
addflag(lastrace->flags, F_STARTATT, A_CHA, NA, NA, "6");
addflag(lastrace->flags, F_STARTASLEEPPCT, 0, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 30, NA, NA, NULL);
addflag(lastrace->flags, F_UNIQUE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_FISTS, NA, NA, "1d2");
addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "+5 dagger of sharpness");
addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "blessed ring of hunger");
addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "10 huge bags of holding");
//addflag(lastrace->flags, F_WANTS, OT_GOLD, NA, NA, NULL);
addflag(lastrace->flags, F_WANTSOBFLAG, F_RARITY, NA, NA, NULL); // ie. everything
addflag(lastrace->flags, F_STARTSKILL, SK_THIEVERY, PR_MASTER, NA, NULL);
addflag(lastrace->flags, F_STARTSKILL, SK_STEALTH, PR_MASTER, NA, NULL);
addflag(lastrace->flags, F_STARTSKILL, SK_BACKSTAB, PR_MASTER, NA, NULL);
addflag(lastrace->flags, F_STARTSKILL, SK_THROWING, PR_MASTER, NA, NULL);
addflag(lastrace->flags, F_STARTSKILL, SK_CLIMBING, PR_MASTER, NA, NULL);
addflag(lastrace->flags, F_SPELLCASTTEXT, NA, NA, NA, "waves his hand");
// god abilities
addflag(lastrace->flags, F_GODOF, NA, NA, NA, "Thieves");
addflag(lastrace->flags, F_FLEEONHPPCT, 10, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_A_HIDE, NA, NA, "pw:10;");
addflag(lastrace->flags, F_CANWILL, OT_S_CALLWIND, NA, NA, "pw:10;");
addflag(lastrace->flags, F_CANWILL, OT_S_CONFISCATE, NA, NA, "pw:10;");
addflag(lastrace->flags, F_CANWILL, OT_S_WISHLIMITED, NA, NA, "pw:10;");
addflag(lastrace->flags, F_CANWILL, OT_S_HUNGER, NA, NA, "pw:1;");
addflag(lastrace->flags, F_CANWILL, OT_S_PLANESHIFT, NA, NA, "pw:1;");
// likes/dislikes
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "backstabbing");
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "stealing items");
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "lockpicking");
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "purchasing items");
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "giving away or discarding money");
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "opening locked objects through force");
addrace(R_GODDEATH, "Hecta", 100, '@', C_BOLDMAGENTA, MT_FLESH, RC_GOD); addrace(R_GODDEATH, "Hecta", 100, '@', C_BOLDMAGENTA, MT_FLESH, RC_GOD);
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, NA, NA, "16"); addflag(lastrace->flags, F_STARTATT, A_STR, NA, NA, "16");
addflag(lastrace->flags, F_STARTATT, A_DEX, NA, NA, "20"); addflag(lastrace->flags, F_STARTATT, A_DEX, NA, NA, "20");
addflag(lastrace->flags, F_STARTATT, A_WIS, NA, NA, "15"); addflag(lastrace->flags, F_STARTATT, A_WIS, NA, NA, "15");
@ -8286,44 +8445,20 @@ void initrace(void) {
} }
addflag(lastrace->flags, F_CANWILL, OT_S_WISHLIMITED, NA, NA, "pw:10;"); addflag(lastrace->flags, F_CANWILL, OT_S_WISHLIMITED, NA, NA, "pw:10;");
addflag(lastrace->flags, F_CANWILL, OT_S_PLANESHIFT, NA, NA, "pw:1;"); addflag(lastrace->flags, F_CANWILL, OT_S_PLANESHIFT, NA, NA, "pw:1;");
// likes
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "killing (especially the good-aligned)");
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "attacking the helpless");
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "casting necromancy spells");
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "cursing objects");
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "allowing enemies to flee");
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "magical healing");
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "bestowing blessings");
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "casting holy spells");
addrace(R_GODGREED, "Avamon", 300, '@', C_BOLDMAGENTA, MT_FLESH, RC_GOD);
addflag(lastrace->flags, F_STARTATT, A_STR, NA, NA, "20");
addflag(lastrace->flags, F_STARTATT, A_DEX, NA, NA, "10");
addflag(lastrace->flags, F_STARTATT, A_WIS, NA, NA, "9");
addflag(lastrace->flags, F_STARTATT, A_IQ, NA, NA, "10");
addflag(lastrace->flags, F_STARTATT, A_CON, NA, NA, "8");
addflag(lastrace->flags, F_STARTATT, A_CHA, NA, NA, "6");
addflag(lastrace->flags, F_STARTASLEEPPCT, 0, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 30, NA, NA, NULL);
addflag(lastrace->flags, F_UNIQUE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_SLOW, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_SLOW, NA, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_FISTS, NA, NA, "1d2");
addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "+5 dagger of sharpness");
addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "blessed ring of hunger");
addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "10 huge bags of holding");
//addflag(lastrace->flags, F_WANTS, OT_GOLD, NA, NA, NULL);
addflag(lastrace->flags, F_WANTSOBFLAG, F_RARITY, NA, NA, NULL); // ie. everything
addflag(lastrace->flags, F_STARTSKILL, SK_THIEVERY, PR_MASTER, NA, NULL);
addflag(lastrace->flags, F_STARTSKILL, SK_STEALTH, PR_MASTER, NA, NULL);
addflag(lastrace->flags, F_STARTSKILL, SK_BACKSTAB, PR_MASTER, NA, NULL);
addflag(lastrace->flags, F_STARTSKILL, SK_THROWING, PR_MASTER, NA, NULL);
addflag(lastrace->flags, F_STARTSKILL, SK_CLIMBING, PR_MASTER, NA, NULL);
addflag(lastrace->flags, F_SPELLCASTTEXT, NA, NA, NA, "waves his hand");
// god abilities
addflag(lastrace->flags, F_GODOF, NA, NA, NA, "Thieves");
addflag(lastrace->flags, F_FLEEONHPPCT, 10, NA, NA, NULL);
addflag(lastrace->flags, F_OBESE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_A_HIDE, NA, NA, "pw:10;");
addflag(lastrace->flags, F_CANWILL, OT_S_CALLWIND, NA, NA, "pw:10;");
addflag(lastrace->flags, F_CANWILL, OT_S_CONFISCATE, NA, NA, "pw:10;");
addflag(lastrace->flags, F_CANWILL, OT_S_WISHLIMITED, NA, NA, "pw:10;");
addflag(lastrace->flags, F_CANWILL, OT_S_HUNGER, NA, NA, "pw:1;");
addflag(lastrace->flags, F_CANWILL, OT_S_PLANESHIFT, NA, NA, "pw:1;");
addrace(R_GODMERCY, "Yumi", 300, '@', C_BOLDMAGENTA, MT_FLESH, RC_GOD); addrace(R_GODMERCY, "Yumi", 300, '@', C_BOLDMAGENTA, MT_FLESH, RC_GOD);
addflag(lastrace->flags, F_ALIGNMENT, AL_GOOD, NA, NA, NULL);
addflag(lastrace->flags, F_FLEEONHPPCT, 95, NA, NA, ""); addflag(lastrace->flags, F_FLEEONHPPCT, 95, NA, NA, "");
addflag(lastrace->flags, F_STARTATT, A_STR, NA, NA, "10"); addflag(lastrace->flags, F_STARTATT, A_STR, NA, NA, "10");
addflag(lastrace->flags, F_STARTATT, A_DEX, NA, NA, "10"); addflag(lastrace->flags, F_STARTATT, A_DEX, NA, NA, "10");
@ -8352,6 +8487,7 @@ void initrace(void) {
addflag(lastrace->flags, F_CANWILL, OT_S_PLANESHIFT, NA, NA, "pw:1;"); addflag(lastrace->flags, F_CANWILL, OT_S_PLANESHIFT, NA, NA, "pw:1;");
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "the successful casting of healing spells"); addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "the successful casting of healing spells");
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "allowing fleeing creatures to escape"); addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "allowing fleeing creatures to escape");
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "acts of charity");
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "natural healing"); addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "natural healing");
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "attacking the innocent"); addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "attacking the innocent");
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "sneak attacks"); addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "sneak attacks");
@ -8361,6 +8497,7 @@ void initrace(void) {
// monsters // monsters
addrace(R_BEHOLDER, "beholder", 5, 'e', C_MAGENTA, MT_FLESH, RC_MAGIC); addrace(R_BEHOLDER, "beholder", 5, 'e', C_MAGENTA, MT_FLESH, RC_MAGIC);
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_VHIGH, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, AT_VHIGH, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 50, NA, NULL);
@ -8433,6 +8570,7 @@ void initrace(void) {
// special attack handled in attack.c // special attack handled in attack.c
addrace(R_CREEPINGCLAW, "creeping claw", 3, 'x', C_YELLOW, MT_FLESH, RC_MAGIC); addrace(R_CREEPINGCLAW, "creeping claw", 3, 'x', C_YELLOW, MT_FLESH, RC_MAGIC);
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 78, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 78, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_TINY, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_TINY, NA, NA, NULL);
@ -8457,6 +8595,7 @@ void initrace(void) {
addflag(lastrace->flags, F_CANWILL, OT_A_CHARGE, NA, NA, "range:5;"); addflag(lastrace->flags, F_CANWILL, OT_A_CHARGE, NA, NA, "range:5;");
addrace(R_DARKMANTLE, "darkmantle", 70, 'U', C_BLUE, MT_FLESH, RC_MAGIC); addrace(R_DARKMANTLE, "darkmantle", 70, 'U', C_BLUE, MT_FLESH, RC_MAGIC);
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_STARTHIDDENPCT, 80, NA, NA, NULL); addflag(lastrace->flags, F_STARTHIDDENPCT, 80, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_HIGH, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, AT_HIGH, NA, NULL);
@ -8516,6 +8655,7 @@ void initrace(void) {
addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL);
addrace(R_GIANTHILL, "hill giant", 160, 'H', C_GREY, MT_FLESH, RC_HUMANOID); addrace(R_GIANTHILL, "hill giant", 160, 'H', C_GREY, MT_FLESH, RC_HUMANOID);
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 55, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 55, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_FOREST, 55, NA, NULL); addflag(lastrace->flags, F_RARITY, H_FOREST, 55, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
@ -8547,6 +8687,7 @@ void initrace(void) {
addflag(lastrace->flags, F_HASSKILL, SK_TRACKING, PR_SKILLED, NA, NULL); addflag(lastrace->flags, F_HASSKILL, SK_TRACKING, PR_SKILLED, NA, NULL);
addrace(R_GIANTFIRE, "fire giant", 160, 'H', C_RED, MT_FLESH, RC_HUMANOID); addrace(R_GIANTFIRE, "fire giant", 160, 'H', C_RED, MT_FLESH, RC_HUMANOID);
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 50, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_HUGE, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_HUGE, NA, NA, NULL);
@ -8578,6 +8719,7 @@ void initrace(void) {
addrace(R_GIANTFIREFC, "fire giant forgecaller", 160, 'H', C_RED, MT_FLESH, RC_HUMANOID); addrace(R_GIANTFIREFC, "fire giant forgecaller", 160, 'H', C_RED, MT_FLESH, RC_HUMANOID);
lastrace->baseid = R_GIANTFIRE; lastrace->baseid = R_GIANTFIRE;
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "fire giant corpse"); addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "fire giant corpse");
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 48, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 48, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
@ -8613,6 +8755,7 @@ void initrace(void) {
addflag(lastrace->flags, F_HASSKILL, SK_TRACKING, PR_SKILLED, NA, NULL); addflag(lastrace->flags, F_HASSKILL, SK_TRACKING, PR_SKILLED, NA, NULL);
addrace(R_GIANTFIRETITAN, "fire titan", 160, 'H', C_RED, MT_FLESH, RC_HUMANOID); addrace(R_GIANTFIRETITAN, "fire titan", 160, 'H', C_RED, MT_FLESH, RC_HUMANOID);
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 40, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 40, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_ENORMOUS, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_ENORMOUS, NA, NA, NULL);
@ -8644,6 +8787,7 @@ void initrace(void) {
// TODO: storm titan // TODO: storm titan
addrace(R_GNOLL, "gnoll", 130, 'h', C_BROWN, MT_FLESH, RC_HUMANOID); addrace(R_GNOLL, "gnoll", 130, 'h', C_BROWN, MT_FLESH, RC_HUMANOID);
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "gnoll corpse"); addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "gnoll corpse");
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NUMAPPEAR, 2, 3, NA, ""); addflag(lastrace->flags, F_NUMAPPEAR, 2, 3, NA, "");
@ -8669,6 +8813,7 @@ void initrace(void) {
addrace(R_GNOLLHM, "gnoll huntmaster", 130, 'h', C_BROWN, MT_FLESH, RC_HUMANOID); addrace(R_GNOLLHM, "gnoll huntmaster", 130, 'h', C_BROWN, MT_FLESH, RC_HUMANOID);
lastrace->baseid = R_GNOLL; lastrace->baseid = R_GNOLL;
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "gnoll corpse"); addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "gnoll corpse");
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL);
@ -8698,6 +8843,7 @@ void initrace(void) {
addrace(R_GNOLLMR, "gnoll marauder", 130, 'h', C_BROWN, MT_FLESH, RC_HUMANOID); addrace(R_GNOLLMR, "gnoll marauder", 130, 'h', C_BROWN, MT_FLESH, RC_HUMANOID);
lastrace->baseid = R_GNOLL; lastrace->baseid = R_GNOLL;
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "gnoll corpse"); addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "gnoll corpse");
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL);
@ -8724,6 +8870,7 @@ void initrace(void) {
addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL);
addrace(R_GOBLIN, "goblin", 20, 'g', C_BROWN, MT_FLESH, RC_HUMANOID); addrace(R_GOBLIN, "goblin", 20, 'g', C_BROWN, MT_FLESH, RC_HUMANOID);
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_A_FEIGNDEATH, NA, NA, NULL); addflag(lastrace->flags, F_CANWILL, OT_A_FEIGNDEATH, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 87, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 87, NA, NULL);
@ -8753,6 +8900,7 @@ void initrace(void) {
addrace(R_GOBLINWAR, "goblin warrior", 30, 'g', C_BROWN, MT_FLESH, RC_HUMANOID); addrace(R_GOBLINWAR, "goblin warrior", 30, 'g', C_BROWN, MT_FLESH, RC_HUMANOID);
lastrace->baseid = R_GOBLIN; lastrace->baseid = R_GOBLIN;
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "goblin corpse"); addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "goblin corpse");
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 75, NA, NULL);
@ -8780,6 +8928,7 @@ void initrace(void) {
addrace(R_GOBLINSHOOTER, "goblin sharpshooter", 20, 'g', C_BROWN, MT_FLESH, RC_HUMANOID); addrace(R_GOBLINSHOOTER, "goblin sharpshooter", 20, 'g', C_BROWN, MT_FLESH, RC_HUMANOID);
lastrace->baseid = R_GOBLIN; lastrace->baseid = R_GOBLIN;
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "goblin corpse"); addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "goblin corpse");
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 70, NA, NULL);
@ -8810,6 +8959,7 @@ void initrace(void) {
addrace(R_GOBLINHEXER, "goblin hexer", 20, 'g', C_BROWN, MT_FLESH, RC_HUMANOID); addrace(R_GOBLINHEXER, "goblin hexer", 20, 'g', C_BROWN, MT_FLESH, RC_HUMANOID);
lastrace->baseid = R_GOBLIN; lastrace->baseid = R_GOBLIN;
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "goblin corpse"); addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "goblin corpse");
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 63, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 63, NA, NULL);
@ -8838,6 +8988,7 @@ void initrace(void) {
addflag(lastrace->flags, F_MINIONS, 90, 1, 2, "goblin"); addflag(lastrace->flags, F_MINIONS, 90, 1, 2, "goblin");
addrace(R_HOBGOBLIN, "hobgoblin", 90, 'g', C_GREEN, MT_FLESH, RC_HUMANOID); addrace(R_HOBGOBLIN, "hobgoblin", 90, 'g', C_GREEN, MT_FLESH, RC_HUMANOID);
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 73, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 73, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_FOREST, 73, NA, NULL); addflag(lastrace->flags, F_RARITY, H_FOREST, 73, NA, NULL);
@ -8868,6 +9019,7 @@ void initrace(void) {
addrace(R_HOBGOBLINWAR, "hobgoblin warrior", 90, 'g', C_GREEN, MT_FLESH, RC_HUMANOID); addrace(R_HOBGOBLINWAR, "hobgoblin warrior", 90, 'g', C_GREEN, MT_FLESH, RC_HUMANOID);
lastrace->baseid = R_HOBGOBLIN; lastrace->baseid = R_HOBGOBLIN;
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 60, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 60, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_FOREST, 60, NA, NULL); addflag(lastrace->flags, F_RARITY, H_FOREST, 60, NA, NULL);
@ -8901,6 +9053,7 @@ void initrace(void) {
// TODO: hobgoblin warcaster // TODO: hobgoblin warcaster
addrace(R_KOBOLD, "kobold", 18, 'k', C_BROWN, MT_FLESH, RC_HUMANOID); addrace(R_KOBOLD, "kobold", 18, 'k', C_BROWN, MT_FLESH, RC_HUMANOID);
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 95, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 95, NA, NULL);
addflag(lastrace->flags, F_POISONOUS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_POISONOUS, B_TRUE, NA, NA, NULL);
@ -8916,6 +9069,7 @@ void initrace(void) {
addflag(lastrace->flags, F_STARTATT, A_DEX, AT_HIGH, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_DEX, AT_HIGH, NA, NULL);
addflag(lastrace->flags, F_STARTOBDT, 20, DT_PIERCE, NA, NULL); addflag(lastrace->flags, F_STARTOBDT, 20, DT_PIERCE, NA, NULL);
addflag(lastrace->flags, F_STARTOBCLASS, 25, OC_POTION, NA, NULL); addflag(lastrace->flags, F_STARTOBCLASS, 25, OC_POTION, NA, NULL);
addflag(lastrace->flags, F_STARTSKILL, SK_THROWING, PR_ADEPT, NA, NULL);
addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "1-3 darts"); addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "1-3 darts");
addflag(lastrace->flags, F_STARTOB, 10, NA, NA, "javelin"); addflag(lastrace->flags, F_STARTOB, 10, NA, NA, "javelin");
addflag(lastrace->flags, F_STARTOB, 15, NA, NA, "buckler"); addflag(lastrace->flags, F_STARTOB, 15, NA, NA, "buckler");
@ -8974,6 +9128,7 @@ void initrace(void) {
addflag(lastrace->flags, F_HASSKILL, SK_TRACKING, PR_SKILLED, NA, NULL); addflag(lastrace->flags, F_HASSKILL, SK_TRACKING, PR_SKILLED, NA, NULL);
addrace(R_LURKINGHORROR, "lurking horror", 100, 'U', C_MAGENTA, MT_FLESH, RC_DEMON); addrace(R_LURKINGHORROR, "lurking horror", 100, 'U', C_MAGENTA, MT_FLESH, RC_DEMON);
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL);
@ -9000,6 +9155,7 @@ void initrace(void) {
addrace(R_MINOTAUR, "minotaur", 130, 'H', C_BROWN, MT_FLESH, RC_HUMANOID); addrace(R_MINOTAUR, "minotaur", 130, 'H', C_BROWN, MT_FLESH, RC_HUMANOID);
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 62, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 62, NA, NULL);
@ -9014,8 +9170,8 @@ void initrace(void) {
addflag(lastrace->flags, F_STARTATT, A_IQ, NA, NA, "5-7"); addflag(lastrace->flags, F_STARTATT, A_IQ, NA, NA, "5-7");
addflag(lastrace->flags, F_STARTATT, A_DEX, AT_GTAVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_DEX, AT_GTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_VHIGH, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, AT_VHIGH, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_BUTT, NA, NA, "2d4"); addflag(lastrace->flags, F_HASATTACK, OT_BUTT, NA, NA, "2d4+6");
addflag(lastrace->flags, F_HASATTACK, OT_BUTT, NA, NA, "2d4"); addflag(lastrace->flags, F_HASATTACK, OT_BUTT, NA, NA, "2d4+6");
addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "+2 heavy flail"); addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "+2 heavy flail");
addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "greataxe"); addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "greataxe");
addflag(lastrace->flags, F_WANTSBETTERWEP, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_WANTSBETTERWEP, B_TRUE, NA, NA, NULL);
@ -9029,6 +9185,7 @@ void initrace(void) {
addrace(R_OGRE, "ogre", 160, 'O', C_BROWN, MT_FLESH, RC_HUMANOID); addrace(R_OGRE, "ogre", 160, 'O', C_BROWN, MT_FLESH, RC_HUMANOID);
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 60, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 60, NA, NULL);
@ -9058,6 +9215,7 @@ void initrace(void) {
addrace(R_OGRESAVAGE, "ogre savage", 160, 'O', C_BROWN, MT_FLESH, RC_HUMANOID); addrace(R_OGRESAVAGE, "ogre savage", 160, 'O', C_BROWN, MT_FLESH, RC_HUMANOID);
lastrace->baseid = R_OGRE; lastrace->baseid = R_OGRE;
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 45, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 45, NA, NULL);
@ -9087,6 +9245,7 @@ void initrace(void) {
addrace(R_OGREWARHULK, "ogre warhulk", 160, 'O', C_BROWN, MT_FLESH, RC_HUMANOID); addrace(R_OGREWARHULK, "ogre warhulk", 160, 'O', C_BROWN, MT_FLESH, RC_HUMANOID);
lastrace->baseid = R_OGRE; lastrace->baseid = R_OGRE;
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 45, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 45, NA, NULL);
@ -9115,6 +9274,7 @@ void initrace(void) {
addflag(lastrace->flags, F_MINIONS, 25, 1, 2, "orc warrior"); addflag(lastrace->flags, F_MINIONS, 25, 1, 2, "orc warrior");
addrace(R_ORC, "orc", 90, 'o', C_BROWN, MT_FLESH, RC_HUMANOID); addrace(R_ORC, "orc", 90, 'o', C_BROWN, MT_FLESH, RC_HUMANOID);
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 78, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 78, NA, NULL);
@ -9144,6 +9304,7 @@ void initrace(void) {
addrace(R_ORCWARRIOR, "orc warrior", 90, 'o', C_BROWN, MT_FLESH, RC_HUMANOID); addrace(R_ORCWARRIOR, "orc warrior", 90, 'o', C_BROWN, MT_FLESH, RC_HUMANOID);
lastrace->baseid = R_ORC; lastrace->baseid = R_ORC;
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 70, NA, NULL);
@ -9200,6 +9361,7 @@ void initrace(void) {
addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL);
addrace(R_PEGASUS, "pegasus", 130, 'Q', C_GREY, MT_FLESH, RC_MAGIC); addrace(R_PEGASUS, "pegasus", 130, 'Q', C_GREY, MT_FLESH, RC_MAGIC);
addflag(lastrace->flags, F_ALIGNMENT, AL_GOOD, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 57, NA, ""); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 57, NA, "");
addflag(lastrace->flags, F_RARITY, H_FOREST, 57, NA, NULL); addflag(lastrace->flags, F_RARITY, H_FOREST, 57, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_HIGH, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, AT_HIGH, NA, NULL);
@ -9227,6 +9389,7 @@ void initrace(void) {
addflag(lastrace->flags, F_HASSKILL, SK_TRACKING, PR_SKILLED, NA, NULL); addflag(lastrace->flags, F_HASSKILL, SK_TRACKING, PR_SKILLED, NA, NULL);
addrace(R_POLTERGEIST, "poltergeist", 50, 'p', C_GREEN, MT_FLESH, RC_UNDEAD); // sPirit addrace(R_POLTERGEIST, "poltergeist", 50, 'p', C_GREEN, MT_FLESH, RC_UNDEAD); // sPirit
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_AVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, AT_AVERAGE, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
@ -9254,6 +9417,7 @@ void initrace(void) {
addflag(lastrace->flags, F_XPMULTIPLY, 2, NA, NA, NULL); addflag(lastrace->flags, F_XPMULTIPLY, 2, NA, NA, NULL);
addrace(R_SATYR, "satyr", 80, 'h', C_GREEN, MT_FLESH, RC_HUMANOID); addrace(R_SATYR, "satyr", 80, 'h', C_GREEN, MT_FLESH, RC_HUMANOID);
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 72, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 72, NA, NULL);
@ -9285,6 +9449,7 @@ void initrace(void) {
addflag(lastrace->flags, F_HASSKILL, SK_TRACKING, PR_SKILLED, NA, NULL); addflag(lastrace->flags, F_HASSKILL, SK_TRACKING, PR_SKILLED, NA, NULL);
addrace(R_SHADOWCAT, "shadowcat", 5, 'f', C_BLUE, MT_FLESH, RC_MAGIC); addrace(R_SHADOWCAT, "shadowcat", 5, 'f', C_BLUE, MT_FLESH, RC_MAGIC);
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 65, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 65, NA, NULL);
@ -9355,6 +9520,7 @@ void initrace(void) {
addrace(R_TROLL, "troll", 100, 't', C_GREEN, MT_FLESH, RC_HUMANOID); addrace(R_TROLL, "troll", 100, 't', C_GREEN, MT_FLESH, RC_HUMANOID);
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 65, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 65, NA, NULL);
@ -9780,6 +9946,7 @@ void initrace(void) {
addflag(lastrace->flags, F_NOISETEXT, N_LOWHP, 2, NA, "whines in pain^whining"); addflag(lastrace->flags, F_NOISETEXT, N_LOWHP, 2, NA, "whines in pain^whining");
addflag(lastrace->flags, F_FLEEONHPPCT, 60, NA, NA, ""); addflag(lastrace->flags, F_FLEEONHPPCT, 60, NA, NA, "");
addrace(R_DOGBLINK, "blink dog", 35, 'd', C_BLUE, MT_FLESH, RC_ANIMAL); addrace(R_DOGBLINK, "blink dog", 35, 'd', C_BLUE, MT_FLESH, RC_ANIMAL);
addflag(lastrace->flags, F_ALIGNMENT, AL_GOOD, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NUMAPPEAR, 2, 4, NA, ""); addflag(lastrace->flags, F_NUMAPPEAR, 2, 4, NA, "");
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_HIGH, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, AT_HIGH, NA, NULL);
@ -9805,6 +9972,7 @@ void initrace(void) {
addflag(lastrace->flags, F_NOISETEXT, N_FRUSTRATED, 3, NA, "growls^growling"); addflag(lastrace->flags, F_NOISETEXT, N_FRUSTRATED, 3, NA, "growls^growling");
addflag(lastrace->flags, F_NOISETEXT, N_LOWHP, 2, NA, "whines in pain^whining"); addflag(lastrace->flags, F_NOISETEXT, N_LOWHP, 2, NA, "whines in pain^whining");
addrace(R_DOGDEATH, "death hound", 40, 'd', C_MAGENTA, MT_FLESH, RC_ANIMAL); addrace(R_DOGDEATH, "death hound", 40, 'd', C_MAGENTA, MT_FLESH, RC_ANIMAL);
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_NUMAPPEAR, 2, 6, NA, ""); addflag(lastrace->flags, F_NUMAPPEAR, 2, 6, NA, "");
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_CON, AT_AVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_CON, AT_AVERAGE, NA, NULL);
@ -10456,6 +10624,7 @@ void initrace(void) {
// undead // undead
addrace(R_ZOMBIE, "zombie", 50, 'Z', C_BLUE, MT_FLESH, RC_UNDEAD); addrace(R_ZOMBIE, "zombie", 50, 'Z', C_BLUE, MT_FLESH, RC_UNDEAD);
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_MINDLESS, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_MINDLESS, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_CON, NA, NA, "6"); addflag(lastrace->flags, F_STARTATT, A_CON, NA, NA, "6");
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 85, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 85, NA, NULL);
@ -10477,6 +10646,7 @@ void initrace(void) {
addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL);
addrace(R_SKELETON, "skeleton", 20, 'Z', C_GREY, MT_BONE, RC_UNDEAD); addrace(R_SKELETON, "skeleton", 20, 'Z', C_GREY, MT_BONE, RC_UNDEAD);
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_MINDLESS, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_MINDLESS, NA, NULL);
addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "5-20 bones"); addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "5-20 bones");
addflag(lastrace->flags, F_BLOODOB, NA, NA, NA, NULL); addflag(lastrace->flags, F_BLOODOB, NA, NA, NA, NULL);
@ -10496,6 +10666,7 @@ void initrace(void) {
addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL);
addrace(R_GHAST, "ghast", 50, 'Z', C_MAGENTA, MT_FLESH, RC_UNDEAD); addrace(R_GHAST, "ghast", 50, 'Z', C_MAGENTA, MT_FLESH, RC_UNDEAD);
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_GTAVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, AT_GTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_BLOODOB, NA, NA, NA, NULL); addflag(lastrace->flags, F_BLOODOB, NA, NA, NA, NULL);
addflag(lastrace->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL);
@ -10516,6 +10687,7 @@ void initrace(void) {
addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL);
addrace(R_GHOST, "ghost", 50, 'p', C_BLUE, MT_MAGIC, RC_UNDEAD); // p for sPirit addrace(R_GHOST, "ghost", 50, 'p', C_BLUE, MT_MAGIC, RC_UNDEAD); // p for sPirit
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_GTAVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, AT_GTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_BLOODOB, NA, NA, NA, NULL); addflag(lastrace->flags, F_BLOODOB, NA, NA, NA, NULL);
addflag(lastrace->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL);
@ -10536,6 +10708,7 @@ void initrace(void) {
// their previous corpse. use f_mycorpse->oid for this. // their previous corpse. use f_mycorpse->oid for this.
addrace(R_GHOUL, "ghoul", 50, 'Z', C_BLUE, MT_FLESH, RC_UNDEAD); addrace(R_GHOUL, "ghoul", 50, 'Z', C_BLUE, MT_FLESH, RC_UNDEAD);
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_MINDLESS, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_MINDLESS, NA, NULL);
addflag(lastrace->flags, F_BLOODOB, NA, NA, NA, NULL); addflag(lastrace->flags, F_BLOODOB, NA, NA, NA, NULL);
addflag(lastrace->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL);
@ -10556,6 +10729,7 @@ void initrace(void) {
addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL);
addrace(R_VAMPIRE, "vampire", 75, 'V', C_BLUE, MT_FLESH, RC_UNDEAD); addrace(R_VAMPIRE, "vampire", 75, 'V', C_BLUE, MT_FLESH, RC_UNDEAD);
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_EXHIGH, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, AT_EXHIGH, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_DEX, AT_VHIGH, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_DEX, AT_VHIGH, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_WIS, AT_GTAVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_WIS, AT_GTAVERAGE, NA, NULL);
@ -11396,7 +11570,7 @@ void addtrail(lifeform_t *lf, int dir) {
} else { } else {
char buf[BUFLENTINY]; char buf[BUFLENTINY];
sprintf(buf, "%d", lf->id); sprintf(buf, "%d", lf->id);
footprint = addob(lf->cell->obpile, "footprint"); footprint = addobfast(lf->cell->obpile, OT_FOOTPRINT);
addtempflag(footprint->flags, F_TRAIL, lf->race->id, fpdir, S_SIGHT, buf, getfootprinttime(lf)); addtempflag(footprint->flags, F_TRAIL, lf->race->id, fpdir, S_SIGHT, buf, getfootprinttime(lf));
} }
} }
@ -11409,7 +11583,7 @@ void addtrail(lifeform_t *lf, int dir) {
} else { } else {
char buf[BUFLENTINY]; char buf[BUFLENTINY];
sprintf(buf, "%d", lf->id); sprintf(buf, "%d", lf->id);
scent = addob(lf->cell->obpile, "scent"); scent = addobfast(lf->cell->obpile, OT_SCENT);
addtempflag(scent->flags, F_TRAIL, lf->race->id, dir, S_SMELL, buf, SCENTTIME); addtempflag(scent->flags, F_TRAIL, lf->race->id, dir, S_SMELL, buf, SCENTTIME);
} }
} }
@ -13258,14 +13432,14 @@ void precalclos(lifeform_t *lf) {
cell_t *c; cell_t *c;
cell_t **los; cell_t **los;
int maxvisrange; int maxvisrange;
int oldnlos = -1,nlos = 0; int nlos = 0;
int i; int i;
los = malloc( sizeof(cell_t *) * (MAX_MAPW * MAX_MAPH)); los = malloc( sizeof(cell_t *) * (MAX_MAPW * MAX_MAPH));
// free existing structures // free existing structures
if (lf->los) { if (lf->los) {
oldnlos = lf->nlos;
free(lf->los); lf->los = NULL; free(lf->los); lf->los = NULL;
} }
@ -13275,7 +13449,8 @@ void precalclos(lifeform_t *lf) {
for (x = lf->cell->x - maxvisrange; x <= lf->cell->x + maxvisrange ; x++) { for (x = lf->cell->x - maxvisrange; x <= lf->cell->x + maxvisrange ; x++) {
c = getcellat(lf->cell->map, x, y); c = getcellat(lf->cell->map, x, y);
// //
if (c && (c != lf->cell) && haslos(lf, c)) { //if (c && (c != lf->cell) && haslos(lf, c)) {
if (c && haslos(lf, c)) {
los[nlos] = c; los[nlos] = c;
nlos++; nlos++;
} }
@ -14992,6 +15167,9 @@ int steal(lifeform_t *lf, obpile_t *op, enum FLAG wantflag) {
break; break;
} }
} // end foreach steal } // end foreach steal
if (isplayer(lf)) pleasegodmaybe(R_GODTHIEVES, 5+numgot);
return B_FALSE; return B_FALSE;
} }
@ -15496,6 +15674,18 @@ void turneffectslf(lifeform_t *lf) {
} }
} }
// gods get angry
if (isplayer(lf)) {
f = lfhasflag(lf, F_GAVEMONEY);
if (f) {
int angeramt;
angeramt = f->val[0];
limit(&angeramt, 25, NA);
angergodmaybe(R_GODTHIEVES, angeramt);
killflag(f);
}
}
// get more hungry // get more hungry
modhunger(lf, 1); modhunger(lf, 1);
@ -15826,7 +16016,7 @@ void turneffectslf(lifeform_t *lf) {
if (!asleep) { if (!asleep) {
if (poisoncausesvomit(f->val[0])) { if (poisoncausesvomit(f->val[0])) {
addob(lf->cell->obpile, "pool of vomit"); addobfast(lf->cell->obpile, OT_VOMITPOOL);
} }
loseconcentration(lf); loseconcentration(lf);
} }
@ -16664,7 +16854,7 @@ int validateraces(void) {
cell_t fakecell; cell_t fakecell;
map_t fakemap; map_t fakemap;
// add flags based on raceclass // add flags based on raceclass, and fill in missing alignments
for (r = firstrace ; r ; r = r->next) { for (r = firstrace ; r ; r = r->next) {
if (r->raceclass->id == RC_AQUATIC) { if (r->raceclass->id == RC_AQUATIC) {
addflag(r->flags, F_HASSKILL, SK_SWIMMING, PR_MASTER, NA, NULL); addflag(r->flags, F_HASSKILL, SK_SWIMMING, PR_MASTER, NA, NULL);
@ -16706,6 +16896,10 @@ int validateraces(void) {
addflag(r->flags, F_DTVULN, DT_HOLY, NA, NA, NULL); addflag(r->flags, F_DTVULN, DT_HOLY, NA, NA, NULL);
addflag(r->flags, F_SEEINDARK, B_TRUE, NA, NA, NULL); addflag(r->flags, F_SEEINDARK, B_TRUE, NA, NA, NULL);
} }
if (!hasflag(r->flags, F_ALIGNMENT)) {
addflag(r->flags, F_ALIGNMENT, AL_NEUTRAL, NA, NA, NULL);
}
} }
// generate xp list // generate xp list

1
lf.h
View File

@ -89,6 +89,7 @@ void gainxp(lifeform_t *lf, long amt);
void genxplist(void); void genxplist(void);
int getactspeed(lifeform_t *lf); int getactspeed(lifeform_t *lf);
void getadjallies(lifeform_t *lf, object_t *stairob, lifeform_t **adjally, int *nadjallies); void getadjallies(lifeform_t *lf, object_t *stairob, lifeform_t **adjally, int *nadjallies);
enum ALIGNMENT getalignment(lifeform_t *lf);
enum ALLEGIENCE getallegiance(lifeform_t *lf); enum ALLEGIENCE getallegiance(lifeform_t *lf);
int getallouterarmour(lifeform_t *lf, object_t **ob, int *nobs); int getallouterarmour(lifeform_t *lf, object_t **ob, int *nobs);
object_t *getarmour(lifeform_t *lf, enum BODYPART bp); object_t *getarmour(lifeform_t *lf, enum BODYPART bp);

30
map.c
View File

@ -395,7 +395,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int jobok, int
ot = NULL; ot = NULL;
} }
if (ot) { if (ot) {
addob(lf->pack, ot->name); addobfast(lf->pack, ot->id);
} }
} }
} }
@ -1492,6 +1492,15 @@ int countcellexitsfor(lifeform_t *lf) {
return exits; return exits;
} }
int countlfs(map_t *map) {
lifeform_t *lf;
int count = 0;
for (lf = map->lf ; lf ; lf = lf->next) {
count++;
}
return count;
}
// //
void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_t *entryob) { void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_t *entryob) {
int wantrooms = B_TRUE; int wantrooms = B_TRUE;
@ -1736,7 +1745,7 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
while (!c || !isempty(c) || countobs(c->obpile, B_TRUE)) { while (!c || !isempty(c) || countobs(c->obpile, B_TRUE)) {
c = getrandomroomcell(map, ANYROOM); c = getrandomroomcell(map, ANYROOM);
} }
o = addob(c->obpile, "staircase going up"); o = addobfast(c->obpile, OT_STAIRSUP);
// have to force these stairs to go back to a different region. // have to force these stairs to go back to a different region.
f = hasflag(o->flags, F_CLIMBABLE); f = hasflag(o->flags, F_CLIMBABLE);
f->val[1] = map->region->parentregion->id; f->val[1] = map->region->parentregion->id;
@ -1745,7 +1754,7 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
// special case: first dungeon level has barriers over the exit stairs // special case: first dungeon level has barriers over the exit stairs
if (map->region->rtype->id == RG_FIRSTDUNGEON) { if (map->region->rtype->id == RG_FIRSTDUNGEON) {
if (c->lf) killlf(c->lf); if (c->lf) killlf(c->lf);
addob(c->obpile, "magical barrier"); addobfast(c->obpile, OT_MAGICBARRIER);
} }
} else { } else {
for (i = 0; i < map->region->rtype->stairsperlev; i++) { for (i = 0; i < map->region->rtype->stairsperlev; i++) {
@ -1753,7 +1762,7 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
while (!c || !isempty(c) || countobs(c->obpile, B_TRUE)) { while (!c || !isempty(c) || countobs(c->obpile, B_TRUE)) {
c = getrandomroomcell(map, ANYROOM); c = getrandomroomcell(map, ANYROOM);
} }
o = addob(c->obpile, "staircase going up"); o = addobfast(c->obpile, OT_STAIRSUP);
linkstairs(o, NULL); linkstairs(o, NULL);
} }
} }
@ -1765,7 +1774,7 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
while (!c || !isempty(c) || countobs(c->obpile, B_TRUE)) { while (!c || !isempty(c) || countobs(c->obpile, B_TRUE)) {
c = getrandomroomcell(map, ANYROOM); c = getrandomroomcell(map, ANYROOM);
} }
o = addob(c->obpile, "staircase going down"); o = addobfast(c->obpile, OT_STAIRSDOWN);
linkstairs(o, NULL); linkstairs(o, NULL);
} }
} }
@ -1999,6 +2008,11 @@ void createheaven(map_t *map, int depth, map_t *parentmap, int exitdir, object_t
assert(lf); assert(lf);
// add to god list // add to god list
godlf[ngodlfs++] = lf; godlf[ngodlfs++] = lf;
if (ngodlfs > MAXGODS) {
dblog("Error - number of gods(%d) exceeds MAXGODS.",ngodlfs);
msg("Error - number of gods(%d) exceeds MAXGODS.",ngodlfs);
exit(1);
}
} }
} }
} }
@ -2695,7 +2709,7 @@ void createpit(map_t *map, int depth, map_t *parentmap, int exitdir, object_t *e
// clear it // clear it
setcelltype(c, CT_CORRIDOR); setcelltype(c, CT_CORRIDOR);
// put an exit here // put an exit here
o = addobject(c->obpile, "hole in the roof", B_FALSE, B_FALSE); o = addobject(c->obpile, NULL, B_FALSE, B_FALSE, OT_HOLEINROOF);
assert(o); assert(o);
// link it // link it
linkstairs(o, entryob); linkstairs(o, entryob);
@ -2952,7 +2966,7 @@ void explodecells(cell_t *c, int dam, int killwalls, object_t *o, int range, int
if (cc && (mydist <= (range+1))) { if (cc && (mydist <= (range+1))) {
if (cc->lf && !isdead(cc->lf)) { if (cc->lf && !isdead(cc->lf)) {
// move away from centre of explosion // move away from centre of explosion
knockback(cc->lf, getdiraway(cc, c, NULL, B_FALSE, DT_COMPASS), 2, NULL, 40-(mydist*10)); knockback(cc->lf, getdiraway(cc, c, NULL, B_FALSE, DT_COMPASS, B_FALSE), 2, NULL, 40-(mydist*10));
} }
} }
} }
@ -4102,7 +4116,7 @@ int linkholes(map_t *map) {
} }
// note we specifically say DONT link the new hole, to avoid an infinite // note we specifically say DONT link the new hole, to avoid an infinite
// loop! // loop!
newob = addobject(c2->obpile, ot->name, B_FALSE, B_FALSE); newob = addobject(c2->obpile, NULL, B_FALSE, B_FALSE, ot->id);
// link holes manually now. // link holes manually now.
linkstairs(newob, o); linkstairs(newob, o);

30
move.c
View File

@ -435,7 +435,7 @@ int dorandommove(lifeform_t *lf, int badmovesok, int restonfail) {
// src is where something is // src is where something is
// dst is what we are going away from // dst is what we are going away from
// wantcheck is whether to check for dangerous things before considering a direction valid // wantcheck is whether to check for dangerous things before considering a direction valid
int getdiraway(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, int dirtype) { int getdiraway(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, int dirtype, int keepinlof) {
int d; int d;
cell_t *c; cell_t *c;
int maxdist=-1,bestdir=D_NONE; int maxdist=-1,bestdir=D_NONE;
@ -463,8 +463,6 @@ int getdiraway(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, int d
// destination is the thing we're fleeing from! // destination is the thing we're fleeing from!
thisdist = 0; thisdist = 0;
} else { } else {
if (wantcheck) { if (wantcheck) {
if (srclf) { if (srclf) {
if (canandwillmove(srclf, d, &error)) { if (canandwillmove(srclf, d, &error)) {
@ -487,6 +485,12 @@ int getdiraway(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, int d
} }
} }
if (keepinlof) {
if (!haslof(c, dst, LOF_NEED, NULL)) {
ok = B_FALSE;
}
}
if (ok) { if (ok) {
if (dirtype == DT_ORTH) { if (dirtype == DT_ORTH) {
thisdist = getcelldistorth(c, dst); thisdist = getcelldistorth(c, dst);
@ -791,7 +795,7 @@ int makeorthogonal(int dir) {
} }
// see 'movetowards' for description of dirtype // see 'movetowards' for description of dirtype
int moveawayfrom(lifeform_t *lf, cell_t *dst, int dirtype ) { int moveawayfrom(lifeform_t *lf, cell_t *dst, int dirtype, int keepinlof ) {
int dir; int dir;
int rv = B_TRUE; int rv = B_TRUE;
@ -801,7 +805,7 @@ int moveawayfrom(lifeform_t *lf, cell_t *dst, int dirtype ) {
} }
// move away from them // move away from them
dir = getdiraway(lf->cell, dst, lf, B_TRUE, dirtype); dir = getdiraway(lf->cell, dst, lf, B_TRUE, dirtype, keepinlof);
if (dir == D_NONE) { if (dir == D_NONE) {
rv = B_TRUE; rv = B_TRUE;
} else { } else {
@ -1179,11 +1183,12 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
for (l = newcell->map->lf ; l ; l = l->next) { for (l = newcell->map->lf ; l ; l = l->next) {
if (l != lf) { if (l != lf) {
flag_t *alarm; flag_t *alarm;
if (haslos(l, newcell)) { //if (haslos(l, newcell)) {
if (cansee(l, lf)) {
int dointerrupt = B_FALSE; int dointerrupt = B_FALSE;
if (isplayer(l)) { if (isplayer(l)) {
if (cansee(l, lf) && areenemies(lf, l)) { if (areenemies(lf, l)) {
if (lfhasflag(l, F_RUNNING) || lfhasflag(l, F_TRAINING)) { if (lfhasflag(l, F_RUNNING) || lfhasflag(l, F_TRAINING)) {
// TODO: also check for isresting(l), if we have allies standing watch // TODO: also check for isresting(l), if we have allies standing watch
getlfnamea(lf, lfname); getlfnamea(lf, lfname);
@ -1191,8 +1196,8 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
} }
dointerrupt = B_TRUE; dointerrupt = B_TRUE;
} }
} else { } else if (isplayer(lf)) {
if (isplayer(lf) && areallies(lf, l)) { if (areallies(lf, l)) {
// remember player's last known loc // remember player's last known loc
f = lfhasflag(l, F_PETOF); f = lfhasflag(l, F_PETOF);
if (f) { if (f) {
@ -1471,7 +1476,7 @@ int opendoor(lifeform_t *lf, object_t *o) {
if (isplayer(lf)) { if (isplayer(lf)) {
// has known trap? // has known trap?
if (hasflagval(o->flags, F_TRAPPED, NA, NA, B_TRUE, NULL)) { if (hasflagval(o->flags, F_TRAPPED, NA, NA, B_TRUE, NULL)) {
if (getattrbracket(getattr(lf, A_IQ), A_IQ, NULL) >= AT_AVERAGE) { if (getattrbracket(getattr(lf, A_WIS), A_WIS, NULL) >= AT_AVERAGE) {
char ch; char ch;
sprintf(buf,"Really open %s?", obname); sprintf(buf,"Really open %s?", obname);
ch = askchar(buf,"yn","n", B_TRUE); ch = askchar(buf,"yn","n", B_TRUE);
@ -1488,7 +1493,7 @@ int opendoor(lifeform_t *lf, object_t *o) {
dir = getdirtowards(doorcell, lf->cell, NULL, B_FALSE, DT_ORTH); dir = getdirtowards(doorcell, lf->cell, NULL, B_FALSE, DT_ORTH);
pastdoorcell = getcellindir(doorcell, dir); pastdoorcell = getcellindir(doorcell, dir);
if (pastdoorcell && getcellwaterdepth(pastdoorcell, NULL)) { if (pastdoorcell && getcellwaterdepth(pastdoorcell, NULL)) {
if (getattrbracket(getattr(lf, A_IQ), A_IQ, NULL) >= AT_AVERAGE) { if (getattrbracket(getattr(lf, A_WIS), A_WIS, NULL) >= AT_AVERAGE) {
char ch; char ch;
sprintf(buf,"Your hear running water behind %s. Really open it?", obname); sprintf(buf,"Your hear running water behind %s. Really open it?", obname);
ch = askchar(buf,"yn","n", B_TRUE); ch = askchar(buf,"yn","n", B_TRUE);
@ -2024,7 +2029,6 @@ int teleportto(lifeform_t *lf, cell_t *c, int wantsmoke) {
addob(lf->cell->obpile, "cloud of smoke"); addob(lf->cell->obpile, "cloud of smoke");
} }
movelf(lf, c); movelf(lf, c);
// addob(lf->cell->obpile, "cloud of smoke");
if (cansee(player, lf)) { if (cansee(player, lf)) {
redraw(); // redraw screen redraw(); // redraw screen
@ -2070,6 +2074,7 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
if (isplayer(lf) && !lfhasflag(lf, F_SNEAK)) { if (isplayer(lf) && !lfhasflag(lf, F_SNEAK)) {
if (cell && celldangerous(lf, cell, B_TRUE, &errcode)) { if (cell && celldangerous(lf, cell, B_TRUE, &errcode)) {
if (getattrbracket(getattr(lf, A_WIS), A_WIS, NULL) >= AT_AVERAGE) {
char ques[BUFLEN]; char ques[BUFLEN];
char ch; char ch;
if ((errcode == E_AVOIDOB) && rdata) { if ((errcode == E_AVOIDOB) && rdata) {
@ -2087,6 +2092,7 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
} }
} }
} }
}
moveok = B_FALSE; moveok = B_FALSE;
if (moveclear(lf, dir, &errcode)) { if (moveclear(lf, dir, &errcode)) {

4
move.h
View File

@ -8,12 +8,12 @@ int closedoorat(lifeform_t *lf, cell_t *c);
int closedoor(lifeform_t *lf, object_t *o); int closedoor(lifeform_t *lf, object_t *o);
int diropposite(int dir); int diropposite(int dir);
int dorandommove(lifeform_t *lf, int badmovesok, int restonfail); int dorandommove(lifeform_t *lf, int badmovesok, int restonfail);
int getdiraway(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, int dirtype); int getdiraway(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, int dirtype, int keepinlof);
int getdirtowards(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, int dirtype); int getdirtowards(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, int dirtype);
int getwalkoffdir(lifeform_t *lf, int dir); int getwalkoffdir(lifeform_t *lf, int dir);
int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher, int fallcheckdiff); int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher, int fallcheckdiff);
int makeorthogonal(int dir); int makeorthogonal(int dir);
int moveawayfrom(lifeform_t *lf, cell_t *dst, int dirtype); int moveawayfrom(lifeform_t *lf, cell_t *dst, int dirtype, int keepinlof);
int moveclear(lifeform_t *lf, int dir, enum ERROR *error); int moveclear(lifeform_t *lf, int dir, enum ERROR *error);
int moveeffects(lifeform_t *lf); int moveeffects(lifeform_t *lf);
int movelf(lifeform_t *lf, cell_t *newcell); int movelf(lifeform_t *lf, cell_t *newcell);

18
nexus.c
View File

@ -44,6 +44,9 @@ int numnpcnames;
extern vault_t *firstvault; extern vault_t *firstvault;
extern flag_t *retflag[];
extern int nretflags;
glyph_t playerglyph,tempglyph; glyph_t playerglyph,tempglyph;
double startticks,lastticks; double startticks,lastticks;
@ -1434,7 +1437,8 @@ void timeeffectsworld(map_t *map) {
timeleft += firstlftime; timeleft += firstlftime;
// now do effects based on time... // now do effects based on time...
while (timeleft >= TICK_INTERVAL) { while (timeleft >= TICK_INTERVAL) {
flag_t *f, *nextf; flag_t *f;
int i;
timeleft -= TICK_INTERVAL; timeleft -= TICK_INTERVAL;
@ -1476,24 +1480,22 @@ void timeeffectsworld(map_t *map) {
// now finish off water spread // now finish off water spread
noredraw = B_TRUE; noredraw = B_TRUE;
for (f = map->flags->first ; f ; f = nextf) {
nextf = f->next; getflags(map->flags, F_NEWWATERDEPTH, F_NONE);
if (f->id == F_NEWWATERDEPTH) { for (i = 0; i < nretflags; i++) {
cell_t *c; cell_t *c;
f = retflag[i];
c = getcellat(map, f->val[0], f->val[1]); c = getcellat(map, f->val[0], f->val[1]);
if (c) { if (c) {
if (f->val[2] > DP_NONE) { if (f->val[2] > DP_NONE) {
o = hasobwithflag(c->obpile, F_DEEPWATER); o = hasobwithflag(c->obpile, F_DEEPWATER);
if (!o) { if (!o) {
o = addob(c->obpile, "water"); o = addobfast(c->obpile, OT_WATERDEEP);
} }
} }
setwaterdepth(c, f->val[2]); setwaterdepth(c, f->val[2]);
} }
killflag(f); killflag(f);
continue;
}
} }
noredraw = B_FALSE; noredraw = B_FALSE;

343
objects.c
View File

@ -402,7 +402,11 @@ void addocnoun(objectclass_t *oc, char *text) {
// create a new object, stacking ok // create a new object, stacking ok
object_t *addob(obpile_t *where, char *name) { object_t *addob(obpile_t *where, char *name) {
return addobject(where, name, B_TRUE, B_TRUE); return addobject(where, name, B_TRUE, B_TRUE, OT_NONE);
}
object_t *addobfast(obpile_t *where, enum OBTYPE oid) {
return addobject(where, NULL, B_TRUE, B_TRUE, oid);
} }
// create a new object // create a new object
@ -411,17 +415,17 @@ object_t *addob(obpile_t *where, char *name) {
// object with o->amt set, instead of // object with o->amt set, instead of
// creating new obejct entries. // creating new obejct entries.
// NOTE: This function MUST return number of obs created via global "nretobs" // NOTE: This function MUST return number of obs created via global "nretobs"
object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes) { object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes, enum OBTYPE forceoid) {
objecttype_t *ot; objecttype_t *ot;
object_t *o = NULL; object_t *o = NULL;
char *p,*nsp,*p2; char *p,*nsp;
char numstringmin[BUFLEN]; char numstringmin[BUFLEN];
char numstringmax[BUFLEN]; char numstringmax[BUFLEN];
int howmany = 1; int howmany = 1;
int i; int i;
int db = B_FALSE; int db = B_FALSE;
flag_t *f; flag_t *f;
char *localname; char *localname = NULL;
int wantblessed = B_UNCURSED; int wantblessed = B_UNCURSED;
race_t *corpserace = NULL; race_t *corpserace = NULL;
int dorandombrand = B_FALSE; int dorandombrand = B_FALSE;
@ -429,6 +433,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
brand_t *br; brand_t *br;
obmod_t *om; obmod_t *om;
obmod_t *wantom[MAXOBMODS]; obmod_t *wantom[MAXOBMODS];
int bonus = 0;
int nom = 0; int nom = 0;
int n; int n;
int bookcontents = -1; int bookcontents = -1;
@ -450,8 +455,26 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
nadded = 0; nadded = 0;
nretobs = 0; nretobs = 0;
if (where->owner && hasflag(where->owner->flags, F_NOPACK)) {
if (db) dblog("error giving ob '%s' - owner isn't allowed to carry objects!", name);
nretobs = 0;
return NULL;
}
if (forceoid != OT_NONE) {
ot = findot(forceoid);
howmany = 1;
if (db) {
dblog("DB: called addobject() for forceoid %s, canstack = %d",ot->name, canstack);
}
} else {
char *p2;
localname = strdup(name); localname = strdup(name);
if (db) {
dblog("DB: called addobject() for %s, canstack = %d",localname, canstack);
}
// check for premods. eg. "flaming xxx" "frozen xxx" etc // check for premods. eg. "flaming xxx" "frozen xxx" etc
for (om = firstobmod ; om ; om = om->next) { for (om = firstobmod ; om ; om = om->next) {
if (db) dblog("DB: checking for '%s' in '%s'",om->prefix, localname); if (db) dblog("DB: checking for '%s' in '%s'",om->prefix, localname);
@ -464,25 +487,6 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
} }
} }
if (db) {
dblog("DB: called addobject() for %s, canstack = %d",localname, canstack);
}
if (where->owner && hasflag(where->owner->flags, F_NOPACK)) {
if (db) dblog("error giving ob '%s' - owner isn't allowed to carry objects!", name);
nretobs = 0;
return NULL;
}
// we CAN place objects in solid cells - for example,
// placing a fire on top of a wooden door.
/*
if (where->where) {
if (where->where->type != (celltype_t *)DUMMYCELLTYPE) {
assert(!where->where->type->solid);
}
}
*/
// parse name string // parse name string
nsp = numstringmin; nsp = numstringmin;
@ -504,6 +508,8 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
} else { } else {
strcpy(numstringmax,numstringmin); strcpy(numstringmax,numstringmin);
} }
// "p" should now point at the start of the actual
// object name.
// are we giving multiple objects? // are we giving multiple objects?
@ -525,6 +531,37 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
howmany = 1; howmany = 1;
} }
bonus = 0;
// handle for bonuses. eg. "+1"
p2 = strchr(p, '+');
if (p2) {
char *p3;
char numbuf[BUFLENSMALL];
p3 = numbuf;
p++;
while (isdigit(*p2)) {
*p3 = *p2;
p2++;
p3++;
}
*p3 = '\0';
bonus += atoi(numbuf);
}
// check for penalties. eg. "-1"
p2 = strchr(p, '-');
if (p2) {
char *p3;
char numbuf[BUFLENSMALL];
p3 = numbuf;
p2++;
while (isdigit(*p2)) {
*p3 = *p2;
p2++;
p3++;
}
*p3 = '\0';
bonus -= atoi(numbuf);
}
// handle prefixes. strip them off as we go. // handle prefixes. strip them off as we go.
donesomething = B_TRUE; donesomething = B_TRUE;
@ -757,6 +794,20 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
} }
if (db) dblog("DB: FOUND: ot->name = '%s'", ot->name ); if (db) dblog("DB: FOUND: ot->name = '%s'", ot->name );
// check for specific brands. eg. "xxx of pyromania"
// NOTE: this will override any random brands from "branded"
for (br = firstbrand ; br ; br = br->next) {
if (strstr(localname, br->suffix)) {
// does this brand apply to this objecttype?
if (brandappliesto(br, ot)) {
wantbrand = br;
break;
}
}
}
} // end if forceoid given
//////////////////////////////////// ////////////////////////////////////
// we now have the objecttype! // we now have the objecttype!
//////////////////////////////////// ////////////////////////////////////
@ -1082,9 +1133,6 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
// other special changes we need to make based on what was // other special changes we need to make based on what was
// asked for // asked for
if ((gamemode != GM_LOADING) && o) { if ((gamemode != GM_LOADING) && o) {
char *p2;
int bonus = 0;
// corpses - fill in details // corpses - fill in details
if (o->type->id == OT_CORPSE) { if (o->type->id == OT_CORPSE) {
flag_t *rf, *cf; flag_t *rf, *cf;
@ -1325,44 +1373,6 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
} }
} }
// check for bonuses. eg. "+1"
p2 = strchr(p, '+');
if (p2) {
char *p3;
char numbuf[BUFLENSMALL];
p3 = numbuf;
p2++;
while (isdigit(*p2)) {
*p3 = *p2;
p2++;
p3++;
}
*p3 = '\0';
bonus += atoi(numbuf);
}
// check for penalties. eg. "-1"
p2 = strchr(p, '-');
if (p2) {
char *p3;
char numbuf[BUFLENSMALL];
p3 = numbuf;
p2++;
while (isdigit(*p2)) {
*p3 = *p2;
p2++;
p3++;
}
*p3 = '\0';
bonus -= atoi(numbuf);
}
// if no bonus yet, get one based on 'wantgoodness' // if no bonus yet, get one based on 'wantgoodness'
if (!bonus) { if (!bonus) {
switch (wantgoodness) { switch (wantgoodness) {
@ -1387,12 +1397,10 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
} }
} }
if (bonus) { if (bonus && hasflag(o->flags, F_ENCHANTABLE)) {
if (hasflag(o->flags, F_ENCHANTABLE)) {
// for swords, armour etc // for swords, armour etc
addflag_real(o->flags, F_BONUS, bonus, NA, NA, NULL, PERMENANT, B_UNKNOWN, -1); addflag_real(o->flags, F_BONUS, bonus, NA, NA, NULL, PERMENANT, B_UNKNOWN, -1);
} }
}
// special rings which get randomized... // special rings which get randomized...
if (o->type->id == OT_RING_CON) { if (o->type->id == OT_RING_CON) {
@ -1431,24 +1439,13 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
} }
// now apply a random brand if we wanted one // now apply a random brand if we wanted one
if (dorandombrand) { if (!wantbrand && dorandombrand) {
wantbrand = getrandombrandfor(ot); wantbrand = getrandombrandfor(ot);
} }
} }
// check for specific brands. eg. "xxx of pyromania" // apply the brand
// NOTE: this will override any random brands from "branded"
for (br = firstbrand ; br ; br = br->next) {
if (strstr(name, br->suffix)) {
// does this brand apply to this objecttype?
if (brandappliesto(br, o->type)) {
wantbrand = br;
break;
}
}
}
if (wantbrand) { if (wantbrand) {
if (brandappliesto(wantbrand, o->type)) { if (brandappliesto(wantbrand, o->type)) {
copyflags(o->flags, wantbrand->flags, FROMBRAND); copyflags(o->flags, wantbrand->flags, FROMBRAND);
@ -1456,43 +1453,12 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
} }
} }
if (where->owner) { if (where->owner) {
// new owner gains "hold confer" flags conferred by this object // new owner gains "hold confer" flags conferred by this object
giveobflags(where->owner, o, F_HOLDCONFER); giveobflags(where->owner, o, F_HOLDCONFER);
} }
// special cases // special cases
/*
if (o->type->id == OT_VENDINGMACHINE) {
char buf[BUFLEN];
cell_t *loc;
loc = getoblocation(o);
// populate with objects
for (i = 0; i < 10; i++) {
objecttype_t *ot2;
strcpy(buf, "");
while (!strcmp(buf, "")) {
real_getrandomob(loc->map, buf, RO_NONE, NA, loc->map->depth + rnd(10,15), NA, getobsize(o)-1);
// replace "1 potion" with "a potion"
if (strstr(buf, "1 ") == buf) {
char temp[BUFLEN];
strcpy(temp, buf);
sprintf(buf, "a %s",temp + 2);
}
// make sure you can hold it
ot2 = findotn(buf);
if (!ot2 ||
hasflag(ot2->flags, F_NOPICKUP) ||
hasflag(ot2->flags, F_IMPASSABLE) ) {
strcpy(buf, "");
}
}
addflag(o->flags, F_CONTAINSOB, 'a' + i, NA, NA, buf);
}
}
*/
// ie. don't do these things when just creating objects // ie. don't do these things when just creating objects
// for validation purposes // for validation purposes
@ -1540,7 +1506,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
} // end foreach added object } // end foreach added object
// don't need the name anymore. // don't need the name anymore.
free(localname); if (localname) free(localname);
// populate retobs // populate retobs
for (i = 0; i < nadded; i++) { for (i = 0; i < nadded; i++) {
@ -3089,12 +3055,11 @@ int getobaccuracy(object_t *wep, lifeform_t *weilder) {
} }
int getobbonus(object_t *o) { int getobbonus(object_t *o) {
flag_t *f; int bonus = 0,i;
int bonus = 0;
for (f = o->flags->first ; f ; f = f->next) { getflags(o->flags, F_BONUS, F_NONE);
if (f->id == F_BONUS) { for (i = 0; i < nretflags; i++) {
bonus += f->val[0]; bonus += retflag[i]->val[0];
}
} }
return bonus; return bonus;
} }
@ -3153,7 +3118,7 @@ int getobspellpower(object_t *o, lifeform_t *lf) {
int getobvalue(object_t *o) { int getobvalue(object_t *o) {
float price; float price;
flag_t *f; flag_t *f;
int rarity = 0; int rarity = 0,i;
enum RARITY rr = RR_COMMON; enum RARITY rr = RR_COMMON;
if (o->type->id == OT_GOLD) { if (o->type->id == OT_GOLD) {
@ -3170,7 +3135,9 @@ int getobvalue(object_t *o) {
price += f->val[0]; price += f->val[0];
} }
for (f = o->flags->first ; f ; f = f->next) { getflags(o->flags, F_ARMOURRATING, F_BONUS, F_DAM, F_EDIBLE, F_LINKSPELL, F_MANUALOF, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
// damage // damage
if (f->id == F_DAM) { if (f->id == F_DAM) {
int min,max; int min,max;
@ -3226,7 +3193,7 @@ int getobvalue(object_t *o) {
} else if (o->type->obclass->id == OC_TECH) { } else if (o->type->obclass->id == OC_TECH) {
// tech value is based on tech level & rarity // tech value is based on tech level & rarity
float multiplier = 1; float multiplier = 1;
switch (gettechlevel(o)) { switch (gettechlevel(o->type->id)) {
case PR_INEPT: case PR_INEPT:
multiplier = 3.25; multiplier = 3.25;
break; break;
@ -3392,7 +3359,7 @@ object_t *getrandomammo(lifeform_t *lf) {
object_t *gun; object_t *gun;
object_t *o; object_t *o;
flag_t *f; flag_t *f;
int i;
gun = getfirearm(lf); gun = getfirearm(lf);
if (!gun) { if (!gun) {
return NULL; return NULL;
@ -3401,15 +3368,16 @@ object_t *getrandomammo(lifeform_t *lf) {
// possible ammo. Need to allow the player to // possible ammo. Need to allow the player to
// pick a specific ammo to use. USe a flag on wep // pick a specific ammo to use. USe a flag on wep
// to do this? Or a flag on the player? // to do this? Or a flag on the player?
for (f = gun->flags->first ; f ; f = f->next) {
if (f->id == F_AMMOOB) { getflags(gun->flags, F_AMMOOB, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
for (o = lf->pack->first ; o ; o = o->next) { for (o = lf->pack->first ; o ; o = o->next) {
if (o->type->id == f->val[0]) { if (o->type->id == f->val[0]) {
return o; return o;
} }
} }
} }
}
return NULL; return NULL;
} }
@ -4427,8 +4395,11 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
int ok = B_TRUE; int ok = B_TRUE;
// are all of the brand flags known? // are all of the brand flags known?
for (brf = br->flags->first ; brf ; brf = brf->next) { for (brf = br->flags->first ; brf ; brf = brf->next) {
for (f = o->flags->first; f ; f = f->next) { int i;
if ((f->id == brf->id) && (f->lifetime == FROMBRAND)) { getflags(o->flags, brf->id, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f->lifetime == FROMBRAND) {
if (f->known || showall) { if (f->known || showall) {
} else { } else {
ok = B_FALSE; ok = B_FALSE;
@ -4438,7 +4409,6 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
} }
} }
} }
if (ok) { if (ok) {
strcat(localbuf, br->suffix); strcat(localbuf, br->suffix);
} }
@ -5115,13 +5085,18 @@ float getshopprice(object_t *o, lifeform_t *buyer) {
return val; return val;
} }
enum SKILLLEVEL gettechlevel(object_t *o) { enum SKILLLEVEL gettechlevel(enum OBTYPE oid) {
flag_t *f; flag_t *f;
objecttype_t *ot;
enum SKILLLEVEL tlev = PR_INEPT; enum SKILLLEVEL tlev = PR_INEPT;
f = hasflag(o->flags, F_TECHLEVEL); ot = findot(oid);
if (ot) {
f = hasflag(ot->flags, F_TECHLEVEL);
if (f) { if (f) {
tlev = f->val[0]; tlev = f->val[0];
} }
}
return tlev; return tlev;
} }
@ -6577,6 +6552,12 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, 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_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
addot(OT_S_SMITEGOOD, "smite good", "Instantly deals 1-^bpower*2^n damage to good creatures.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 10, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
// l3 // l3
addot(OT_S_POISONBOLT, "poison bolt", "Fires a glob of venom at the target.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_POISONBOLT, "poison bolt", "Fires a glob of venom at the target.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL);
@ -6968,12 +6949,6 @@ void initobjects(void) {
addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL); addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL);
addot(OT_S_CUREPOISON, "cure poison", "Cures the target of all poisons.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
addot(OT_S_HAILSTORM, "hail storm", "Creates an intense storm of hail, causing damage to all within.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_HAILSTORM, "hail storm", "Creates an intense storm of hail, causing damage to all within.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_COLD, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_COLD, NA, NA, NULL);
@ -7058,7 +7033,7 @@ void initobjects(void) {
addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
/////////////////// ///////////////////
// life / clearic spells // life / cleric spells
/////////////////// ///////////////////
// l1 // l1
addot(OT_S_HEALINGMIN, "minor healing", "Restores 1-8 health to the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_HEALINGMIN, "minor healing", "Restores 1-8 health to the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
@ -7075,6 +7050,12 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL); addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
addot(OT_S_SMITEEVIL, "smite evil", "Instantly deals 1-^bpower*2^n damage to evil creatures.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 10, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
// l3 // l3
addot(OT_S_HEALING, "healing", "Restores 10-20 health to the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_HEALING, "healing", "Restores 10-20 health to the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL);
@ -7082,6 +7063,20 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
addot(OT_S_HOLYAURA, "holy aura", "Surrounds the target with a holy aura, causing their weapon to deal holy damage.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL);
addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL);
// l4
addot(OT_S_CUREPOISON, "cure poison", "Cures the target of all poisons.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
/////////////////// ///////////////////
// mental/psionic // mental/psionic
/////////////////// ///////////////////
@ -7165,6 +7160,7 @@ void initobjects(void) {
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
addot(OT_S_LIGHT, "light area", "Creates a temporary light source centred on the caster.\nAt Power III, you can control where the light appears.\nAt Power VIII, the light becomes permenant.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_LIGHT, "light area", "Creates a temporary light source centred on the caster.\nAt Power III, you can control where the light appears.\nAt Power VIII, the light becomes permenant.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL);
@ -7511,6 +7507,10 @@ void initobjects(void) {
addflag(lastot->flags, F_LINKSPELL, OT_S_POLYMORPH, NA, NA, NULL); addflag(lastot->flags, F_LINKSPELL, OT_S_POLYMORPH, NA, NA, NULL);
addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, NA, NA, NULL); addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
addot(OT_WAND_TURNUNDEAD, "wand of turn undead", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 72, RR_RARE, NULL);
addflag(lastot->flags, F_LINKSPELL, OT_S_TURNUNDEAD, NA, NA, NULL);
addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, NA, NA, NULL);
// tools - unique // tools - unique
addot(OT_ORBDUNGEONEXIT, "dungeon exit orb", "When operated, this magical key will disable the barriers around the dungeon exit stairs.", MT_STONE, 2, OC_TOOLS, SZ_SMALL); addot(OT_ORBDUNGEONEXIT, "dungeon exit orb", "When operated, this magical key will disable the barriers around the dungeon exit stairs.", MT_STONE, 2, OC_TOOLS, SZ_SMALL);
@ -10303,9 +10303,11 @@ void makeknown(enum OBTYPE otid) {
// //
// keep a list of objects and flags here, then give them afterwards. // keep a list of objects and flags here, then give them afterwards.
for (o = player->pack->first ; o ; o = o->next) { for (o = player->pack->first ; o ; o = o->next) {
if (o->type->id == otid) { if ((o->type->id == otid) && !isknown(o)) {
if (!isknown(o)) { getflags(o->flags, F_ACTIVATECONFER, F_EQUIPCONFER, F_HOLDCONFER, F_NONE);
for (f = o->flags->first ; f ; f = f->next) { for (i = 0; i < nretflags; i++) {
f = retflag[i];
if ((f->id == F_HOLDCONFER) && (f->val[2] == IFKNOWN)) { if ((f->id == F_HOLDCONFER) && (f->val[2] == IFKNOWN)) {
srcob[nobs] = o; srcob[nobs] = o;
fttogive[nobs] = F_HOLDCONFER; fttogive[nobs] = F_HOLDCONFER;
@ -10323,7 +10325,6 @@ void makeknown(enum OBTYPE otid) {
} }
} }
} }
}
for (k = knowledge; k ; k = k->next) { for (k = knowledge; k ; k = k->next) {
if (k->id == otid) { if (k->id == otid) {
@ -11072,7 +11073,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
return B_TRUE; return B_TRUE;
} }
if (gettechlevel(o) > getskill(lf, SK_TECHUSAGE)) { if (gettechlevel(o->type->id) > getskill(lf, SK_TECHUSAGE)) {
if (isplayer(lf)) { if (isplayer(lf)) {
msg("This technology is beyond your understanding."); msg("This technology is beyond your understanding.");
} }
@ -11082,7 +11083,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
// has known trap? // has known trap?
if (isplayer(lf)) { if (isplayer(lf)) {
if (hasflagval(o->flags, F_TRAPPED, NA, NA, B_TRUE, NULL)) { if (hasflagval(o->flags, F_TRAPPED, NA, NA, B_TRUE, NULL)) {
if (getattrbracket(getattr(lf, A_IQ), A_IQ, NULL) >= AT_AVERAGE) { if (getattrbracket(getattr(lf, A_WIS), A_WIS, NULL) >= AT_AVERAGE) {
char ch; char ch;
sprintf(buf,"Really operate %s?", obname); sprintf(buf,"Really operate %s?", obname);
ch = askchar(buf,"yn","n", B_TRUE); ch = askchar(buf,"yn","n", B_TRUE);
@ -11999,15 +12000,25 @@ int pour(lifeform_t *lf, object_t *o) {
blessob(dst); blessob(dst);
// we now know that this is holy water // we now know that this is holy water
if (!isknown(o)) makeknown(o->type->id); if (!isknown(o)) makeknown(o->type->id);
// god effects
if (isplayer(lf)) {
pleasegodmaybe(R_GODPURITY, 3);
angergodmaybe(R_GODDEATH, 15);
}
} else if ((o->type->id == OT_POT_WATER) && (o->blessed == B_CURSED)) { // unholy water } else if ((o->type->id == OT_POT_WATER) && (o->blessed == B_CURSED)) { // unholy water
if (isplayer(lf)) { if (isplayer(lf)) {
msg("You pour %s onto %s.", obname,dstname); msg("You pour %s onto %s.", obname,dstname);
} }
o->blessknown = B_TRUE; o->blessknown = B_TRUE;
// bless whatever we poured onto // curse whatever we poured onto
curseob(dst); curseob(dst);
// we now know that this is holy water // we now know that this is holy water
if (!isknown(o)) makeknown(o->type->id); if (!isknown(o)) makeknown(o->type->id);
// god effects
if (isplayer(lf)) {
pleasegodmaybe(R_GODDEATH, 3);
angergodmaybe(R_GODPURITY, 25);
}
} else if (o->type->id == OT_POT_INVULN) { } else if (o->type->id == OT_POT_INVULN) {
flag_t *f; flag_t *f;
f = hasflag(dst->flags, F_DAMAGABLE); f = hasflag(dst->flags, F_DAMAGABLE);
@ -12770,9 +12781,11 @@ int readsomething(lifeform_t *lf, object_t *o) {
// only id if it does something // only id if it does something
willid = B_FALSE; willid = B_FALSE;
} }
case OT_SCR_ENCHANT: // only id if it does something case OT_SCR_ENCHANT:
case OT_SCR_CREATEMONSTER: // only id if it does something case OT_SCR_CREATEMONSTER:
case OT_SCR_REMOVECURSE: // only id if it does something case OT_SCR_REMOVECURSE:
case OT_SCR_DETECTAURA:
// only id if it does something
willid = B_FALSE; willid = B_FALSE;
break; break;
default: default:
@ -13128,7 +13141,6 @@ int readsomething(lifeform_t *lf, object_t *o) {
} }
object_t *relinkob(object_t *src, obpile_t *dst) { object_t *relinkob(object_t *src, obpile_t *dst) {
flag_t *f,*nextf;
if (!obfits(src, dst)) return NULL; if (!obfits(src, dst)) return NULL;
if (src->pile->owner) { if (src->pile->owner) {
@ -13137,12 +13149,7 @@ object_t *relinkob(object_t *src, obpile_t *dst) {
} }
// unweild // unweild
for (f = src->flags->first ; f ; f = nextf) { killflagsofid(src->flags, F_EQUIPPED);
nextf = f->next;
if (f->id == F_EQUIPPED) {
killflag(f);
}
}
// adjust letter... // adjust letter...
// gold should always have letter '$' // gold should always have letter '$'
@ -13647,7 +13654,7 @@ object_t *splitob(object_t *o) {
// doesn't matter if it goes down to zero, as we will put it back up soon. // doesn't matter if it goes down to zero, as we will put it back up soon.
o->amt--; o->amt--;
// give new object // give new object
newob = addobject(o->pile, o->type->name, B_NOSTACK, B_FALSE); newob = addobject(o->pile, NULL, B_NOSTACK, B_FALSE, o->type->id);
// restore count // restore count
o->amt++; o->amt++;
if (newob) { if (newob) {
@ -13964,16 +13971,28 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
int acc; int acc;
int youhit = B_FALSE; int youhit = B_FALSE;
int missiledam = 0; int missiledam = 0;
object_t *newob; object_t *newob = NULL;
cell_t *newloc; cell_t *newloc;
int db = B_TRUE; int db = B_TRUE;
int willcatch = B_FALSE; int willcatch = B_FALSE;
int announcedmiss = B_FALSE; int announcedmiss = B_FALSE;
int outofammo = B_FALSE; int outofammo = B_FALSE;
float multiplier; float multiplier;
obpile_t *op = NULL;
reason = E_OK; reason = E_OK;
// giving away money
if (isplayer(thrower) && (o->type->id == OT_GOLD)) {
flag_t *f;
f = lfhasflag(thrower, F_GAVEMONEY);
if (f) {
f->val[0] += o->amt;
} else {
addflag(thrower->flags, F_GAVEMONEY, o->amt, NA, NA, NULL);
}
}
// you can't throw with as much force while swimming. // you can't throw with as much force while swimming.
if (isswimming(thrower) && !firearm) { if (isswimming(thrower) && !firearm) {
speed /= 2; speed /= 2;
@ -14378,6 +14397,15 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
int reduceamt = 0; int reduceamt = 0;
int throwdam; int throwdam;
op = addobpile(NOOWNER, NOLOC, NULL);
// split off new object into a fake obpile
// so we don't modify the original stack with
// things like poison rubbing off.
o = real_moveob(o, op, amt, B_FALSE);
o->birthtime = -1;
throwdam = getthrowdam(o); throwdam = getthrowdam(o);
dam = (int)((float)throwdam * multiplier); dam = (int)((float)throwdam * multiplier);
if (db) dblog("fireat(): dam = throwdam(%d) * speed(%d)/2 = %d",throwdam, speed, dam); if (db) dblog("fireat(): dam = throwdam(%d) * speed(%d)/2 = %d",throwdam, speed, dam);
@ -14461,6 +14489,9 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
// fake its birth time so that it can be damaged // fake its birth time so that it can be damaged
newob->birthtime = -1; newob->birthtime = -1;
// now we can get rid of the fake obpile, if we used it
if (op) killobpile(op);
// gun out of ammo? // gun out of ammo?
if (firearm && !countobs(firearm->contents, B_FALSE)) { if (firearm && !countobs(firearm->contents, B_FALSE)) {
outofammo = B_TRUE; outofammo = B_TRUE;

View File

@ -10,7 +10,8 @@ material_t *addmaterial(enum MATERIAL id, char *name, float weightrating);
objectclass_t *addoc(enum OBCLASS id, char *name, char *desc, char glyph, int glyphcolour); objectclass_t *addoc(enum OBCLASS id, char *name, char *desc, char glyph, int glyphcolour);
void addocnoun(objectclass_t *oc, char *text); void addocnoun(objectclass_t *oc, char *text);
object_t *addob(obpile_t *where, char *name); object_t *addob(obpile_t *where, char *name);
object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes); object_t *addobfast(obpile_t *where, enum OBTYPE oid);
object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes, enum OBTYPE forceoid);
int addobburst(cell_t *where, int range, int dirtype, char *name, lifeform_t *fromlf, enum LOFTYPE needlof); int addobburst(cell_t *where, int range, int dirtype, char *name, lifeform_t *fromlf, enum LOFTYPE needlof);
obmod_t *addobmod(enum OBMOD id, char *prefix); obmod_t *addobmod(enum OBMOD id, char *prefix);
obpile_t *addobpile(lifeform_t *owner, cell_t *where, object_t *parentob); obpile_t *addobpile(lifeform_t *owner, cell_t *where, object_t *parentob);
@ -121,7 +122,7 @@ char *getschoolname(enum SPELLSCHOOL sch);
char *getschoolnameshort(enum SPELLSCHOOL sch); char *getschoolnameshort(enum SPELLSCHOOL sch);
int getshatterdam(object_t *o); int getshatterdam(object_t *o);
float getshopprice(object_t *o, lifeform_t *buyer); float getshopprice(object_t *o, lifeform_t *buyer);
enum SKILLLEVEL gettechlevel(object_t *o); enum SKILLLEVEL gettechlevel(enum OBTYPE oid);
int getthrowdam(object_t *o); int getthrowdam(object_t *o);
char *gettopobname(cell_t *c, char *retbuf); char *gettopobname(cell_t *c, char *retbuf);
enum BODYPART getweildloc(object_t *o, enum BODYPART *otherloc, int *twohanded); enum BODYPART getweildloc(object_t *o, enum BODYPART *otherloc, int *twohanded);

2
save.c
View File

@ -526,7 +526,7 @@ int loadob(FILE *f, obpile_t *op, long *id) {
return B_TRUE; return B_TRUE;
} }
// create the object // create the object
o = addobject(op, ot->name, B_NOSTACK, B_FALSE); // no stacking! o = addobject(op, NULL, B_NOSTACK, B_FALSE, ot->id); // no stacking!
// overwrite ob parameters // overwrite ob parameters
o->id = obid; o->id = obid;

158
spell.c
View File

@ -240,9 +240,9 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
removeob(water,ALL); removeob(water,ALL);
// give food // give food
if (getskill(user, SK_COOKING >= PR_EXPERT)) { if (getskill(user, SK_COOKING >= PR_EXPERT)) {
o = addob(user->pack, "jerky"); o = addobfast(user->pack, OT_JERKY);
} else { } else {
o = addob(user->pack, "stew"); o = addobfast(user->pack, OT_STEW);
} }
if (o) { if (o) {
@ -1547,6 +1547,8 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
if (isplayer(user)) { if (isplayer(user)) {
msg("There doesn't seem to be anything here which you could steal."); msg("There doesn't seem to be anything here which you could steal.");
} }
} else {
pleasegodmaybe(R_GODTHIEVES, 5);
} }
} else { } else {
lifeform_t *shk; lifeform_t *shk;
@ -1908,19 +1910,6 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// destroy objects right away // destroy objects right away
removedeadobs(caster->pack); removedeadobs(caster->pack);
// handle cell under the caster
for (o = caster->cell->obpile->first ; o ; o = o->next) {
// destroy metal items on the ground
if (ismetal(o->material->id)) {
takedamage(o, 9999, DT_DIRECT);
if (hasflag(o->flags, F_DEAD)) {
totalmass += getobweight(o);
}
}
}
// destroy objects right away
removedeadobs(caster->cell->obpile);
for (i = 0; i < caster->nlos; i++) { for (i = 0; i < caster->nlos; i++) {
targcell = caster->los[i]; targcell = caster->los[i];
for (o = targcell->obpile->first ; o ; o = o->next) { for (o = targcell->obpile->first ; o ; o = o->next) {
@ -2034,13 +2023,14 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// animate corpses within lof of caster // animate corpses within lof of caster
for (i = 0; i < target->nlos; i++) { for (i = 0; i < target->nlos; i++) {
targcell = target->los[i]; targcell = target->los[i];
if (targcell != target->cell) {
for (o = targcell->obpile->first ; o ; o = nexto) { for (o = targcell->obpile->first ; o ; o = nexto) {
nexto = o->next; nexto = o->next;
if (o->type->id == OT_CORPSE) { if (o->type->id == OT_CORPSE) {
lifeform_t *newlf; lifeform_t *newlf;
newlf = makezombie(o); newlf = makezombie(o);
if (newlf) { if (newlf) {
if (isplayer(caster) && skillcheck(caster, A_IQ, 20, power)) { if (isplayer(target) && skillcheck(target, A_IQ, 20, power)) {
makefriendly(newlf, PERMENANT); makefriendly(newlf, PERMENANT);
} }
donesomething = B_TRUE; donesomething = B_TRUE;
@ -2048,6 +2038,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
} }
} }
}
if (donesomething) { if (donesomething) {
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
@ -2437,7 +2428,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
powerleft = power; powerleft = power;
for (i = 0; i < caster->nlos; i++) { for (i = 0; i < caster->nlos; i++) {
c = caster->los[i]; c = caster->los[i];
if (c->lf && (c->lf->race->raceclass->id == RC_ANIMAL) && (gethitdice(c->lf) <= powerleft)) { if (c->lf && (c->lf != caster) && (c->lf->race->raceclass->id == RC_ANIMAL) && (gethitdice(c->lf) <= powerleft)) {
if (lfhasflag(c->lf, F_HOSTILE)) { if (lfhasflag(c->lf, F_HOSTILE)) {
powerleft -= gethitdice(c->lf); powerleft -= gethitdice(c->lf);
makepeaceful(c->lf); makepeaceful(c->lf);
@ -4173,9 +4164,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if ((spellid == OT_S_HEALINGMIN) && donesomething) { if ((spellid == OT_S_HEALINGMIN) && donesomething) {
// minor healing will stop here // minor healing will stop here
return B_FALSE; } else {
}
if (target->hp < target->maxhp) { if (target->hp < target->maxhp) {
int min,max; int min,max;
switch (spellid) { switch (spellid) {
@ -4228,15 +4217,29 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
donesomething = B_TRUE; donesomething = B_TRUE;
} }
}
if (isplayer(target)) { if (isplayer(target)) {
if (!donesomething) { if (!donesomething) {
nothinghappens(); nothinghappens();
} }
} }
if (donesomething && isplayer(caster) && !frompot) { if (donesomething && isplayer(caster)) {
if (!frompot) {
pleasegodmaybe(R_GODMERCY, 3); pleasegodmaybe(R_GODMERCY, 3);
} }
angergodmaybe(R_GODDEATH, 20);
}
// hostile monsters might calm down
if (!frompot && donesomething && isplayer(caster) && !isplayer(target) && (getallegiance(target) == AL_HOSTILE)) {
enum ATTRBRACKET iqb;
iqb = getattrbracket(getattr(target, A_IQ), A_IQ, NULL);
if ((iqb >= IQ_ANIMAL) && cansee(target, caster)) {
if (skillcheckvs(caster, SC_MORALE, 3, target, SC_MORALE, 0)) {
makepeaceful(target);
}
}
}
} else if (spellid == OT_S_HOLDPORTAL) { } else if (spellid == OT_S_HOLDPORTAL) {
object_t *o; object_t *o;
if (!validatespellcell(caster, &targcell,TT_DOOR, spellid, power, frompot)) return B_TRUE; if (!validatespellcell(caster, &targcell,TT_DOOR, spellid, power, frompot)) return B_TRUE;
@ -4279,6 +4282,14 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
} }
} }
} else if (spellid == OT_S_HOLYAURA) {
flag_t *f;
if (!target) target = caster;
f = addtempflag(target->flags, F_HOLYAURA, B_TRUE, NA, NA, NULL, FROMSPELL);
f->obfrom = spellid;
f = addtempflag(target->flags, F_PRODUCESLIGHT, 2, NA, NA, NULL, FROMSPELL);
f->obfrom = spellid;
} else if (spellid == OT_S_ICEEDGE) { } else if (spellid == OT_S_ICEEDGE) {
object_t *wep; object_t *wep;
enum DAMTYPE dt; enum DAMTYPE dt;
@ -4343,7 +4354,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// knock lfs away // knock lfs away
if (targcell->lf) { if (targcell->lf) {
knockback(targcell->lf, getdiraway(targcell, targcell, NULL, B_FALSE, DT_COMPASS), 1, NULL, 25+power); knockback(targcell->lf, getdiraway(targcell, targcell, NULL, B_FALSE, DT_COMPASS, B_FALSE), 1, NULL, 25+power);
donesomething = B_TRUE; donesomething = B_TRUE;
} }
@ -4554,19 +4565,6 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// destroy objects right away // destroy objects right away
removedeadobs(caster->pack); removedeadobs(caster->pack);
// handle cell under the caster
for (o = caster->cell->obpile->first ; o ; o = o->next) {
// destroy metal items on the ground
if (ismetal(o->material->id)) {
takedamage(o, 9999, DT_DIRECT);
if (hasflag(o->flags, F_DEAD)) {
totalmass += getobweight(o);
}
}
}
// destroy objects right away
removedeadobs(caster->cell->obpile);
for (i = 0; i < caster->nlos; i++) { for (i = 0; i < caster->nlos; i++) {
targcell = caster->los[i]; targcell = caster->los[i];
for (o = targcell->obpile->first ; o ; o = o->next) { for (o = targcell->obpile->first ; o ; o = o->next) {
@ -5258,10 +5256,13 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
} }
if (!donesomething) { if (donesomething) {
if (isplayer(caster)) pleasegodmaybe(R_GODTHIEVES, 5);
} else {
fizzle(caster); fizzle(caster);
} }
} }
} else if (spellid == OT_S_LEVITATION) { } else if (spellid == OT_S_LEVITATION) {
flag_t *f; flag_t *f;
@ -5376,11 +5377,13 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
int i; int i;
for (i = 0; i < caster->nlos; i++) { for (i = 0; i < caster->nlos; i++) {
if (caster->los[i] != caster->cell) {
target = caster->los[i]->lf; target = caster->los[i]->lf;
if (target && areenemies(caster, target)) { if (target && areenemies(caster, target)) {
poss[nposs++] = target; poss[nposs++] = target;
} }
} }
}
if (nposs) { if (nposs) {
int nhits; int nhits;
@ -6259,6 +6262,29 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (isplayer(target) || haslos(player, target->cell)) { if (isplayer(target) || haslos(player, target->cell)) {
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
} }
} else if ((spellid == OT_S_SMITEEVIL) || (spellid == OT_S_SMITEGOOD)) {
enum ALIGNMENT wantalign;
if (spellid == OT_S_SMITEEVIL) {
wantalign = AL_EVIL;
} else {
wantalign = AL_GOOD;
}
if (!validatespellcell(caster, &targcell, TT_NONE, spellid, power, frompot)) return B_TRUE;
target = targcell->lf;
if (!target || (getalignment(target) != wantalign)) {
fizzle(caster);
return B_TRUE;
}
if (isplayer(target)) {
msg("The power of %s smites you!", (spellid == OT_S_SMITEEVIL) ? "good" : "evil");
} else if (cansee(player, target)) {
char lfname[BUFLEN];
getlfname(target, lfname);
msg("The power of %s smites %s!", (spellid == OT_S_SMITEEVIL) ? "good" : "evil", lfname);
}
// use direct damage rather than holy, because otherwise it might be increased
// due to vulnerabilities
losehp(target, rnd(1,power*2), DT_DIRECT, caster, "a smiting");
} else if (spellid == OT_S_SOFTENEARTH) { } else if (spellid == OT_S_SOFTENEARTH) {
int seen = B_FALSE; int seen = B_FALSE;
int ndone = 0; int ndone = 0;
@ -6433,8 +6459,10 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
poss[0] = caster->cell; poss[0] = caster->cell;
nposs = 1; nposs = 1;
for (i = 0; i < caster->nlos; i++) { for (i = 0; i < caster->nlos; i++) {
if (caster->los[i] != caster->cell) {
poss[nposs++] = caster->los[i]; poss[nposs++] = caster->los[i];
} }
}
// for each cell we can see... // for each cell we can see...
for (i = 0; i < caster->nlos; i++) { for (i = 0; i < caster->nlos; i++) {
c = poss[i]; c = poss[i];
@ -6875,11 +6903,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
} else if (spellid == OT_S_THORNS) { } else if (spellid == OT_S_THORNS) {
flag_t *f; flag_t *f;
// always targetted at caster if (!target) target = caster;
targcell = caster->cell;
target = caster;
f = addtempflag(caster->flags, F_RETALIATE, 1, 4, DT_PIERCE, "sharp thorns", FROMSPELL); f = addtempflag(target->flags, F_RETALIATE, 1, 4, DT_PIERCE, "sharp thorns", FROMSPELL);
f->obfrom = spellid; f->obfrom = spellid;
} else if (spellid == OT_S_TRUESTRIKE) { } else if (spellid == OT_S_TRUESTRIKE) {
if (!validatespellcell(caster, &targcell, TT_PLAYER, spellid, power, frompot)) return B_TRUE; if (!validatespellcell(caster, &targcell, TT_PLAYER, spellid, power, frompot)) return B_TRUE;
@ -6891,11 +6917,15 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
addflag(caster->flags, F_TRUESTRIKE, power, NA, NA, NULL); addflag(caster->flags, F_TRUESTRIKE, power, NA, NA, NULL);
} else if (spellid == OT_S_TURNUNDEAD) { } else if (spellid == OT_S_TURNUNDEAD) {
int i; int i;
// works on all undead in sight lifeform_t *lf;
if (!target) {
target = caster;
}
// works on all undead in _target's_ sight
for (i = 0; i < caster->nlos; i++) { for (i = 0; i < caster->nlos; i++) {
targcell = caster->los[i]; targcell = caster->los[i];
target = targcell->lf; lf = targcell->lf;
if (target && isundead(target)) { if (lf && (lf != caster) && isundead(lf)) {
int howlong = 10; int howlong = 10;
int worked = B_TRUE; int worked = B_TRUE;
// TODO: does it work? depends on caster level & intelligence & power // TODO: does it work? depends on caster level & intelligence & power
@ -6904,7 +6934,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
howlong = rnd(10,20); howlong = rnd(10,20);
if (worked) { if (worked) {
// don't use scare() since it will fail due to them being undead. // don't use scare() since it will fail due to them being undead.
addtempflag(target->flags, F_FLEEFROM, caster->id, NA, NA, NULL,howlong); addtempflag(lf->flags, F_FLEEFROM, target->id, NA, NA, NULL,howlong);
} }
} }
} }
@ -6952,7 +6982,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
wantsize = SZ_ANY; wantsize = SZ_ANY;
break; break;
} }
ngot = summonlfs(caster, caster->cell, wantrc, wantsize, nwant, lifetime); ngot = summonlfs(caster, caster->cell, wantrc, wantsize, AL_NONE, nwant, lifetime);
if (!ngot) { if (!ngot) {
fizzle(caster); fizzle(caster);
return B_TRUE; return B_TRUE;
@ -7059,7 +7089,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
// knock lfs away // knock lfs away
if (c->lf) { if (c->lf) {
knockback(c->lf, getdiraway(c, c, NULL, B_FALSE, DT_COMPASS), 1, NULL, 30+power); knockback(c->lf, getdiraway(c, c, NULL, B_FALSE, DT_COMPASS, B_FALSE), 1, NULL, 30+power);
donesomething = B_TRUE; donesomething = B_TRUE;
} }
} }
@ -7075,7 +7105,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
// knock lfs away // knock lfs away
if (c->lf) { if (c->lf) {
knockback(c->lf, getdiraway(c, c, NULL, B_FALSE, DT_COMPASS), 1, NULL, 30+power); knockback(c->lf, getdiraway(c, c, NULL, B_FALSE, DT_COMPASS, B_FALSE), 1, NULL, 30+power);
donesomething = B_TRUE; donesomething = B_TRUE;
} }
} }
@ -7091,7 +7121,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
// knock lfs away // knock lfs away
if (c->lf) { if (c->lf) {
knockback(c->lf, getdiraway(c, c, NULL, B_FALSE, DT_COMPASS), 1, NULL, 30+power); knockback(c->lf, getdiraway(c, c, NULL, B_FALSE, DT_COMPASS, B_FALSE), 1, NULL, 30+power);
donesomething = B_TRUE; donesomething = B_TRUE;
} }
} }
@ -7107,7 +7137,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
// knock lfs away // knock lfs away
if (c->lf) { if (c->lf) {
knockback(c->lf, getdiraway(c, c, NULL, B_FALSE, DT_COMPASS), 1, NULL, 30+power); knockback(c->lf, getdiraway(c, c, NULL, B_FALSE, DT_COMPASS, B_FALSE), 1, NULL, 30+power);
donesomething = B_TRUE; donesomething = B_TRUE;
} }
} }
@ -8360,7 +8390,7 @@ void stopspell(lifeform_t *caster, enum OBTYPE spellid) {
// returns # created // returns # created
int summonlfs(lifeform_t *caster, cell_t *where, enum RACECLASS wantrc, enum LFSIZE wantsize, int howmany, int lifetime) { int summonlfs(lifeform_t *caster, cell_t *where, enum RACECLASS wantrc, enum LFSIZE wantsize, enum ALIGNMENT wantalign, int howmany, int lifetime) {
lifeform_t *newlf; lifeform_t *newlf;
race_t *r = NULL; race_t *r = NULL;
enum RACE poss[MAXCANDIDATES]; enum RACE poss[MAXCANDIDATES];
@ -8371,16 +8401,24 @@ int summonlfs(lifeform_t *caster, cell_t *where, enum RACECLASS wantrc, enum LFS
// determine possible types of race // determine possible types of race
for (r = firstrace ; r; r = r->next) { for (r = firstrace ; r; r = r->next) {
int ok = B_FALSE; int ok = B_TRUE;
if ((wantrc == RC_ANY) || (r->raceclass->id == wantrc)) { if ((wantrc != RC_ANY) && (r->raceclass->id != wantrc)) {
flag_t *f; ok = B_FALSE;
if (wantsize == SZ_ANY) {
ok = B_TRUE;
} else {
f = hasflag(r->flags, F_SIZE);
if (f && (f->val[0] == wantsize)) {
ok = B_TRUE;
} }
if (wantsize != SZ_ANY) {
flag_t *f;
f = hasflag(r->flags, F_SIZE);
if (f && (f->val[0] != wantsize)) {
ok = B_FALSE;
}
}
if (wantalign != AL_NONE) {
flag_t *f;
f = hasflag(r->flags, F_ALIGNMENT);
if (f && (f->val[0] != wantalign)) {
ok = B_FALSE;
} }
} }
if (ok) { if (ok) {
@ -8538,7 +8576,7 @@ cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, e
if (!frompot && where && where->lf && haslos(caster, where) && isplayer(caster) && areallies(caster, where->lf)) { if (!frompot && where && where->lf && haslos(caster, where) && isplayer(caster) && areallies(caster, where->lf)) {
// warn before targetting yourself! // warn before targetting yourself!
if (getattrbracket(getattr(caster, A_IQ), A_IQ, NULL) >= AT_AVERAGE) { if (getattrbracket(getattr(caster, A_WIS), A_WIS, NULL) >= AT_AVERAGE) {
objecttype_t *sp; objecttype_t *sp;
sp = findot(spellid); sp = findot(spellid);
if (sp) { if (sp) {

View File

@ -26,7 +26,7 @@ void spellcloud(cell_t *srcloc, int radius, char ch, enum COLOUR col, enum OBTYP
void stopspell(lifeform_t *caster, enum OBTYPE spellid); void stopspell(lifeform_t *caster, enum OBTYPE spellid);
void stopallspells(lifeform_t *lf); void stopallspells(lifeform_t *lf);
void stopallspellsexcept(lifeform_t *lf, ...); void stopallspellsexcept(lifeform_t *lf, ...);
int summonlfs(lifeform_t *caster, cell_t *where, enum RACECLASS wantrc, enum LFSIZE wantsize, int howmany, int lifetime); int summonlfs(lifeform_t *caster, cell_t *where, enum RACECLASS wantrc, enum LFSIZE wantsize, enum ALIGNMENT wantalign, int howmany, int lifetime);
lifeform_t *validateabillf(lifeform_t *user, enum OBTYPE aid, lifeform_t **target); lifeform_t *validateabillf(lifeform_t *user, enum OBTYPE aid, lifeform_t **target);
cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, enum OBTYPE spellid, int power, int frompot); cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, enum OBTYPE spellid, int power, int frompot);
//lifeform_t *validatespelllf(lifeform_t *caster, lifeform_t **lf); //lifeform_t *validatespelllf(lifeform_t *caster, lifeform_t **lf);