- [+] vampire gas cloud not working for player

- [+] monsters should only weild weapons if they are better than their
      inbuilt attcaks!
- [+] show dtected obkects in bold green
- [+] bug: can blink into impassable objects
- [+] infinite loop in ai turn for porcupine.
    - [+] movetowards()
* [+] vampires
- [+] vampire changes back to its original form.  CRASH.
This commit is contained in:
Rob Pearce 2011-08-05 21:34:35 +00:00
parent 81c7f37eff
commit 00f9d4e0bf
15 changed files with 427 additions and 159 deletions

129
ai.c
View File

@ -711,9 +711,16 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) {
} // end if attackok } // end if attackok
// if we could see our traget, but everything we tried failed (spells, moving and ranged attack), // if we could see our traget, but everything we tried failed (spells, moving and ranged attack),
// just rest. // either rest or move randomly.
if (movefailed) { if (movefailed) {
rest(lf, B_TRUE); makenoise(lf, N_FRUSTRATED);
if (onein(2)) {
rest(lf, B_TRUE);
} else {
if (dorandommove(lf, B_NOBADMOVES, B_FALSE)) {
rest(lf, B_TRUE);
}
}
return B_FALSE; return B_FALSE;
} }
} else { } else {
@ -1494,74 +1501,78 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
f = hasflag(ot->flags, purpose); f = hasflag(ot->flags, purpose);
if (f) { if (f) {
int range; if ((f->val[1] == NA) || pctchance(f->val[1])) {
switch (f->val[0]) { int range;
case ST_VICTIM: switch (f->val[0]) {
range = getspellrange(spellid, getspellpower(lf, spellid)); case ST_VICTIM:
if ((range == UNLIMITED) || (getcelldist(lf->cell, victim->cell) <= range)) { range = getspellrange(spellid, getspellpower(lf, spellid));
if ((range == UNLIMITED) || (getcelldist(lf->cell, victim->cell) <= range)) {
if (db) {
dblog(".oO { spell possibility: %s }", ot ? ot->name : "?unkownspell?");
}
ok = B_TRUE;
}
break;
case ST_SELF:
case ST_ANYWHERE:
if (db) { if (db) {
dblog(".oO { spell possibility: %s }", ot ? ot->name : "?unkownspell?"); dblog(".oO { spell possibility: %s }", ot ? ot->name : "?unkownspell?");
} }
ok = B_TRUE; ok = B_TRUE;
} break;
break; case ST_ADJVICTIM:
case ST_SELF: if (getcelldist(lf->cell,victim->cell) == 1) {
case ST_ANYWHERE: if (ot->id == OT_A_GRAB) {
if (db) { if (lfhasflag(lf, F_GRABBING) || lfhasflag(lf, F_GRABBEDBY) ||
dblog(".oO { spell possibility: %s }", ot ? ot->name : "?unkownspell?"); lfhasflag(victim, F_GRABBING) || lfhasflag(victim, F_GRABBEDBY)) {
} } else {
ok = B_TRUE; ok = B_TRUE;
break; }
case ST_ADJVICTIM: } else if (ot->id == OT_A_CRUSH) {
if (getcelldist(lf->cell,victim->cell) == 1) { // can only crush if you first grab something
if (ot->id == OT_A_GRAB) { if (lfhasflag(lf, F_GRABBING)) {
if (lfhasflag(lf, F_GRABBING) || lfhasflag(lf, F_GRABBEDBY) || ok = B_TRUE;
lfhasflag(victim, F_GRABBING) || lfhasflag(victim, F_GRABBEDBY)) { }
} else if (ot->id == OT_A_SUCKBLOOD) {
// must attach first
if (lfhasflag(lf, F_ATTACHEDTO)) {
ok = B_TRUE;
}
} else { } else {
ok = B_TRUE; ok = B_TRUE;
} }
} else if (ot->id == OT_A_CRUSH) { }
// can only crush if you first grab something break;
if (lfhasflag(lf, F_GRABBING)) { case ST_ADJSELF:
ok = B_TRUE; if (getcelldist(lf->cell,victim->cell) == 1) {
}
} else if (ot->id == OT_A_SUCKBLOOD) {
// must attach first
if (lfhasflag(lf, F_ATTACHEDTO)) {
ok = B_TRUE;
}
} else {
ok = B_TRUE; ok = B_TRUE;
} }
} break;
break; case ST_SPECIAL:
case ST_ADJSELF: specialcase = B_TRUE;
if (getcelldist(lf->cell,victim->cell) == 1) { break;
ok = B_TRUE; }
}
break;
case ST_SPECIAL:
specialcase = B_TRUE;
break;
}
// now check for line of sight / fire // now check for line of sight / fire
switch (f->val[0]) { switch (f->val[0]) {
case ST_VICTIM: case ST_VICTIM:
case ST_ADJVICTIM: case ST_ADJVICTIM:
if (needlos && (!victim || !cansee(lf, victim)) ) { if (needlos && (!victim || !cansee(lf, victim)) ) {
if (db) dblog(".oO { cant cast %s - no LOS to victim }", ot ? ot->name : "?unkownspell?"); if (db) dblog(".oO { cant cast %s - no LOS to victim }", ot ? ot->name : "?unkownspell?");
return B_FALSE; return B_FALSE;
} }
if (needlof && !haslof(lf->cell, victim->cell, needlof, NULL) ) { if (needlof && !haslof(lf->cell, victim->cell, needlof, NULL) ) {
if (db) dblog(".oO { cant cast %s - no LOF to victim }", ot ? ot->name : "?unkownspell?"); if (db) dblog(".oO { cant cast %s - no LOF to victim }", ot ? ot->name : "?unkownspell?");
return B_FALSE; return B_FALSE;
} }
break; break;
default: default:
break; break;
}
} else { // failed pctchance for spell
if (db) dblog(".oO { failed pct check for casting %s }", ot ? ot->name : "?unkownspell?");
return B_FALSE;
} }
} else { } else {
// invalid spell for this purpose // invalid spell for this purpose
if (db) dblog(".oO { cant cast %s - not valid for given purpose }", ot ? ot->name : "?unkownspell?"); if (db) dblog(".oO { cant cast %s - not valid for given purpose }", ot ? ot->name : "?unkownspell?");

View File

@ -255,7 +255,6 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
} }
// then use all our innate attacks.. // then use all our innate attacks..
getflags(lf->flags, F_HASATTACK, F_NONE); getflags(lf->flags, F_HASATTACK, F_NONE);
for (i = 0; i < nretflags; i++) { for (i = 0; i < nretflags; i++) {
f = retflag[i]; f = retflag[i];
@ -2160,4 +2159,24 @@ void wepeffects(flagpile_t *fp, cell_t *where, flag_t *damflag, int dam) {
} // end if (fid == hitconfer) } // end if (fid == hitconfer)
} }
if (wep && owner && victim) {
if ((wep->type->id == OT_TEETH) && lfhasflag(owner, F_VAMPIRIC) && isbleeding(victim)) {
// drain life!
gainhp(owner, dam);
if (isplayer(owner)) {
char lfname[BUFLEN];
char victimname[BUFLEN];
getlfname(owner,lfname);
getlfname(victim, victimname);
msg("You suck %s%s blood!", victimname, getpossessive(victimname));
} else if (cansee(player, owner)) {
char lfname[BUFLEN];
char victimname[BUFLEN];
getlfname(owner,lfname);
getlfname(victim, victimname);
msg("%s sucks %s%s blood!", lfname, victimname, getpossessive(victimname));
}
}
}
} }

17
defs.h
View File

@ -735,6 +735,7 @@ enum RACE {
R_ANTS, R_ANTS,
R_ANTLION, R_ANTLION,
R_BAT, R_BAT,
R_BATVAMPIRE,
R_BEAR, R_BEAR,
R_BEARCUB, R_BEARCUB,
R_BEARGRIZZLY, R_BEARGRIZZLY,
@ -895,6 +896,7 @@ enum OBTYPE {
OT_TREE, OT_TREE,
// food // food
OT_BERRY, OT_BERRY,
OT_GARLIC,
OT_NUT, OT_NUT,
OT_BANANA, OT_BANANA,
OT_BANANASKIN, // not really food OT_BANANASKIN, // not really food
@ -1489,6 +1491,7 @@ enum NOISETYPE {
N_FLY, N_FLY,
N_WARCRY, N_WARCRY,
N_LOWHP, N_LOWHP,
N_FRUSTRATED,
}; };
enum LFSIZE { enum LFSIZE {
@ -1838,8 +1841,10 @@ enum FLAG {
//F_SPELLLETTER, // text[0] = letter to cast this spell //F_SPELLLETTER, // text[0] = letter to cast this spell
F_AICASTTOFLEE, // AI can cast this spell to help flee/heal F_AICASTTOFLEE, // AI can cast this spell to help flee/heal
// v0 is who to target // v0 is who to target
// v1 is pct chance of using this
F_AICASTTOATTACK, // AI can cast this spell to attack F_AICASTTOATTACK, // AI can cast this spell to attack
// v0 is who to target // v0 is who to target
// v1 is pct chance of using this
F_AIBOOSTITEM, // ai will use this item to boost/buff itself. F_AIBOOSTITEM, // ai will use this item to boost/buff itself.
// if using this on wands, update aiobok() ! // if using this on wands, update aiobok() !
F_AIHEALITEM, // ai will use this item when low on hp F_AIHEALITEM, // ai will use this item when low on hp
@ -1858,6 +1863,7 @@ enum FLAG {
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
F_VAMPIRIC, // successful bite attacks form this lf will heal it
F_VEGETARIAN, // this lf will not eat meat. F_VEGETARIAN, // this lf will not eat meat.
F_PARTVEGETARIAN,// this lf will only eat if hunger >= 'hungry' F_PARTVEGETARIAN,// this lf will only eat if hunger >= 'hungry'
F_CARNIVORE, // this lf will only eat meat. F_CARNIVORE, // this lf will only eat meat.
@ -1934,8 +1940,13 @@ enum FLAG {
// v2 is counter until casting // v2 is counter until casting
// text is: "targlfid;targobid;mapid;cellx;celly;" // text is: "targlfid;targobid;mapid;cellx;celly;"
F_AVOIDCURSEDOB, // for AI animals - they will avoid walking on obid 'text' F_AVOIDOB, // for AI - they will avoid walking on obid 'text'
// (text is a long) // (text is a long)
// if v0 is not NA, then only avoid it if its blessed
// value == v0.
F_AVOIDOBTYPE, // AI won't walk on top of obtype v0.
// if v1 == B_TRUE, then avoid lfs weilding this
// object too.
F_STAYINHABITAT, // lf will not walk onto a cell of a different F_STAYINHABITAT, // lf will not walk onto a cell of a different
// habitat // habitat
F_STAYINROOM, // lf will not walk out of roomid v0 F_STAYINROOM, // lf will not walk out of roomid v0
@ -2048,6 +2059,7 @@ enum FLAG {
// v0 = max distance to splatter (or UNLIMITED) // v0 = max distance to splatter (or UNLIMITED)
// text = type of object to splatter // text = type of object to splatter
F_OBESE, // double base weight for race! F_OBESE, // double base weight for race!
F_FORCEPOLY, // when this lf polymorphs, always chance to raceid v0
F_ORIGRACE, // original player race (if you polymorphed) F_ORIGRACE, // original player race (if you polymorphed)
F_ORIGJOB, // original player job (if you polymorphed) F_ORIGJOB, // original player job (if you polymorphed)
F_POLYMORPHED, // lf has been polymorphed F_POLYMORPHED, // lf has been polymorphed
@ -2113,7 +2125,8 @@ enum FLAG {
// otherwise just an indicative size is shown // otherwise just an indicative size is shown
F_DETECTMAGIC, // autodetect magic/special objects F_DETECTMAGIC, // autodetect magic/special objects
F_DETECTMETAL, // autodetect nearby metal F_DETECTMETAL, // autodetect nearby metal
F_DETECTOBS, // autodetect nearby obs in orthog dist v0 F_DETECTOBS, // autodetect nearby obs of type v1 in orthog dist v0
// v1 = NA means everything.
F_DISEASEIMMUNE, // lf can't be diseased F_DISEASEIMMUNE, // lf can't be diseased
F_DRUNK, // v1 is drunknness - 1-5. F_DRUNK, // v1 is drunknness - 1-5.
F_ENHANCESEARCH, // gives v0 bonus on search checks. F_ENHANCESEARCH, // gives v0 bonus on search checks.

10
flag.c
View File

@ -100,6 +100,7 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
f->val[1] += val2; f->val[1] += val2;
f->val[2] += val3; f->val[2] += val3;
// TODO: how to handle text?? // TODO: how to handle text??
f->text = strdup("");
return f; return f;
} }
} }
@ -303,6 +304,15 @@ flagpile_t *addflagpile(lifeform_t *owner, object_t *ob) {
return fp; return fp;
} }
void changeflagtext(flag_t *f, char *newtext) {
free(f->text);
if (newtext) {
f->text = strdup(newtext);
} else {
f->text = strdup("");
}
}
void copyflag(flagpile_t *dst, flagpile_t *src, enum FLAG id) { void copyflag(flagpile_t *dst, flagpile_t *src, enum FLAG id) {
flag_t *f; flag_t *f;
for (f = src->first ; f ; f = f->next) { for (f = src->first ; f ; f = f->next) {

1
flag.h
View File

@ -8,6 +8,7 @@ flag_t *addflag(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char
flag_t *addtempflag(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char *text, int timeleft); flag_t *addtempflag(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char *text, int timeleft);
flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char *text, int lifetime, int known, long obfromid); flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char *text, int lifetime, int known, long obfromid);
flagpile_t *addflagpile(lifeform_t *owner, object_t *o); flagpile_t *addflagpile(lifeform_t *owner, object_t *o);
void changeflagtext(flag_t *f, char *newtext);
void copyflag(flagpile_t *dst, flagpile_t *src, enum FLAG id); void copyflag(flagpile_t *dst, flagpile_t *src, enum FLAG id);
void copyflags(flagpile_t *dst, flagpile_t *src, int lifetime); void copyflags(flagpile_t *dst, flagpile_t *src, int lifetime);
int countflags(flagpile_t *fp); int countflags(flagpile_t *fp);

13
god.c
View File

@ -293,7 +293,7 @@ int godgiftmaybe(enum RACE rid) {
int chance; int chance;
// ie. 100 -> 2% // ie. 100 -> 2%
// ie. 500 -> 10% // ie. 500 -> 10%
chance = piety / 5; 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.
char obtogive[BUFLEN]; char obtogive[BUFLEN];
int rollagain = B_TRUE; int rollagain = B_TRUE;
@ -307,7 +307,7 @@ int godgiftmaybe(enum RACE rid) {
flag_t *f; flag_t *f;
object_t *wep; object_t *wep;
rollagain = B_FALSE; rollagain = B_FALSE;
switch (rnd(5,5)) { switch (rnd(1,5)) {
case 1: case 1:
sprintf(obtogive, "3-5 cursed potions of water"); sprintf(obtogive, "3-5 cursed potions of water");
break; break;
@ -338,7 +338,7 @@ int godgiftmaybe(enum RACE rid) {
break; break;
case 5: case 5:
msg("\"Go forth and kill in my name!\""); msg("\"Go forth and kill in my name!\"");
setrace(player, R_VAMPIRE, B_TRUE); setrace(player, R_VAMPIRE, B_TRUE); // ie. don't set origrace!
break; break;
} }
} }
@ -394,8 +394,9 @@ int godgiftmaybe(enum RACE rid) {
} }
} }
// since you got a gift, lower piety back to 100 (slightly pleased) // since you got a gift, lower piety a little.
setpiety(rid, 101); //setpiety(rid, 101);
modpiety(rid, -50);
} // end if (pctchance enough to get a gift) } // end if (pctchance enough to get a gift)
} // end if (piety > 100) } // end if (piety > 100)
return gotgift; return gotgift;
@ -444,7 +445,7 @@ void pleasegod(enum RACE rid, int amt) {
modpiety(rid, amt); modpiety(rid, amt);
// announce // announce
//msg("You feel like %s approves of your actions.", lfname); msg("You feel like %s approves of your actions.", lfname);
godgiftmaybe(rid); godgiftmaybe(rid);
} }

4
io.c
View File

@ -7384,7 +7384,7 @@ void drawstatus(void) {
if (hlev == H_NONE) { if (hlev == H_NONE) {
strcpy(buf2, ""); strcpy(buf2, "");
} else { } else {
gethungername(gethungerlevel(f->val[0]), buf2); gethungername(player, gethungerlevel(f->val[0]), buf2);
capitalise(buf2); capitalise(buf2);
} }
} else { } else {
@ -8162,7 +8162,7 @@ void showlfstats(lifeform_t *lf, int showall) {
if (f) { if (f) {
doheadingsmall(mainwin, y2, x2, ftext, "Hunger"); doheadingsmall(mainwin, y2, x2, ftext, "Hunger");
gethungername(gethungerlevel(f->val[0]), buf); gethungername(lf, gethungerlevel(f->val[0]), buf);
capitalise(buf); capitalise(buf);
wprintw(mainwin, "%-14s", buf); y2++; wprintw(mainwin, "%-14s", buf); y2++;
/* /*

202
lf.c
View File

@ -1236,6 +1236,16 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
// stop hiding // stop hiding
killflagsofid(lf->flags, F_HIDING); killflagsofid(lf->flags, F_HIDING);
// willing this spell? reset counter!
// do this _before_ casting the spell,
// in case the spell causes us to lose
// the f_canwill flag (eg. polymorph)
if (willflag) {
if (willflag->val[2] != NA) {
willflag->val[1] = -1;
}
}
// cast the spell // cast the spell
f = hasflag(sp->flags, F_CASTINGTIME); f = hasflag(sp->flags, F_CASTINGTIME);
if (f) { if (f) {
@ -1284,13 +1294,6 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
} }
} }
// willing this spell? reset counter!
if (willflag) {
if (willflag->val[2] != NA) {
willflag->val[1] = -1;
}
}
// successful cast? // successful cast?
if (!rv) { if (!rv) {
practice(lf, SK_SPELLCASTING, 1); practice(lf, SK_SPELLCASTING, 1);
@ -1330,6 +1333,16 @@ int checkfordrowning(lifeform_t *lf, object_t *o) {
// will you drown? // will you drown?
if (depth >= DP_HEAD) { if (depth >= DP_HEAD) {
if (lf->race->id == R_VAMPIRE) {
if (isplayer(lf)) {
msg("^BThe running water burns you!");
} else if (cansee(player, lf)) {
char lfname[BUFLEN];
getlfname(lf, lfname);
msg("^%cThe running water burns %s!", getlfcol(lf, CC_BAD), lfname);
}
losehp(lf, roll("6d6"), DT_DIRECT, NULL, "running water");
}
if (!slev && !lfhasflag(lf, F_BREATHWATER)) { if (!slev && !lfhasflag(lf, F_BREATHWATER)) {
int damamt; int damamt;
@ -1673,9 +1686,9 @@ void die(lifeform_t *lf) {
} }
} }
if (lf->race->id == R_VAMPIRE) { if ((lf->race->id == R_VAMPIRE) && !hasflag(lf->flags, F_ORIGRACE)) {
// if are asleep, we will die normally // if are asleep or killed by running water/sunlight, we will die normally
if (lfhasflag(lf, F_ASLEEP)) { if (lfhasflag(lf, F_ASLEEP) || (lf->lastdamtype == DT_DIRECT)) {
noise(lf->cell, lf, NC_OTHER, 4, "a horrified scream!", "screams in horror!"); noise(lf->cell, lf, NC_OTHER, 4, "a horrified scream!", "screams in horror!");
} else if (findobinmap(lf->cell->map, OT_COFFIN)) { // coffin around? } else if (findobinmap(lf->cell->map, OT_COFFIN)) { // coffin around?
// restore 1 hp // restore 1 hp
@ -1684,7 +1697,9 @@ void die(lifeform_t *lf) {
// convert into a gas cloud! // convert into a gas cloud!
dospelleffects(NULL, OT_S_GASEOUSFORM, 10, lf, NULL, lf->cell, B_UNCURSED, NULL, B_TRUE); dospelleffects(NULL, OT_S_GASEOUSFORM, 10, lf, NULL, lf->cell, B_UNCURSED, NULL, B_TRUE);
// ai will now look for our coffin // ai will now look for our coffin
if (!isplayer(lf)) { if (isplayer(lf)) {
msg("^GYou feel the presence of a nearby coffin...");
} else {
addflag(lf->flags, F_WANTS, OT_COFFIN, B_COVETS, NA, NULL); addflag(lf->flags, F_WANTS, OT_COFFIN, B_COVETS, NA, NULL);
addflag(lf->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lf->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
} }
@ -1854,8 +1869,7 @@ void die(lifeform_t *lf) {
// remember what killed us. // remember what killed us.
f = hasflag(corpse->flags, F_CORPSEOF); f = hasflag(corpse->flags, F_CORPSEOF);
if (f) { if (f) {
free(f->text); changeflagtext(f, lf->lastdam);
f->text = strdup(lf->lastdam);
} }
} }
@ -2894,8 +2908,7 @@ void enhanceskills(lifeform_t *lf) {
break; break;
} }
if (!streq(newtext, f->text)) { if (!streq(newtext, f->text)) {
free(f->text); changeflagtext(f, newtext);
f->text = strdup(newtext);
if (isplayer(lf)) msg("^gYour unarmed attack damage has increased!"); if (isplayer(lf)) msg("^gYour unarmed attack damage has increased!");
} }
} }
@ -3252,7 +3265,6 @@ int flee(lifeform_t *lf) {
} }
// are we fleeing? // are we fleeing?
getflags(lf->flags, F_FLEEFROM, F_NONE); getflags(lf->flags, F_FLEEFROM, F_NONE);
for (i = 0; i < nretflags; i++) { for (i = 0; i < nretflags; i++) {
f = retflag[i]; f = retflag[i];
@ -4193,8 +4205,42 @@ object_t *getbestweapon(lifeform_t *lf) {
object_t *bestwep = NULL; object_t *bestwep = NULL;
//int bestmaxdam = -999; //int bestmaxdam = -999;
object_t *o; object_t *o;
obpile_t *op = NULL;
bestwep = getweapon(lf); bestwep = getweapon(lf);
if (!bestwep) {
int i;
// get best innate attack
getflags(lf->flags, F_HASATTACK, F_NONE);
for (i = 0; i < nretflags; i++) {
objecttype_t *ot;
if (!op) {
op = addobpile(NULL, NULL, NULL);
}
ot = findot(retflag[i]->val[0]);
if (ot) {
o = addob(op, ot->name);
if (isweapon(o) && !isfirearm(o) && canweild(lf, o) && isbetterwepthan(o, bestwep)) {
bestwep = o;
// inherit damage from hasattack flag
if (strlen(retflag[i]->text)) {
flag_t *damflag;
damflag = hasflag(bestwep->flags, F_DAM);
if (damflag) {
free(damflag->text);
damflag->text = strdup(retflag[i]->text);
}
}
} else {
killob(o);
}
}
}
}
for (o = lf->pack->first ; o ; o = o->next) { for (o = lf->pack->first ; o ; o = o->next) {
// if it does damage and we can weild it... // if it does damage and we can weild it...
@ -4216,6 +4262,15 @@ object_t *getbestweapon(lifeform_t *lf) {
} }
*/ */
if (bestwep && (bestwep->pile->owner == NULL)) {
// ie. best weapon is an innate attack
bestwep = NULL;
}
if (op) {
killobpile(op);
}
return bestwep; return bestwep;
} }
@ -4442,7 +4497,7 @@ enum HUNGER gethungerlevel(int hunger) {
return H_STARVED; return H_STARVED;
} }
char *gethungername(enum HUNGER hunger, char *buf) { char *gethungername(lifeform_t *lf, enum HUNGER hunger, char *buf) {
switch (hunger) { switch (hunger) {
case H_STUFFED: case H_STUFFED:
strcpy(buf, "stuffed"); strcpy(buf, "stuffed");
@ -4451,19 +4506,39 @@ char *gethungername(enum HUNGER hunger, char *buf) {
strcpy(buf, "full"); strcpy(buf, "full");
break; break;
case H_NONE: case H_NONE:
strcpy(buf, "not hungry"); if (lf && (lf->race->id == R_VAMPIRE)) {
strcpy(buf, "not thirsty");
} else {
strcpy(buf, "not hungry");
}
break; break;
case H_PECKISH: case H_PECKISH:
strcpy(buf, "peckish"); if (lf && (lf->race->id == R_VAMPIRE)) {
strcpy(buf, "parched");
} else {
strcpy(buf, "peckish");
}
break; break;
case H_HUNGRY: case H_HUNGRY:
strcpy(buf, "hungry"); if (lf && (lf->race->id == R_VAMPIRE)) {
strcpy(buf, "thirsty");
} else {
strcpy(buf, "hungry");
}
break; break;
case H_VHUNGRY: case H_VHUNGRY:
strcpy(buf, "very hungry"); if (lf && (lf->race->id == R_VAMPIRE)) {
strcpy(buf, "very thirsty");
} else {
strcpy(buf, "very hungry");
}
break; break;
case H_STARVING: case H_STARVING:
strcpy(buf, "starving"); if (lf && (lf->race->id == R_VAMPIRE)) {
strcpy(buf, "dehydrating");
} else {
strcpy(buf, "starving");
}
break; break;
case H_STARVED: case H_STARVED:
strcpy(buf, "starved"); strcpy(buf, "starved");
@ -6262,16 +6337,14 @@ void givejob(lifeform_t *lf, enum JOB jobid) {
f = lfhasflagval(lf, F_HASATTACK, OT_FISTS, NA, NA, NULL); f = lfhasflagval(lf, F_HASATTACK, OT_FISTS, NA, NA, NULL);
if (f) { if (f) {
// monk fists do more damage // monk fists do more damage
free(f->text); changeflagtext(f, "1d4");
f->text = strdup("1d4");
} }
} else if (j->id == J_PIRATE) { } else if (j->id == J_PIRATE) {
flag_t *f; flag_t *f;
f = lfhasflagval(lf, F_HASATTACK, OT_FISTS, NA, NA, NULL); f = lfhasflagval(lf, F_HASATTACK, OT_FISTS, NA, NA, NULL);
if (f) { if (f) {
f->val[0] = OT_HOOKHAND; f->val[0] = OT_HOOKHAND;
free(f->text); changeflagtext(f, "1d4");
f->text = strdup("1d4");
} }
} else if (j->id == J_SHOPKEEPER) { } else if (j->id == J_SHOPKEEPER) {
// shopkeepers are not hostile. // shopkeepers are not hostile.
@ -8330,7 +8403,8 @@ void initrace(void) {
addflag(lastrace->flags, F_STARTOBCLASS, 50, OC_ARMOUR, NA, NULL); addflag(lastrace->flags, F_STARTOBCLASS, 50, OC_ARMOUR, NA, NULL);
addflag(lastrace->flags, F_STARTOBCLASS, 50, OC_ARMOUR, NA, NULL); addflag(lastrace->flags, F_STARTOBCLASS, 50, OC_ARMOUR, NA, NULL);
addflag(lastrace->flags, F_WANTSBETTERWEP, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_WANTSBETTERWEP, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 3, NA, "roars^a roars"); addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 3, NA, "roars^a roar");
addflag(lastrace->flags, F_NOISETEXT, N_FRUSTRATED, 3, NA, "roars^a roar");
addflag(lastrace->flags, F_SEEINDARK, 3, NA, NA, NULL); addflag(lastrace->flags, F_SEEINDARK, 3, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_A_HEAVYBLOW, 2, 2, NULL); addflag(lastrace->flags, F_CANWILL, OT_A_HEAVYBLOW, 2, 2, NULL);
addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL);
@ -9510,6 +9584,28 @@ void initrace(void) {
addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_TREMORSENSE, 10, NA, NA, NULL); addflag(lastrace->flags, F_TREMORSENSE, 10, NA, NA, NULL);
addflag(lastrace->flags, F_NOISETEXT, N_FLY, 1, NA, "^flapping wings"); addflag(lastrace->flags, F_NOISETEXT, N_FLY, 1, NA, "^flapping wings");
addrace(R_BATVAMPIRE, "vampire bat", 6, 'B', C_BLUE, MT_FLESH, RC_ANIMAL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 76, NA, "");
addflag(lastrace->flags, F_RARITY, H_FOREST, 84, NA, "");
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_VERYFAST, NA, NA, "");
addflag(lastrace->flags, F_FLYING, B_TRUE, NA, NA, "");
addflag(lastrace->flags, F_HITDICE, 2, 4, NA, "");
addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d2");
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d3");
addflag(lastrace->flags, F_MAXATTACKS, 2, 2, NA, NULL);
addflag(lastrace->flags, F_EVASION, -10, NA, NA, NULL);
addflag(lastrace->flags, F_VAMPIRIC, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOBODYPART, BP_WEAPON, NA, NA, NULL);
addflag(lastrace->flags, F_NOBODYPART, BP_SECWEAPON, NA, NA, NULL);
addflag(lastrace->flags, F_NOBODYPART, BP_SHOULDERS, NA, NA, NULL);
addflag(lastrace->flags, F_NOBODYPART, BP_HANDS, NA, NA, NULL);
addflag(lastrace->flags, F_NOBODYPART, BP_LEGS, NA, NA, NULL);
addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_TREMORSENSE, 10, NA, NA, NULL);
addflag(lastrace->flags, F_NOISETEXT, N_FLY, 1, NA, "^flapping wings");
addrace(R_BEAR, "black bear", 150, 'q', C_BLUE, MT_FLESH, RC_ANIMAL); addrace(R_BEAR, "black bear", 150, 'q', C_BLUE, MT_FLESH, RC_ANIMAL);
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);
@ -9679,6 +9775,8 @@ void initrace(void) {
addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, NA, NA, NULL); addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, NA, NA, NULL);
addflag(lastrace->flags, F_SEEINDARK, 6, NA, NA, NULL); addflag(lastrace->flags, F_SEEINDARK, 6, NA, NA, NULL);
addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 3, NA, "barks^barking");
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");
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);
@ -9703,6 +9801,8 @@ void initrace(void) {
addflag(lastrace->flags, F_SEEINDARK, 6, NA, NA, NULL); addflag(lastrace->flags, F_SEEINDARK, 6, NA, NA, NULL);
addflag(lastrace->flags, F_SPELLCASTTEXT, NA, NA, NA, NULL); // don't announce spellcasting addflag(lastrace->flags, F_SPELLCASTTEXT, NA, NA, NA, NULL); // don't announce spellcasting
addflag(lastrace->flags, F_CANWILL, OT_S_BLINK, 2, 2, "pw:1;"); addflag(lastrace->flags, F_CANWILL, OT_S_BLINK, 2, 2, "pw:1;");
addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 3, NA, "barks^barking");
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_NUMAPPEAR, 2, 6, NA, ""); addflag(lastrace->flags, F_NUMAPPEAR, 2, 6, NA, "");
@ -9727,6 +9827,8 @@ void initrace(void) {
addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SEEINDARK, 5, NA, NA, NULL); addflag(lastrace->flags, F_SEEINDARK, 5, NA, NA, NULL);
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_NOISETEXT, N_GETANGRY, 3, NA, "howls^a howl");
addflag(lastrace->flags, F_NOISETEXT, N_FRUSTRATED, 3, NA, "growls^growling");
addflag(lastrace->flags, F_HITCONFER, F_POISONED, SC_POISON, 24, "10-15"); addflag(lastrace->flags, F_HITCONFER, F_POISONED, SC_POISON, 24, "10-15");
addflag(lastrace->flags, F_HITCONFERVALS, P_VENOM, 1, NA, NULL); addflag(lastrace->flags, F_HITCONFERVALS, P_VENOM, 1, NA, NULL);
addflag(lastrace->flags, F_CRITKNOCKDOWN, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_CRITKNOCKDOWN, B_TRUE, NA, NA, NULL);
@ -9751,6 +9853,8 @@ void initrace(void) {
addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, NA, NA, NULL); addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, NA, NA, NULL);
addflag(lastrace->flags, F_SEEINDARK, 5, NA, NA, NULL); addflag(lastrace->flags, F_SEEINDARK, 5, NA, NA, NULL);
addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 3, NA, "barks^barking");
addflag(lastrace->flags, F_NOISETEXT, N_FRUSTRATED, 2, 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_HAWKYOUNG, "young hawk", 1, 'A', C_GREY, MT_FLESH, RC_ANIMAL); // 'A' for Avian addrace(R_HAWKYOUNG, "young hawk", 1, 'A', C_GREY, MT_FLESH, RC_ANIMAL); // 'A' for Avian
@ -10184,6 +10288,7 @@ void initrace(void) {
addflag(lastrace->flags, F_CANWILL, OT_A_SPRINT, 8, 8, NULL); addflag(lastrace->flags, F_CANWILL, OT_A_SPRINT, 8, 8, NULL);
addflag(lastrace->flags, F_LEVRACE, 5, R_WOLF, NA, NULL); addflag(lastrace->flags, F_LEVRACE, 5, R_WOLF, NA, NULL);
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_NOISETEXT, N_FRUSTRATED, 3, NA, "growls^growling");
addflag(lastrace->flags, F_FLEEONHPPCT, 75, NA, NA, ""); addflag(lastrace->flags, F_FLEEONHPPCT, 75, NA, NA, "");
addrace(R_WOLF, "wolf", 25, 'd', C_GREY, MT_FLESH, RC_ANIMAL); addrace(R_WOLF, "wolf", 25, 'd', C_GREY, MT_FLESH, RC_ANIMAL);
addflag(lastrace->flags, F_STARTATT, A_CON, AT_VHIGH, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_CON, AT_VHIGH, NA, NULL);
@ -10208,6 +10313,7 @@ void initrace(void) {
addflag(lastrace->flags, F_SEEINDARK, 5, NA, NA, NULL); addflag(lastrace->flags, F_SEEINDARK, 5, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_A_SPRINT, 5, 5, NULL); addflag(lastrace->flags, F_CANWILL, OT_A_SPRINT, 5, 5, NULL);
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_NOISETEXT, N_FRUSTRATED, 3, NA, "growls^growling");
addflag(lastrace->flags, F_FLEEONHPPCT, 50, NA, NA, ""); addflag(lastrace->flags, F_FLEEONHPPCT, 50, NA, NA, "");
// insects // insects
@ -10460,21 +10566,33 @@ void initrace(void) {
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_HUMANOID, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_VAMPIRIC, 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_DTVULN, DT_LIGHT, NA, NA, "3d6");
addflag(lastrace->flags, F_SEEINVIS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SEEINVIS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SEEINDARK, 8, NA, NA, NULL);
addflag(lastrace->flags, F_AVOIDOBTYPE, OT_GARLIC, B_TRUE, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_FAST, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_FAST, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_FAST, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 8, 3, NA, NULL); addflag(lastrace->flags, F_HITDICE, 8, 3, NA, NULL);
addflag(lastrace->flags, F_ARMOURRATING, 5, NA, NA, NULL); addflag(lastrace->flags, F_ARMOURRATING, 5, NA, NA, NULL);
addflag(lastrace->flags, F_EVASION, -10, NA, NA, NULL); addflag(lastrace->flags, F_EVASION, -10, NA, NA, NULL);
addflag(lastrace->flags, F_HOMEOB, NA, NA, NA, "coffin"); addflag(lastrace->flags, F_HOMEOB, NA, NA, NA, "coffin");
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d6+4"); addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d6+4");
addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d4+3");
addflag(lastrace->flags, F_FLYING, B_TRUE, NA, NA, "");
addflag(lastrace->flags, F_CANWILL, OT_S_CHARM, 3, 3, "pw:6;"); addflag(lastrace->flags, F_CANWILL, OT_S_CHARM, 3, 3, "pw:6;");
addflag(lastrace->flags, F_CANWILL, OT_A_CHARGE, 5, 5, "range:3;"); addflag(lastrace->flags, F_CANWILL, OT_A_CHARGE, 5, 5, "range:3;");
addflag(lastrace->flags, F_CANWILL, OT_S_STUN, 5, 5, "pw:1;");
addflag(lastrace->flags, F_CANWILL, OT_S_POLYMORPH, 3, 3, "pw:1;");
addflag(lastrace->flags, F_FORCEPOLY, R_BATVAMPIRE, 20, 20, "pw:3;");
addflag(lastrace->flags, F_DETECTOBS, 10, OT_COFFIN, NA, NULL);
addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "pile of ash"); addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "pile of ash");
addflag(lastrace->flags, F_NOISETEXT, N_FRUSTRATED, 3, NA, "hisses angrily^an angry hiss");
// special: change to gas cloud with 1 hp on death, if not asleep // special: change to gas cloud with 1 hp on death, if not asleep
// special: flee from garlic
// TODO: can shapeshift to bat // TODO: can shapeshift to bat
// TODO: flee from holy symbols / garlic
addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL);
@ -12569,6 +12687,10 @@ void modhunger(lifeform_t *lf, int amt) {
return; return;
} }
if (isundead(lf) && (lf->race->id != R_VAMPIRE)) {
return;
}
// modify for effects // modify for effects
if (amt > 0) { if (amt > 0) {
int multiplier = 0; int multiplier = 0;
@ -12622,7 +12744,7 @@ void modhunger(lifeform_t *lf, int amt) {
if (isplayer(lf)) { if (isplayer(lf)) {
gethungername(posthlev, buf); gethungername(lf, posthlev, buf);
msg("^wYou are %s%s%s%c", msg("^wYou are %s%s%s%c",
((amt < 0) && (posthlev > H_NONE)) ? "still " : "", ((amt < 0) && (posthlev > H_NONE)) ? "still " : "",
needfeeling ? "feeling " : "", needfeeling ? "feeling " : "",
@ -12633,7 +12755,7 @@ void modhunger(lifeform_t *lf, int amt) {
} else if (cansee(player, lf)) { } else if (cansee(player, lf)) {
char lfname[BUFLEN]; char lfname[BUFLEN];
getlfname(lf, lfname); getlfname(lf, lfname);
gethungername(posthlev, buf); gethungername(lf, posthlev, buf);
msg("^%c%s looks %s%c", getlfcol(lf, CC_BAD), lfname, buf, (needexclam) ? '!' : '.'); msg("^%c%s looks %s%c", getlfcol(lf, CC_BAD), lfname, buf, (needexclam) ? '!' : '.');
} }
@ -13792,6 +13914,7 @@ void setguntarget(lifeform_t *lf, lifeform_t *targ) {
void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) { void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
flag_t *f,*nextf; flag_t *f,*nextf;
int i; int i;
int nkilled = 0;
race_t *newrace; race_t *newrace;
char buf[BUFLEN]; char buf[BUFLEN];
@ -13862,8 +13985,10 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
nextf = f->next; nextf = f->next;
if (f->lifetime == FROMRACE) { if (f->lifetime == FROMRACE) {
killflag(f); killflag(f);
nkilled++;
} else if ((f->lifetime > 0) && (f->id != F_POLYMORPHED)) { } else if ((f->lifetime > 0) && (f->id != F_POLYMORPHED)) {
killflag(f); killflag(f);
nkilled++;
} }
} }
@ -14475,7 +14600,7 @@ int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *r
} }
break; break;
case SC_RESISTMAG: case SC_RESISTMAG:
attrib = (getattr(lf, A_CON)/4) + (getattr(lf, A_WIS)/4) + getmr(lf); attrib = (getattr(lf, A_CON)/6) + (getattr(lf, A_WIS)/4) + getmr(lf);
break; break;
case SC_SEARCH: case SC_SEARCH:
attrib = (getskill(lf, SK_SPOTHIDDEN)*4); attrib = (getskill(lf, SK_SPOTHIDDEN)*4);
@ -15045,6 +15170,7 @@ int takeoff(lifeform_t *lf, object_t *o) {
if ((gamemode == GM_GAMESTARTED)) { if ((gamemode == GM_GAMESTARTED)) {
if (isplayer(lf)) { if (isplayer(lf)) {
msg("You take off %s.", obname); msg("You take off %s.", obname);
statdirty = B_TRUE;
} else if (cansee(player, lf)) { } else if (cansee(player, lf)) {
getlfname(lf, buf); getlfname(lf, buf);
capitalise(buf); capitalise(buf);
@ -15335,6 +15461,18 @@ void turneffectslf(lifeform_t *lf) {
if (isdead(lf)) return; if (isdead(lf)) return;
} }
} }
// vampire in sunlight?
if ((lf->race->id == R_VAMPIRE) && isoutdoors(lf->cell->map) && !isnighttime()) {
if (isplayer(lf)) {
msg("^bThe sunlight burns you!");
} else if (cansee(player, lf)) {
char lfname[BUFLEN];
getlfname(lf, lfname);
msg("^%cThe sunlight burns %s!", getlfcol(lf, CC_BAD), lfname);
}
losehp(lf, roll("6d6"), DT_DIRECT, NULL, "sunlight");
if (isdead(lf)) return;
}
// float up into space? // float up into space?
if (lf->cell->map->region->rtype->id == RG_WORLDMAP) { if (lf->cell->map->region->rtype->id == RG_WORLDMAP) {

2
lf.h
View File

@ -120,7 +120,7 @@ int gethidemodifier(lifeform_t *lf);
int gethitdice(lifeform_t *lf); int gethitdice(lifeform_t *lf);
int gethppct(lifeform_t *lf); int gethppct(lifeform_t *lf);
enum HUNGER gethungerlevel(int hunger); enum HUNGER gethungerlevel(int hunger);
char * gethungername(enum HUNGER hunger, char *buf); char *gethungername(lifeform_t *lf, enum HUNGER hunger, char *buf);
int gethungerval(lifeform_t *lf); int gethungerval(lifeform_t *lf);
job_t *getjob(lifeform_t *lf); job_t *getjob(lifeform_t *lf);
int getlastdir(lifeform_t *lf); int getlastdir(lifeform_t *lf);

44
map.c
View File

@ -30,6 +30,9 @@ extern lifeform_t *player;
extern lifeform_t *godlf[]; extern lifeform_t *godlf[];
extern int ngodlfs; extern int ngodlfs;
extern flag_t *retflag[];
extern int nretflags;
extern glyph_t tempglyph; extern glyph_t tempglyph;
extern enum OBCLASS sortorder[]; extern enum OBCLASS sortorder[];
@ -1247,7 +1250,7 @@ void calclight(map_t *map) {
if (isoutdoors(map)) { if (isoutdoors(map)) {
int hours,mins,secs; int hours,mins,secs;
splittime(&hours,&mins,&secs); splittime(&hours,&mins,&secs);
if ((hours < 5) || (hours >= 19)) { if (isnighttime()) {
// ie. nighttime, after 7pm or before 5am // ie. nighttime, after 7pm or before 5am
} else { } else {
// ie. daytime // ie. daytime
@ -3861,6 +3864,7 @@ int isempty(cell_t *c) {
//returns TT_ based on what you can scan there //returns TT_ based on what you can scan there
int isinscanrange(cell_t *c, void **thing, char *desc, glyph_t *glyph) { int isinscanrange(cell_t *c, void **thing, char *desc, glyph_t *glyph) {
flag_t *f; flag_t *f;
int i;
// handle scanner // handle scanner
f = lfhasflag(player, F_DETECTLIFE); f = lfhasflag(player, F_DETECTLIFE);
if (f) { if (f) {
@ -3933,19 +3937,30 @@ int isinscanrange(cell_t *c, void **thing, char *desc, glyph_t *glyph) {
return TT_MONSTER; return TT_MONSTER;
} }
f = lfhasflag(player, F_DETECTOBS); // get list of all detected ob ids.
if (f) { getflags(player->flags, F_DETECTOBS, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (getcelldistorth(player->cell, c) <= f->val[0]) { if (getcelldistorth(player->cell, c) <= f->val[0]) {
object_t *o; object_t *o;
for (o = c->obpile->first ; o ; o = o->next) { for (o = c->obpile->first ; o ; o = o->next) {
if (!hasflag(o->flags, F_NOPICKUP) && !hasflag(o->flags, F_DOOR)) { if ((f->val[1] == NA) || (o->type->id == f->val[1])) {
*thing = o; if (!hasflag(o->flags, F_NOPICKUP) && !hasflag(o->flags, F_DOOR)) {
if (glyph) { *thing = o;
glyph->ch = '*'; if (glyph) {
glyph->colour = C_GREY; glyph->ch = '*';
glyph->colour = C_BOLDGREEN;
}
if (desc) {
if (f->val[1] == NA) {
strcpy(desc, "a detected object");
} else {
getobname(o, desc, o->amt);
}
}
return TT_OBJECT;
} }
if (desc) sprintf(desc, "an object");
return TT_OBJECT;
} }
} }
} }
@ -4000,6 +4015,15 @@ int isnewcellok(cell_t *cell, char *err) {
return B_TRUE; return B_TRUE;
} }
int isnighttime(void) {
int hours,mins,secs;
splittime(&hours,&mins,&secs);
if ((hours < 5) || (hours >= 19)) {
return B_TRUE;
}
return B_FALSE;
}
int isonmap(map_t *map, int x, int y) { int isonmap(map_t *map, int x, int y) {
if ((x < 0) || (y < 0)) { if ((x < 0) || (y < 0)) {
return B_FALSE; return B_FALSE;

1
map.h
View File

@ -97,6 +97,7 @@ int isinscanrange(cell_t *c, void **thing, char *desc, glyph_t *glyph);
int islit(cell_t *c); int islit(cell_t *c);
int isloopdirok(cell_t *cell, int dir); int isloopdirok(cell_t *cell, int dir);
int isnewcellok(cell_t *cell, char *err); int isnewcellok(cell_t *cell, char *err);
int isnighttime(void);
int isonmap(map_t *map, int x, int y); int isonmap(map_t *map, int x, int y);
int isoutdoors(map_t *m); int isoutdoors(map_t *m);
int isroom(cell_t *c); int isroom(cell_t *c);

41
move.c
View File

@ -26,6 +26,9 @@ extern enum GAMEMODE gamemode;
extern enum ERROR reason; extern enum ERROR reason;
extern void *rdata; extern void *rdata;
extern flag_t *retflag[];
extern int nretflags;
extern WINDOW *gamewin, *msgwin; extern WINDOW *gamewin, *msgwin;
int canandwillmove(lifeform_t *lf, int dir, enum ERROR *error) { int canandwillmove(lifeform_t *lf, int dir, enum ERROR *error) {
@ -1946,7 +1949,22 @@ int initiatemove(lifeform_t *lf, cell_t *cell, int *didmsg) {
reason = E_OK; reason = E_OK;
// avoid this object in future // avoid this object in future
sprintf(buf, "%ld",o->id); sprintf(buf, "%ld",o->id);
addflag(lf->flags, F_AVOIDCURSEDOB, NA, NA, NA, buf); addflag(lf->flags, F_AVOIDOB, B_CURSED, NA, NA, buf);
return B_TRUE;
} else if (lfhasflagval(lf, F_AVOIDOBTYPE, o->type->id, NA, NA, NULL)) {
if (cansee(player, lf)) {
char lfname[BUFLEN];
getlfname(lf,lfname);
getobname(o, buf, o->amt);
msg("%s %s away from %s!", lfname, isplayer(lf) ? "shy" : "shies", buf);
o->blessknown = B_TRUE;
if (didmsg) *didmsg = B_TRUE;
}
taketime(lf, getmovespeed(lf));
reason = E_OK;
// avoid this object in future
sprintf(buf, "%ld",o->id);
addflag(lf->flags, F_AVOIDOB, NA, NA, NA, buf);
return B_TRUE; return B_TRUE;
} }
} }
@ -2317,8 +2335,12 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
msg("You swap places with %s.", lfname); msg("You swap places with %s.", lfname);
} }
} else { } else {
// attack! if (!onpurpose || canandwillmove(lf, dir, &errcode)) {
return attackcell(lf, cell, B_FALSE); return attackcell(lf, cell, B_FALSE);
} else {
// won't attack for some reason.
return B_TRUE;
}
} }
break; break;
case E_CANTMOVE: case E_CANTMOVE:
@ -2540,6 +2562,7 @@ int willmove(lifeform_t *lf, int dir, enum ERROR *error) {
// don't attack other monsters // don't attack other monsters
if (cell->lf) { // if someone is in the way if (cell->lf) { // if someone is in the way
object_t *defenderwep = NULL;
if (lf->race->raceclass->id == RC_INSECT) { if (lf->race->raceclass->id == RC_INSECT) {
if (hasactivespell(cell->lf, OT_S_REPELINSECTS)) { if (hasactivespell(cell->lf, OT_S_REPELINSECTS)) {
if (error) *error = E_WONT; if (error) *error = E_WONT;
@ -2547,6 +2570,14 @@ int willmove(lifeform_t *lf, int dir, enum ERROR *error) {
} }
} }
defenderwep = getweapon(cell->lf);
if (defenderwep) {
if (lfhasflagval(lf, F_AVOIDOBTYPE, defenderwep->type->id, B_TRUE, NA, NULL)) {
if (error) *error = E_WONT;
return B_FALSE;
}
}
if (!isplayer(lf)) { // if we are a monster if (!isplayer(lf)) { // if we are a monster
// if the person in the way isn't our enemy... // if the person in the way isn't our enemy...
if (!areenemies(lf, cell->lf)) { if (!areenemies(lf, cell->lf)) {
@ -2573,10 +2604,10 @@ int willmove(lifeform_t *lf, int dir, enum ERROR *error) {
for (o = cell->obpile->first ; o ; o = o->next) { for (o = cell->obpile->first ; o ; o = o->next) {
flag_t *f; flag_t *f;
sprintf(buf, "%ld",o->id); sprintf(buf, "%ld",o->id);
f = lfhasflagval(lf, F_AVOIDCURSEDOB, NA, NA, NA, buf); f = lfhasflagval(lf, F_AVOIDOB, NA, NA, NA, buf);
if (f) { if (f) {
// still cursed? // still cursed?
if (iscursed(o)) { if ((f->val[0] != NA) && (o->blessed == f->val[0])) {
if (error) *error = E_WONT; if (error) *error = E_WONT;
return B_FALSE; return B_FALSE;
} else { } else {

View File

@ -2675,6 +2675,7 @@ objecttype_t *findotn(char *name) {
modname = strrep(modname, "blocks ", "block ", NULL); modname = strrep(modname, "blocks ", "block ", NULL);
modname = strrep(modname, "cans ", "can ", NULL); modname = strrep(modname, "cans ", "can ", NULL);
modname = strrep(modname, "chunks ", "chunk ", NULL); modname = strrep(modname, "chunks ", "chunk ", NULL);
modname = strrep(modname, "cloves ", "clove ", NULL);
modname = strrep(modname, "flasks ", "flask ", NULL); modname = strrep(modname, "flasks ", "flask ", NULL);
modname = strrep(modname, "gems ", "gem ", NULL); modname = strrep(modname, "gems ", "gem ", NULL);
modname = strrep(modname, "leaves ", "leaf ", NULL); modname = strrep(modname, "leaves ", "leaf ", NULL);
@ -6236,6 +6237,12 @@ void initobjects(void) {
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, NULL);
addflag(lastot->flags, F_RARITY, H_FOREST, 100, NA, NULL); addflag(lastot->flags, F_RARITY, H_FOREST, 100, NA, NULL);
addflag(lastot->flags, F_NUMAPPEAR, 1, 15, NA, ""); addflag(lastot->flags, F_NUMAPPEAR, 1, 15, NA, "");
addot(OT_GARLIC, "clove of garlic", "A very pungent clove of raw garlic. ", MT_FOOD, 0.1, OC_FOOD, SZ_TINY);
addflag(lastot->flags, F_GLYPH, C_BROWN, NA, NA, "%");
addflag(lastot->flags, F_EDIBLE, B_TRUE, 5, NA, "");
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_RARITY, H_FOREST, 100, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_NUMAPPEAR, 1, 3, NA, "");
addot(OT_NUT, "peanut", "A species in the legume family.", MT_FOOD, 0.1, OC_FOOD, SZ_TINY); addot(OT_NUT, "peanut", "A species in the legume family.", MT_FOOD, 0.1, OC_FOOD, SZ_TINY);
addflag(lastot->flags, F_GLYPH, C_BROWN, NA, NA, "%"); addflag(lastot->flags, F_GLYPH, C_BROWN, NA, NA, "%");
addflag(lastot->flags, F_EDIBLE, B_TRUE, 12, NA, ""); addflag(lastot->flags, F_EDIBLE, B_TRUE, 12, NA, "");
@ -7088,6 +7095,7 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 1, 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_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
// l2 // l2
addot(OT_S_LOWERMETAB, "lower metabolism", "Slow your body's functions, decreasing your rate of hunger but also your speed. At power level V your speed is no longer affected.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_LOWERMETAB, "lower metabolism", "Slow your body's functions, decreasing your rate of hunger but also your speed. At power level V your speed is no longer affected.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL);
@ -7199,6 +7207,8 @@ void initobjects(void) {
addot(OT_S_POLYMORPH, "polymorph", "Transmutes the target into a new living race.\nBecomes semi-controlled at Power V, and fully-controlled at power VIII.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_POLYMORPH, "polymorph", "Transmutes the target into a new living race.\nBecomes semi-controlled at Power V, and fully-controlled at power VIII.", 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_SPELLLEVEL, 6, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 6, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, 10, NA, NULL);
addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, NA, NA, NULL);
// l7 // l7
addot(OT_S_GASEOUSFORM, "gaseous form", "Changes the caster into a cloud of gas.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_GASEOUSFORM, "gaseous form", "Changes the caster into a cloud of gas.", 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);
@ -7390,6 +7400,7 @@ void initobjects(void) {
addot(OT_A_POLYREVERT, "revertform", "Revert to your original form.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY); addot(OT_A_POLYREVERT, "revertform", "Revert to your original form.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addflag(lastot->flags, F_NOANNOUNCE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOANNOUNCE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, 10, NA, NULL);
addot(OT_A_QUIVERINGPALM, "quivering palm", "A deadly palm strike which knocks the molecules in the target's body out of alignment.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY); addot(OT_A_QUIVERINGPALM, "quivering palm", "A deadly palm strike which knocks the molecules in the target's body out of alignment.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addot(OT_A_PRAY, "pray", "Ask for help from a higher being.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY); addot(OT_A_PRAY, "pray", "Ask for help from a higher being.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY);
@ -9581,7 +9592,6 @@ int isbetterwepthan(object_t *a, object_t *b) {
acca = getobaccuracy(a, a->pile->owner); acca = getobaccuracy(a, a->pile->owner);
accb = getobaccuracy(b, b->pile->owner); accb = getobaccuracy(b, b->pile->owner);
if (db) { if (db) {
msg("PREACC:a=%s:%d(acc %d), b=%s:%d(acc %d)",namea,dama,(int)acca, nameb, damb,(int)accb); msg("PREACC:a=%s:%d(acc %d), b=%s:%d(acc %d)",namea,dama,(int)acca, nameb, damb,(int)accb);
} }
@ -12631,7 +12641,9 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, object_t *o, enum BLESSTYPE
*seen = B_TRUE; *seen = B_TRUE;
} }
} }
modhunger(lf, -pctof(0.05, (float)HUNGERCONST)); if (!isundead(lf)) {
modhunger(lf, -pctof(0.05, (float)HUNGERCONST));
}
break; break;
case OT_POT_BLOOD: case OT_POT_BLOOD:
if (lf->race->id == R_VAMPIRE) { if (lf->race->id == R_VAMPIRE) {
@ -12643,6 +12655,7 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, object_t *o, enum BLESSTYPE
b = B_BLESSED; b = B_BLESSED;
} }
dospelleffects(lf, OT_S_HEALINGMAJ,b ? 5 : 1, lf, NULL, lf->cell, b, seen, B_TRUE); dospelleffects(lf, OT_S_HEALINGMAJ,b ? 5 : 1, lf, NULL, lf->cell, b, seen, B_TRUE);
modhunger(lf, -HUNGERCONST);
} else { } else {
if (isplayer(lf)) msg("Yuck, this tastes like blood!"); if (isplayer(lf)) msg("Yuck, this tastes like blood!");
} }

80
spell.c
View File

@ -1406,7 +1406,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
char dirch; char dirch;
char targetname[BUFLEN]; char targetname[BUFLEN];
flag_t *f; flag_t *f;
int heavyamt = 8; int heavyamt = 5;
int badweapon = B_FALSE; int badweapon = B_FALSE;
if (isswimming(user) && !lfhasflag(user, F_AQUATIC)) { if (isswimming(user) && !lfhasflag(user, F_AQUATIC)) {
@ -2183,7 +2183,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// controlled // controlled
// must be within line of sight. // must be within line of sight.
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE; if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE;
if (!targcell) { if (!targcell || !cellwalkable(caster, targcell, NULL)) {
fizzle(caster); fizzle(caster);
return B_TRUE; return B_TRUE;
} }
@ -4109,8 +4109,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
flag_t *f; flag_t *f;
f = hasflag(o->flags, F_WALKDAM); f = hasflag(o->flags, F_WALKDAM);
if (f) { if (f) {
free(f->text); changeflagtext(f, dambuf);
f->text = strdup(dambuf);
} }
} }
} }
@ -5819,6 +5818,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
breakallgrabs(caster); breakallgrabs(caster);
} else if (spellid == OT_S_POLYMORPH) { } else if (spellid == OT_S_POLYMORPH) {
race_t *r = NULL; race_t *r = NULL;
flag_t *f;
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE; if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE;
target = targcell->lf; target = targcell->lf;
@ -5828,7 +5828,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
return B_TRUE; return B_TRUE;
} }
if (skillcheck(target, SC_RESISTMAG, 20 + power, 0)) { if ((target != caster) && skillcheck(target, SC_RESISTMAG, 20 + power, 0)) {
if (isplayer(target)) { if (isplayer(target)) {
msg("You feel momentarily different."); msg("You feel momentarily different.");
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
@ -5840,46 +5840,51 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
return B_FALSE; return B_FALSE;
} }
if (lfhasflag(caster, F_CONTROL)) { f = lfhasflag(target, F_FORCEPOLY);
if (power < 5) { if (f) {
power = 5; r = findrace(f->val[0]);
} else {
if (lfhasflag(caster, F_CONTROL)) {
if (power < 5) {
power = 5;
}
} }
}
if (isplayer(caster) && (power >= 5)) { if (isplayer(caster) && (power >= 5)) {
if (isplayer(target)) { // ie. polymorphing yourself if (isplayer(target)) { // ie. polymorphing yourself
askstring("What will you become", '?', buf, BUFLEN, NULL); askstring("What will you become", '?', buf, BUFLEN, NULL);
} else { } else {
char buf2[BUFLEN]; char buf2[BUFLEN];
char targname[BUFLEN]; char targname[BUFLEN];
getlfname(target, targname); getlfname(target, targname);
sprintf(buf2, "What will you transform %s into", targname); sprintf(buf2, "What will you transform %s into", targname);
askstring(buf2, '?', buf, BUFLEN, NULL); askstring(buf2, '?', buf, BUFLEN, NULL);
} }
r = findracebyname(buf);
// make sure race is valid:
// - can't turn into monsters which aren't randomly generated.
// - can't turn into unique monsters
// - can't turn into undead monsters
if (r && !canpolymorphto(r->id)) r = NULL;
} else { // random
if (isplayer(target) && lfhasflag(target, F_CONTROL)) {
askstring("What will you become", '?', buf, BUFLEN, NULL);
r = findracebyname(buf); r = findracebyname(buf);
// make sure race is valid: // make sure race is valid:
// - can't turn into monsters which aren't randomly generated.
// - can't turn into unique monsters
// - can't turn into undead monsters
if (r && !canpolymorphto(r->id)) r = NULL; if (r && !canpolymorphto(r->id)) r = NULL;
} } else { // random
if (isplayer(target) && lfhasflag(target, F_CONTROL)) {
askstring("What will you become", '?', buf, BUFLEN, NULL);
r = findracebyname(buf);
if (!r) { // make sure race is valid:
// random race, but not the same! if (r && !canpolymorphto(r->id)) r = NULL;
r = target->race; }
while ((r == target->race) || !canpolymorphto(r->id)) {
r = getrandomrace(NULL, NA); if (!r) {
// random race, but not the same!
r = target->race;
while ((r == target->race) || !canpolymorphto(r->id)) {
r = getrandomrace(NULL, NA);
}
} }
} }
} } // end if forcepoly
if (r == target->race) { if (r == target->race) {
fizzle(caster); fizzle(caster);
@ -6984,9 +6989,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
f = hasflag(o->flags, F_DAM); f = hasflag(o->flags, F_DAM);
if (f) { if (f) {
char buf[BUFLEN]; char buf[BUFLEN];
free(f->text);
sprintf(buf, "2d%d",power); sprintf(buf, "2d%d",power);
f->text = strdup(buf); changeflagtext(f, buf);
} }
} else { } else {
killob(o); killob(o);

2
text.c
View File

@ -439,6 +439,8 @@ char *makeplural(char *text) {
if (rv) return newtext; if (rv) return newtext;
newtext = strrep(newtext, "chunk ", "chunks ", &rv); newtext = strrep(newtext, "chunk ", "chunks ", &rv);
if (rv) return newtext; if (rv) return newtext;
newtext = strrep(newtext, "clove ", "cloves ", &rv);
if (rv) return newtext;
newtext = strrep(newtext, "flask ", "flasks ", &rv); newtext = strrep(newtext, "flask ", "flasks ", &rv);
if (rv) return newtext; if (rv) return newtext;
newtext = strrep(newtext, "gem ", "gems ", &rv); newtext = strrep(newtext, "gem ", "gems ", &rv);