- [+] in shops, show 'ESC when done, ? to describe/purchase'

- [+]    b - a silver shoddy bastard sword
    - [+] show object's condition before changed material state?
- [+] bug: torches aren't lighting up walls when walking in corridor!
- [+] scrolls with f_scrollneedsob should say 'tried on object' 
- [+] dungeon light
    - [+] lit shoudl be "illuminated" and be an enum
        - [+] IL_FULLYLIT
        - [+] IL_WELLLIT (dark, candelabras in  every room and moss
              every 4 steps)
        - [+] IL_DIM (dark, torches in rooms and moss every 6 steps)
        - [+] IL_SHADOWY (dark, torches in some rooms and moss every 8
              steps)
        - [+] IL_FULLYDARK (ocassionally moss in rooms, otherwise no
              light at all)
    - [+] need more fixed light source objects:
        - [+] moonmoss and sunmoss
    - [+] if not fully lit, map illumination level determines how often
          light sources are placed, and what type.
- [+] special monster behaviour (perception or lore will show this?)
    - [+] insane monsters (attacks anything)
    - [+] hunting for food (hungry, add covets food)
    - [+] returning to lair with plunder (extra treasure)
    - [+] timid (lower morale, maybe add f_timid or alwaysflees)
    - [+] drugged (never flee)
    - [+] drunk
    - [+] diseased (start with a non-lethal disease. eating its corpse
          infects you)
    - [+] determined (will chase the player for longer)
    - [+] lazy (chase for less time)
    - [+] only show if perception >= skilled)
- [+] only show monster jobs if lorelev >= beginner
- [+] bug: cursed scrolls no longer having bad effects. fixed.
- [+] after you fool a monster by feigning death, it shouldn't target
      you for a while.
- [+] prevent wands from being blessed/cursed.
- [+] bug: still no displayed text when your pet dies.
    - [+] update: this seems to happen when a monster is killed by
          another monster
    - [+] The bear cub claws the dog.  The dog wakes up.
    - [+] fixed!
- [+] hwen monsters start with weapons/sheilds, their starting skill
      should be based on hit dice.
    - [+] max skill is hitdice / 3
- [+] wake up player before giving god gift!
- [+] "a goblin shaman moves out of view"
    - [+] but i didnt hav ehigh enough lore!
    - [+] maybe real_getlfname needs "showall".  check this istneda of
          usevis to see whether to show job.
- [+] crash when objects fall through a hole and the lower hole needed
      to be moved slightly.
- [+] bug: invisibility is fooling even things with 'enhancesmell'
- [+] water onto dirt only makes mud if there isn't some already there.
- [+] monk fists DR should max out at 12 or so, since #attacks keeps
      going up!
- [+] don't show god pleaseing messages when asleep
- [+] bug: showing '%s dodges" when you can't see it.
- [+] fix rarity of wands
- [+] reward at bottom of caves:
    - [+] godstone of war (cases RAGE on everyone near you)
Goblin cave bosses:
- [+] goblin king
- [+] young dragon
This commit is contained in:
Rob Pearce 2012-01-10 03:40:43 +00:00
parent 5c4fb99162
commit f7061b45ca
17 changed files with 543 additions and 273 deletions

46
ai.c
View File

@ -38,7 +38,7 @@ int aiattack(lifeform_t *lf, lifeform_t *victim, int timelimit) {
if (!canattack(lf)) { if (!canattack(lf)) {
dblog(".oO { canattack() is false }"); dblog(".oO { canattack() is false }");
return B_FALSE; return B_TRUE;
} }
// mindless? // mindless?
@ -65,12 +65,24 @@ int aiattack(lifeform_t *lf, lifeform_t *victim, int timelimit) {
// feigning death? // feigning death?
if (lfhasflag(victim, F_FEIGNINGDEATH)) { if (lfhasflag(victim, F_FEIGNINGDEATH)) {
if (!lfhasflagval(lf, F_ATTACHEDTO, victim->id, NA, NA, NULL)) { if (!lfhasflagval(lf, F_ATTACHEDTO, victim->id, NA, NA, NULL)) {
int penalty; int checkpassed;
penalty = (getcelldist(lf->cell, victim->cell)-1); flag_t *alreadyfooled = NULL;
if (penalty < 0) penalty = 0; alreadyfooled = lfhasflagval(lf, F_FEIGNFOOLEDBY, victim->id, NA, NA, NULL);
penalty *= 3; if (alreadyfooled) {
if (!skillcheckvs(lf, SC_IQ, -penalty, victim, SC_WILL, 5+gethitdice(victim))) { checkpassed = B_FALSE;
} else {
int penalty;
penalty = (getcelldist(lf->cell, victim->cell)-1);
if (penalty < 0) penalty = 0;
penalty *= 3;
checkpassed = skillcheckvs(lf, SC_IQ, -penalty, victim, SC_WILL, 5+gethitdice(victim));
}
if (!checkpassed) {
dblog(".oO { attempted target fooled me with feign death. ignoring. }"); dblog(".oO { attempted target fooled me with feign death. ignoring. }");
if (!alreadyfooled) {
addtempflag(lf->flags, F_FEIGNFOOLEDBY, victim->id, NA, NA, NULL, rnd(5,10));
}
return B_TRUE; return B_TRUE;
} }
} }
@ -95,7 +107,7 @@ int aiattack(lifeform_t *lf, lifeform_t *victim, int timelimit) {
if (areallies(player, lf) && cantalk(lf)) { if (areallies(player, lf) && cantalk(lf)) {
char text[BUFLEN]; char text[BUFLEN];
if (cansee(lf, victim)) { if (cansee(lf, victim)) {
real_getlfname(victim, text, B_FALSE); real_getlfname(victim, text, B_FALSE, B_FALSE);
} else { } else {
strcpy(text, "something"); strcpy(text, "something");
} }
@ -233,6 +245,14 @@ enum OBTYPE aigetfleespell(lifeform_t *lf) {
return OT_NONE; return OT_NONE;
} }
// how long with this monster chase you for?
int aigetchasetime(lifeform_t *lf) {
flag_t *f;
f = lfhasflag(lf, F_FOLLOWTIME);
if (f) return f->val[0];
return DEF_AIFOLLOWTIME;
}
// this function assumes that you can't just SEE the target! // this function assumes that you can't just SEE the target!
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) {
flag_t *f, *tflag, *bestflag = NULL; flag_t *f, *tflag, *bestflag = NULL;
@ -636,7 +656,7 @@ int ai_attack_existing_target(lifeform_t *lf) {
loseaitargets(lf); loseaitargets(lf);
if (areallies(lf, player) && cantalk(lf)) { if (areallies(lf, player) && cantalk(lf)) {
char text[BUFLEN]; char text[BUFLEN];
real_getlfname(target, text, B_FALSE); real_getlfname(target, text, B_FALSE, B_FALSE);
sayphrase(lf, SP_ALLY_TARGETKILL, SV_SHOUT, NA, text); sayphrase(lf, SP_ALLY_TARGETKILL, SV_SHOUT, NA, text);
} }
} else { } else {
@ -778,7 +798,7 @@ int ai_bored(lifeform_t *lf, lifeform_t *master, int icanattack) {
} }
if (newtarget) { if (newtarget) {
if (aiattack(lf, newtarget, DEF_AIFOLLOWTIME)) { if (aiattack(lf, newtarget, aigetchasetime(lf))) {
// failed for some reason. maybe target was feigning // failed for some reason. maybe target was feigning
// death? // death?
if (db) dblog(".oO { setting a new target via aiattack failed! }"); if (db) dblog(".oO { setting a new target via aiattack failed! }");
@ -1316,7 +1336,7 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) {
// reset F_TARGET lifetime to full. // reset F_TARGET lifetime to full.
if (targetflag) { if (targetflag) {
if (targetflag->id == F_TARGETLF) { if (targetflag->id == F_TARGETLF) {
targetflag->lifetime = DEF_AIFOLLOWTIME; targetflag->lifetime = aigetchasetime(lf);
} }
if (db) dblog(".oO { i can see my target (at %d,%d). might move towards it. }",target->cell->x,target->cell->y); if (db) dblog(".oO { i can see my target (at %d,%d). might move towards it. }",target->cell->x,target->cell->y);
// remember their location // remember their location
@ -1682,7 +1702,7 @@ void aimovetotargetcell(lifeform_t *lf, flag_t *f) {
if (db) dblog(".oO { successfully walked towards f_targetcell. arrived at %d,%d }",lf->cell->x, lf->cell->y); if (db) dblog(".oO { successfully walked towards f_targetcell. arrived at %d,%d }",lf->cell->x, lf->cell->y);
// moved towards it. // moved towards it.
// reset lifetime // reset lifetime
f->lifetime = DEF_AIFOLLOWTIME; f->lifetime = aigetchasetime(lf);
// are we there yet? // are we there yet?
if (lf->cell == c) { if (lf->cell == c) {
@ -1801,7 +1821,7 @@ void aiturn(lifeform_t *lf) {
if (db) { if (db) {
char lfname[BUFLEN]; char lfname[BUFLEN];
real_getlfname(lf, lfname, B_FALSE); real_getlfname(lf, lfname, B_FALSE, B_TRUE);
dblog("AIMOVE: %s, facing %s", lfname, getdirnameshort(lf->facing)); dblog("AIMOVE: %s, facing %s", lfname, getdirnameshort(lf->facing));
} }
@ -2565,7 +2585,7 @@ int lookforobs(lifeform_t *lf) {
} }
} }
// start walking towards target cell // start walking towards target cell
if (aigoto(lf, c, MR_OB, o, DEF_AIFOLLOWTIME)) { if (aigoto(lf, c, MR_OB, o, aigetchasetime(lf))) {
return B_FALSE; return B_FALSE;
} }
} }

1
ai.h
View File

@ -4,6 +4,7 @@ void addignorecell(lifeform_t *lf, cell_t *c);
int aiattack(lifeform_t *lf, lifeform_t *victim, int timelimit); 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);
int aigetchasetime(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, lifeform_t *target, enum RANGEATTACK *ra, int *range); object_t *aigetrangedattack(lifeform_t *lf, lifeform_t *target, enum RANGEATTACK *ra, int *range);
int aigetspelltarget(lifeform_t *lf, objecttype_t *spelltype, lifeform_t *victim, lifeform_t **spelllf, cell_t **spellcell, object_t **spellob, enum FLAG purpose); int aigetspelltarget(lifeform_t *lf, objecttype_t *spelltype, lifeform_t *victim, lifeform_t **spelllf, cell_t **spellcell, object_t **spellob, enum FLAG purpose);

View File

@ -958,7 +958,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
// we'll need to place the severed head object // we'll need to place the severed head object
addflag(victim->flags, F_BEHEADED, B_TRUE, NA, NA, NULL); addflag(victim->flags, F_BEHEADED, B_TRUE, NA, NA, NULL);
} }
if (cansee(player, victim) && !hasflag(victim->flags, F_NODEATHANNOUNCE)) { if ((isplayer(lf) || cansee(player, victim)) && !hasflag(victim->flags, F_NODEATHANNOUNCE)) {
// don't also say "the xx dies" // don't also say "the xx dies"
addflag(victim->flags, F_NODEATHANNOUNCE, B_TRUE, NA, NA, NULL); addflag(victim->flags, F_NODEATHANNOUNCE, B_TRUE, NA, NA, NULL);
} }
@ -985,7 +985,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
losehp_real(victim, victim->hp, DT_EXPLOSIVE, lf, "a quivering palm strike", B_FALSE, NULL, B_FALSE); losehp_real(victim, victim->hp, DT_EXPLOSIVE, lf, "a quivering palm strike", B_FALSE, NULL, B_FALSE);
} else { } else {
char attackername2[BUFLEN]; char attackername2[BUFLEN];
real_getlfname(lf, attackername2, B_FALSE); real_getlfname(lf, attackername2, B_FALSE, B_TRUE);
if (lf->race->raceclass->id == RC_GOD) { if (lf->race->raceclass->id == RC_GOD) {
flag_t *gf; flag_t *gf;
gf = lfhasflag(lf, F_GODOF); gf = lfhasflag(lf, F_GODOF);
@ -1055,7 +1055,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
int dam; int dam;
char lfname[BUFLEN]; char lfname[BUFLEN];
dam = rolldie(f->val[0], f->val[1]) + f->val[2]; dam = rolldie(f->val[0], f->val[1]) + f->val[2];
real_getlfname(lf, lfname, B_FALSE); real_getlfname(lf, lfname, B_FALSE, B_FALSE);
losehp_real(victim, dam, DT_BITE, lf, lfname, B_FALSE, NULL, B_FALSE); losehp_real(victim, dam, DT_BITE, lf, lfname, B_FALSE, NULL, B_FALSE);
if (isplayer(victim) || cansee(player, victim)) { if (isplayer(victim) || cansee(player, victim)) {
msg("^%c%s bites %s!", isplayer(victim) ? 'b' : 'n', lfname, victimname); msg("^%c%s bites %s!", isplayer(victim) ? 'b' : 'n', lfname, victimname);
@ -1195,7 +1195,9 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
adj = getrandomadjcell(victim->cell, WE_WALKABLE, B_NOEXPAND); adj = getrandomadjcell(victim->cell, WE_WALKABLE, B_NOEXPAND);
if (adj) { if (adj) {
flag_t *f; flag_t *f;
msg("^w%s dodge%s!",victimname,isplayer(victim) ? "" : "s"); if (isplayer(victim) || cansee(player, victim)) {
msg("^w%s dodge%s!",victimname,isplayer(victim) ? "" : "s");
}
f = addflag(victim->flags, F_NOTIME, B_TRUE, NA, NA, NULL); f = addflag(victim->flags, F_NOTIME, B_TRUE, NA, NA, NULL);
moveto(victim, adj, B_FALSE, B_FALSE); moveto(victim, adj, B_FALSE, B_FALSE);
killflag(f); killflag(f);
@ -2187,7 +2189,7 @@ void wepeffects(flagpile_t *fp, cell_t *where, flag_t *damflag, int dam) {
msg("^wA pulse of lethal power blasts %s!", vname); msg("^wA pulse of lethal power blasts %s!", vname);
f->known = B_KNOWN; f->known = B_KNOWN;
} }
real_getlfname(owner, ownername, B_FALSE); real_getlfname(owner, ownername, B_FALSE, B_TRUE);
getobname(wep, wepname, 1); getobname(wep, wepname, 1);
snprintf(damstring, BUFLEN, "%s%s %s",ownername, getpossessive(ownername), wepname); snprintf(damstring, BUFLEN, "%s%s %s",ownername, getpossessive(ownername), wepname);
losehp(victim, dam*3, DT_DIRECT, owner, damstring); losehp(victim, dam*3, DT_DIRECT, owner, damstring);
@ -2214,7 +2216,7 @@ void wepeffects(flagpile_t *fp, cell_t *where, flag_t *damflag, int dam) {
char damstring[BUFLEN]; char damstring[BUFLEN];
char victimname[BUFLEN]; char victimname[BUFLEN];
getlfname(owner, buf); getlfname(owner, buf);
real_getlfname(owner, buf2, B_FALSE); real_getlfname(owner, buf2, B_FALSE, B_FALSE);
getlfname(victim, victimname); getlfname(victim, victimname);
getobname(wep, obname, 1); getobname(wep, obname, 1);
@ -2251,9 +2253,11 @@ void wepeffects(flagpile_t *fp, cell_t *where, flag_t *damflag, int dam) {
// only works if we did damage // only works if we did damage
enum FLAG fid; enum FLAG fid;
int howlong; int howlong;
char *ftext;
flag_t *valflag = NULL; flag_t *valflag = NULL;
fid = f->val[0]; fid = f->val[0];
ftext = f->text;
// the f_poisoned flag stacks, others don't. // the f_poisoned flag stacks, others don't.
if (!lfhasflag(victim, fid) || (fid == F_POISONED)) { if (!lfhasflag(victim, fid) || (fid == F_POISONED)) {
int passedcheck = B_FALSE; int passedcheck = B_FALSE;
@ -2297,7 +2301,11 @@ void wepeffects(flagpile_t *fp, cell_t *where, flag_t *damflag, int dam) {
snprintf(frombuf, BUFLEN, "%s", wepname); snprintf(frombuf, BUFLEN, "%s", wepname);
} }
} else { } else {
strcpy(frombuf, "something unknown"); if (strlen(ftext)) {
strcpy(frombuf, ftext);
} else {
strcpy(frombuf, "something unknown");
}
} }

65
data.c
View File

@ -1188,6 +1188,7 @@ void initobjects(void) {
addoc(OC_WAND, "Wands", "A limited-use magical wand which casts the imbued spell.", '/', C_GREY, RR_VERYRARE); addoc(OC_WAND, "Wands", "A limited-use magical wand which casts the imbued spell.", '/', C_GREY, RR_VERYRARE);
addocnoun(lastobjectclass, "wand"); addocnoun(lastobjectclass, "wand");
addflag(lastobjectclass->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastobjectclass->flags, F_DTIMMUNE, DT_FIRE, NA, NA, NULL); addflag(lastobjectclass->flags, F_DTIMMUNE, DT_FIRE, NA, NA, NULL);
addflag(lastobjectclass->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL); addflag(lastobjectclass->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
addflag(lastobjectclass->flags, F_OPERABLE, B_TRUE, NA, NA, NULL); addflag(lastobjectclass->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
@ -1276,6 +1277,7 @@ void initobjects(void) {
addocnoun(lastobjectclass, "tome"); addocnoun(lastobjectclass, "tome");
addflag(lastobjectclass->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL); addflag(lastobjectclass->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
addflag(lastobjectclass->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastobjectclass->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastobjectclass->flags, F_RARITY, H_CAVE, RR_NEVER, NA, NULL); // override for habitat
addoc(OC_SPELL, "Spells", "A magical spell", '&', C_GREY, RR_NEVER); // this is a "virtual" object class addoc(OC_SPELL, "Spells", "A magical spell", '&', C_GREY, RR_NEVER); // this is a "virtual" object class
addoc(OC_ABILITY, "Abilities", "A special ability", '&', C_GREY, RR_NEVER); // this is a "virtual" object class addoc(OC_ABILITY, "Abilities", "A special ability", '&', C_GREY, RR_NEVER); // this is a "virtual" object class
@ -1406,6 +1408,7 @@ void initobjects(void) {
addflag(lastot->flags, F_DONTSHOWDEST, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DONTSHOWDEST, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_PIT, D_UP, NA, NA, NULL); addflag(lastot->flags, F_PIT, D_UP, NA, NA, NULL);
addflag(lastot->flags, F_OPPOSITESTAIRS, OT_HOLEINGROUND, NA, NA, NULL); addflag(lastot->flags, F_OPPOSITESTAIRS, OT_HOLEINGROUND, NA, NA, NULL);
addflag(lastot->flags, F_NOFEEL, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_ONEPERCELL, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_ONEPERCELL, B_TRUE, NA, NA, NULL);
@ -2345,10 +2348,12 @@ void initobjects(void) {
addot(OT_SCR_IDENTIFY, "scroll of identify", "Completely identifies any one item.", MT_PAPER, 0.5, OC_SCROLL, SZ_SMALL); addot(OT_SCR_IDENTIFY, "scroll of identify", "Completely identifies any one item.", MT_PAPER, 0.5, OC_SCROLL, SZ_SMALL);
addflag(lastot->flags, F_LINKSPELL, OT_S_IDENTIFY, NA, NA, NULL); addflag(lastot->flags, F_LINKSPELL, OT_S_IDENTIFY, NA, NA, NULL);
addflag(lastot->flags, F_SCROLLNEEDSOB, B_IFNOTBLESSED, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_FREQUENT, NULL); addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_FREQUENT, NULL);
addot(OT_SCR_MENDING, "scroll of mending", "Repairs damage to objects.", MT_PAPER, 0.5, OC_SCROLL, SZ_SMALL); addot(OT_SCR_MENDING, "scroll of mending", "Repairs damage to objects.", MT_PAPER, 0.5, OC_SCROLL, SZ_SMALL);
addflag(lastot->flags, F_LINKSPELL, OT_S_MENDING, NA, NA, NULL); addflag(lastot->flags, F_LINKSPELL, OT_S_MENDING, NA, NA, NULL);
addflag(lastot->flags, F_SCROLLNEEDSOB, B_IFNOTBLESSED, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 98, RR_COMMON, NULL); addflag(lastot->flags, F_RARITY, H_ALL, 98, RR_COMMON, NULL);
addflag(lastot->flags, F_MAXPOWER, 4, NA, NA, NULL); addflag(lastot->flags, F_MAXPOWER, 4, NA, NA, NULL);
@ -2401,6 +2406,7 @@ void initobjects(void) {
addot(OT_SCR_ENCHANT, "scroll of enhancement", "Magically enhances a weapon or piece of armour.", MT_PAPER, 0.5, OC_SCROLL, SZ_SMALL); addot(OT_SCR_ENCHANT, "scroll of enhancement", "Magically enhances a weapon or piece of armour.", MT_PAPER, 0.5, OC_SCROLL, SZ_SMALL);
addflag(lastot->flags, F_LINKSPELL, OT_S_ENCHANT, NA, NA, NULL); addflag(lastot->flags, F_LINKSPELL, OT_S_ENCHANT, NA, NA, NULL);
addflag(lastot->flags, F_SCROLLNEEDSOB, B_ALWAYS, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_RARE, NULL); addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_RARE, NULL);
addot(OT_SCR_FREEZEOB, "scroll of freezing touch", "Permenantly changes the next object touched into solid ice.", MT_PAPER, 0.5, OC_SCROLL, SZ_SMALL); addot(OT_SCR_FREEZEOB, "scroll of freezing touch", "Permenantly changes the next object touched into solid ice.", MT_PAPER, 0.5, OC_SCROLL, SZ_SMALL);
@ -2431,6 +2437,7 @@ void initobjects(void) {
addot(OT_SCR_REPLENISHMENT, "scroll of replenishment", "Restores a random amount of charges to a wand.", MT_PAPER, 0.5, OC_SCROLL, SZ_SMALL); addot(OT_SCR_REPLENISHMENT, "scroll of replenishment", "Restores a random amount of charges to a wand.", MT_PAPER, 0.5, OC_SCROLL, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_UNCOMMON, NULL); addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_SCROLLNEEDSOB, B_ALWAYS, NA, NA, NULL);
addflag(lastot->flags, F_LINKSPELL, OT_S_REPLENISH, NA, NA, NULL); addflag(lastot->flags, F_LINKSPELL, OT_S_REPLENISH, NA, NA, NULL);
@ -3923,86 +3930,86 @@ void initobjects(void) {
// wands // wands
addot(OT_WAND_CREATEFOOD, "wand of culinary abundance", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND, SZ_SMALL); addot(OT_WAND_CREATEFOOD, "wand of culinary abundance", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_UNCOMMON, NULL); addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_LINKSPELL, OT_S_CREATEFOOD, NA, NA, NULL); addflag(lastot->flags, F_LINKSPELL, OT_S_CREATEFOOD, NA, NA, NULL);
addflag(lastot->flags, F_OPERNEEDTARGET, TT_NONE, NA, NA, NULL); addflag(lastot->flags, F_OPERNEEDTARGET, TT_NONE, NA, NA, NULL);
addot(OT_WAND_KNOCK, "wand of opening", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND, SZ_SMALL); addot(OT_WAND_KNOCK, "wand of opening", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_ALL, 80, RR_UNCOMMON, NULL); addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_LINKSPELL, OT_S_KNOCK, NA, NA, NULL); addflag(lastot->flags, F_LINKSPELL, OT_S_KNOCK, NA, NA, NULL);
addflag(lastot->flags, F_OPERNEEDTARGET, TT_DOOR, NA, NA, NULL); addflag(lastot->flags, F_OPERNEEDTARGET, TT_DOOR, NA, NA, NULL);
addot(OT_WAND_LIGHT, "wand of light", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND, SZ_SMALL); addot(OT_WAND_LIGHT, "wand of light", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_ALL, 83, RR_UNCOMMON, NULL); addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_LINKSPELL, OT_S_LIGHT, 3, NA, NULL); addflag(lastot->flags, F_LINKSPELL, OT_S_LIGHT, 3, NA, NULL);
addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, TR_NEEDLOF, NA, NULL); addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, TR_NEEDLOF, NA, NULL);
addot(OT_WAND_NULLIFY, "wand of nullification", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND, SZ_SMALL); addot(OT_WAND_NULLIFY, "wand of nullification", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_ALL, 83, RR_RARE, NULL); addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_RARE, NULL);
addflag(lastot->flags, F_LINKSPELL, OT_S_NULLIFY, NA, NA, NULL); addflag(lastot->flags, F_LINKSPELL, OT_S_NULLIFY, NA, NA, NULL);
addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, TR_NEEDLOF, NA, NULL); addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, TR_NEEDLOF, NA, NULL);
addot(OT_WAND_REVEALHIDDEN, "wand of reveal hidden", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND, SZ_SMALL); addot(OT_WAND_REVEALHIDDEN, "wand of reveal hidden", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_ALL, 80, RR_UNCOMMON, NULL); addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_LINKSPELL, OT_S_REVEALHIDDEN, NA, NA, NULL); addflag(lastot->flags, F_LINKSPELL, OT_S_REVEALHIDDEN, NA, NA, NULL);
addot(OT_WAND_SLOW, "wand of slowness", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND, SZ_SMALL); addot(OT_WAND_SLOW, "wand of slowness", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_ALL, 80, RR_RARE, NULL); addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_RARE, NULL);
addflag(lastot->flags, F_LINKSPELL, OT_S_SLOW, NA, NA, NULL); addflag(lastot->flags, F_LINKSPELL, OT_S_SLOW, 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_DIGGING, "wand of digging", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND, SZ_SMALL); addot(OT_WAND_DIGGING, "wand of digging", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_ALL, 80, RR_RARE, NULL); addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_RARE, NULL);
addflag(lastot->flags, F_LINKSPELL, OT_S_DIG, NA, NA, NULL); addflag(lastot->flags, F_LINKSPELL, OT_S_DIG, NA, NA, NULL);
//addflag(lastot->flags, F_OPERNEEDTARGET, TT_NONE, NA, NA, NULL); //addflag(lastot->flags, F_OPERNEEDTARGET, TT_NONE, NA, NA, NULL);
addot(OT_WAND_COLD, "wand of cold", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND, SZ_SMALL); addot(OT_WAND_COLD, "wand of cold", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_ALL, 73, RR_RARE, NULL); addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_RARE, NULL);
addflag(lastot->flags, F_LINKSPELL, OT_S_COLDRAY, NA, NA, NULL); addflag(lastot->flags, F_LINKSPELL, OT_S_COLDRAY, 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_FIRE, "wand of fire", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND, SZ_SMALL); addot(OT_WAND_FIRE, "wand of fire", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_ALL, 73, RR_RARE, NULL); addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_RARE, NULL);
addflag(lastot->flags, F_LINKSPELL, OT_S_FIREDART, NA, NA, NULL); addflag(lastot->flags, F_LINKSPELL, OT_S_FIREDART, 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_HASTE, "wand of haste", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND, SZ_SMALL); addot(OT_WAND_HASTE, "wand of haste", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_ALL, 70, RR_RARE, NULL); addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_RARE, NULL);
addflag(lastot->flags, F_LINKSPELL, OT_S_HASTE, NA, NA, NULL); addflag(lastot->flags, F_LINKSPELL, OT_S_HASTE, 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_SELF, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL);
addot(OT_WAND_WEAKNESS, "wand of enfeeblement", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND, SZ_SMALL); addot(OT_WAND_WEAKNESS, "wand of enfeeblement", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_ALL, 70, RR_RARE, NULL); addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_RARE, NULL);
addflag(lastot->flags, F_LINKSPELL, OT_S_WEAKEN, NA, NA, NULL); addflag(lastot->flags, F_LINKSPELL, OT_S_WEAKEN, 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_WONDER, "wand of wonder", "Produces random effects.", MT_METAL, 0.5, OC_WAND, SZ_SMALL); addot(OT_WAND_WONDER, "wand of wonder", "Produces random effects.", MT_METAL, 0.5, OC_WAND, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_ALL, 70, RR_RARE, NULL); addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_RARE, NULL);
addflag(lastot->flags, F_OPERNEEDTARGET, TT_NONE, NA, NA, NULL); addflag(lastot->flags, F_OPERNEEDTARGET, TT_NONE, 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_INVIS, "wand of invisibility", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND, SZ_SMALL); addot(OT_WAND_INVIS, "wand of invisibility", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_ALL, 65, RR_RARE, NULL); addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_RARE, NULL);
addflag(lastot->flags, F_LINKSPELL, OT_S_INVISIBILITY, NA, NA, NULL); addflag(lastot->flags, F_LINKSPELL, OT_S_INVISIBILITY, 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_SELF, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL);
addot(OT_WAND_DISPERSAL, "wand of dispersal", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND, SZ_SMALL); addot(OT_WAND_DISPERSAL, "wand of dispersal", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_ALL, 65, RR_RARE, NULL); addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_RARE, NULL);
addflag(lastot->flags, F_LINKSPELL, OT_S_DISPERSAL, NA, NA, NULL); addflag(lastot->flags, F_LINKSPELL, OT_S_DISPERSAL, NA, NA, NULL);
addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER|TT_OBJECT, NA, NA, NULL); addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER|TT_OBJECT, 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_AIFLEEITEM, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_AIFLEEITEM, B_TRUE, NA, NA, NULL);
addot(OT_WAND_FIREBALL, "wand of fireball", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND, SZ_SMALL); addot(OT_WAND_FIREBALL, "wand of fireball", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_ALL, 65, RR_RARE, NULL); addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_RARE, NULL);
addflag(lastot->flags, F_LINKSPELL, OT_S_FIREBALL, NA, NA, NULL); addflag(lastot->flags, F_LINKSPELL, OT_S_FIREBALL, 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_DETONATION, "wand of detonation", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND, SZ_SMALL); addot(OT_WAND_DETONATION, "wand of detonation", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_ALL, 60, RR_RARE, NULL); addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_RARE, NULL);
addflag(lastot->flags, F_LINKSPELL, OT_S_DETONATE, NA, NA, NULL); addflag(lastot->flags, F_LINKSPELL, OT_S_DETONATE, NA, NA, NULL);
addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER|TT_DOOR, NA, NA, NULL); addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER|TT_DOOR, 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_WAND_POLYMORPH, "wand of polymorph", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND, SZ_SMALL); addot(OT_WAND_POLYMORPH, "wand of polymorph", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_ALL, 60, RR_RARE, NULL); addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_RARE, NULL);
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); 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_ALL, 72, RR_RARE, NULL); addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_RARE, NULL);
addflag(lastot->flags, F_LINKSPELL, OT_S_TURNUNDEAD, NA, NA, NULL); addflag(lastot->flags, F_LINKSPELL, OT_S_TURNUNDEAD, NA, NA, NULL);
addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, NA, NA, NULL); addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, NA, NA, NULL);
@ -4119,7 +4126,7 @@ void initobjects(void) {
addflag(lastot->flags, F_CHARGEOUTMSG, B_TRUE, NA, NA, "goes out"); addflag(lastot->flags, F_CHARGEOUTMSG, B_TRUE, NA, NA, "goes out");
addflag(lastot->flags, F_REPLENISHABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_REPLENISHABLE, B_TRUE, NA, NA, NULL);
addot(OT_LOCKPICK, "lockpick", "An angled piece of metal, used to open locks. Even those unskilled in lockpicking can attempt to use this item, although success in this case may be unlikely.", MT_METAL, 0.05, OC_TOOLS, SZ_TINY); addot(OT_LOCKPICK, "lockpick", "An angled piece of metal, used to open locks.", MT_METAL, 0.05, OC_TOOLS, SZ_TINY);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, NULL); addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, NULL);
addflag(lastot->flags, F_VALUE, 10, NA, NA, NULL); addflag(lastot->flags, F_VALUE, 10, NA, NA, NULL);
@ -4895,6 +4902,17 @@ void initobjects(void) {
addflag(lastot->flags, F_CHARGELOWMSG, B_TRUE, NA, NA, "flickers"); addflag(lastot->flags, F_CHARGELOWMSG, B_TRUE, NA, NA, "flickers");
addflag(lastot->flags, F_CHARGEOUTMSG, B_TRUE, NA, NA, "goes out"); addflag(lastot->flags, F_CHARGEOUTMSG, B_TRUE, NA, NA, "goes out");
addot(OT_MOSSMOON, "patch of moon moss", "A patch of faintly glowing white moss.", MT_PLANT, 0.1, OC_FLORA, SZ_MINI);
addflag(lastot->flags, F_GLYPH, C_WHITE, ',', NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL);
addflag(lastot->flags, F_RARITY, H_CAVE, NA, RR_COMMON, NULL);
addflag(lastot->flags, F_PRODUCESLIGHT, 2, NA, NA, NULL);
addot(OT_MOSSSUN, "patch of sun moss", "A patch of brightly glowing yellow moss.", MT_PLANT, 0.1, OC_FLORA, SZ_MINI);
addflag(lastot->flags, F_GLYPH, C_YELLOW, ',', NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_RARITY, H_CAVE, NA, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_PRODUCESLIGHT, 4, NA, NA, NULL);
addot(OT_COFFIN, "coffin", "A wooden coffin, made for holding the dead.", MT_WOOD, 100, OC_FURNITURE, SZ_HUMAN); addot(OT_COFFIN, "coffin", "A wooden coffin, made for holding the dead.", MT_WOOD, 100, OC_FURNITURE, SZ_HUMAN);
addflag(lastot->flags, F_RARITY, H_ALL, 75, RR_UNCOMMON, NULL); addflag(lastot->flags, F_RARITY, H_ALL, 75, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_GLYPH, C_GREY, '|', NA, NULL); addflag(lastot->flags, F_GLYPH, C_GREY, '|', NA, NULL);
@ -9221,7 +9239,6 @@ void initrace(void) {
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "2d4"); addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "2d4");
addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_DTIMMUNE, DT_BASH, NA, NA, NULL);
addrace(R_SAWGRASS, "sawgrass", 1, 'F', C_GREY, MT_METAL, RC_PLANT, "Razor sharp metallic grass with serrated edges. This plant senses vibrations in the air around it and lashes out with its sharp fronds."); addrace(R_SAWGRASS, "sawgrass", 1, 'F', C_GREY, MT_METAL, RC_PLANT, "Razor sharp metallic grass with serrated edges. This plant senses vibrations in the air around it and lashes out with its sharp fronds.");
addbodypart(lastrace, BP_BODY, "stalk"); addbodypart(lastrace, BP_BODY, "stalk");
@ -9240,7 +9257,6 @@ void initrace(void) {
addflag(lastrace->flags, F_MAXATTACKS, 1, 1, NA, NULL); addflag(lastrace->flags, F_MAXATTACKS, 1, 1, NA, NULL);
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_DTIMMUNE, DT_BASH, NA, NA, NULL);
// end plants // end plants
// animals // animals
@ -10686,7 +10702,7 @@ void initrace(void) {
addflag(lastrace->flags, F_MORALE, 0, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 0, NA, NA, NULL);
addflag(lastrace->flags, F_AWARENESS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_AWARENESS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_TIMID, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_TIMID, B_TRUE, NA, NA, NULL);
addrace(R_GIANTFLY, "giant fly", 1, 'i', C_GREY, MT_FLESH, RC_INSECT, "Giant flies buzz around the places, feeding on corpses. Usually no more than a nuisance."); addrace(R_GIANTFLY, "giant gnat", 1, 'i', C_GREY, MT_FLESH, RC_INSECT, "Giant gnats buzz around the places, feeding on corpses. Usually no more than a nuisance.");
setbodytype(lastrace, BT_BIRD); setbodytype(lastrace, BT_BIRD);
lastrace->baseid = R_GIANTFLY; lastrace->baseid = R_GIANTFLY;
addflag(lastrace->flags, F_INSECT, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_INSECT, B_TRUE, NA, NA, NULL);
@ -10716,14 +10732,14 @@ void initrace(void) {
addflag(lastrace->flags, F_AWARENESS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_AWARENESS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CARNIVORE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_CARNIVORE, B_TRUE, NA, NA, NULL);
addrace(R_GIANTBLOWFLY, "giant blowfly", 2, 'i', C_GREY, MT_FLESH, RC_INSECT, "Large, more solid versions of giant flies. These can actually cause damage, albeit rarely."); addrace(R_GIANTBLOWFLY, "giant urgnat", 2, 'i', C_GREY, MT_FLESH, RC_INSECT, "Large, more solid versions of giant gnats. These can actually cause damage, albeit rarely.");
setbodytype(lastrace, BT_BIRD); setbodytype(lastrace, BT_BIRD);
lastrace->baseid = R_GIANTFLY; lastrace->baseid = R_GIANTFLY;
addflag(lastrace->flags, F_INSECT, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_INSECT, 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_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL);
addflag(lastrace->flags, F_POISONCORPSE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_POISONCORPSE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "giant fly corpse"); addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "giant gnat corpse");
addflag(lastrace->flags, F_MOVESPEED, SP_VERYFAST, NA, NA, ""); addflag(lastrace->flags, F_MOVESPEED, SP_VERYFAST, NA, NA, "");
addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL);
addflag(lastrace->flags, F_FLYING, B_TRUE, NA, NA, ""); addflag(lastrace->flags, F_FLYING, B_TRUE, NA, NA, "");
@ -11304,6 +11320,7 @@ void initrace(void) {
addflag(r->flags, F_FLEEONHPPCT, 20, NA, NA, NULL); addflag(r->flags, F_FLEEONHPPCT, 20, NA, NA, NULL);
addflag(r->flags, F_RESISTMAG, 15, NA, NA, NULL); addflag(r->flags, F_RESISTMAG, 15, NA, NA, NULL);
addflag(r->flags, F_MEDITATES, B_TRUE, NA, NA, NULL); addflag(r->flags, F_MEDITATES, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SEEINDARK, 10, NA, NA, NULL);
} else if (r->raceclass->id == RC_MAGIC) { } else if (r->raceclass->id == RC_MAGIC) {
addflag(r->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL); addflag(r->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL);
} else if (r->raceclass->id == RC_PLANT) { } else if (r->raceclass->id == RC_PLANT) {

Binary file not shown.

23
defs.h
View File

@ -129,6 +129,8 @@
#define B_NOEXPAND (0) #define B_NOEXPAND (0)
#define B_IFACTIVATED (-1) #define B_IFACTIVATED (-1)
#define B_ALWAYS (-2)
#define B_IFNOTBLESSED (-3)
#define B_BIG (-1) #define B_BIG (-1)
@ -1158,6 +1160,8 @@ enum OBTYPE {
OT_FLOWER, OT_FLOWER,
OT_LEAF, OT_LEAF,
OT_MISTLETOE, OT_MISTLETOE,
OT_MOSSMOON,
OT_MOSSSUN,
OT_SHRUB, OT_SHRUB,
OT_STUMP, OT_STUMP,
OT_TREE, OT_TREE,
@ -2122,6 +2126,9 @@ enum FLAG {
F_FLASHONDEATH, // produce a bright flash when it dies,v0=range F_FLASHONDEATH, // produce a bright flash when it dies,v0=range
F_FLASHONDAM, // produces a bright flash when it is damaged,v0=range,v2=ifacctivated F_FLASHONDAM, // produces a bright flash when it is damaged,v0=range,v2=ifacctivated
F_LASTDAMTYPE, // object equivilant of lf->lastdamtype F_LASTDAMTYPE, // object equivilant of lf->lastdamtype
F_SCROLLNEEDSOB, // this scroll targets an object
// v0 = B_ALWAYS (always targets an ob)
// v0 = B_IFNOTBLESSED (only targets an ob if unblessed)
F_OPERONOFF, // operating this will just turn it on/off F_OPERONOFF, // operating this will just turn it on/off
F_OPERUSECHARGE, // operating this will use 1 charge F_OPERUSECHARGE, // operating this will use 1 charge
F_OPERNEEDTARGET, // need to ask for a target of type val0 when opering F_OPERNEEDTARGET, // need to ask for a target of type val0 when opering
@ -2406,6 +2413,10 @@ 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 / monster flags // lifeform flags / lf flags / monster flags
F_FOLLOWTIME, // v0 = how long will ai chase you for? defaults to
// DEF_AIFOLLOWTIME.
F_BEHAVIOUR, // textual field describing special behaviour for this
// lf
F_NOSMELL, // lf can't smell. not affected by stench, and F_NOSMELL, // lf can't smell. not affected by stench, and
// can't get enhancesmell. // can't get enhancesmell.
F_RESTINGINMOTEL, // sounds will not wake up this lf. monster won't F_RESTINGINMOTEL, // sounds will not wake up this lf. monster won't
@ -2627,6 +2638,8 @@ enum FLAG {
// from f_targetlf (ie. lf we are attacking) // from f_targetlf (ie. lf we are attacking)
F_FOLLOWRANGE, // v0/v1 = min/max celldist to stay away F_FOLLOWRANGE, // v0/v1 = min/max celldist to stay away
// from pet's master // from pet's master
F_FEIGNFOOLEDBY, // lf shouldn't attack lf id v0 because they
// are feigning death
F_TARGETLF, // lf will attack lfid v0. lastknown x/y is v1/v2 F_TARGETLF, // lf will attack lfid v0. lastknown x/y is v1/v2
// optional text is last known movement dir. // optional text is last known movement dir.
F_IGNORECELL, // won't accept targetcells of v0=x v1=y F_IGNORECELL, // won't accept targetcells of v0=x v1=y
@ -3353,11 +3366,19 @@ typedef struct room_s {
int exitslinked; // don't need to save this. int exitslinked; // don't need to save this.
} room_t; } room_t;
enum ILLUMINATION {
IL_FULLLIT, // all cells are light
IL_WELLLIT, // dark, candelabras in every room, moss every 4 steps
IL_DIM, // dark, torches in every room, moss every 6 steps
IL_SHADOWY, // dark, torches in some rooms, moss every 8 steps
IL_FULLDARK, // occasionally moss in rooms
};
typedef struct map_s { typedef struct map_s {
int id; int id;
region_t *region; region_t *region;
int depth; int depth;
int lit; enum ILLUMINATION illumination;
struct room_s room[MAXMAPROOMS]; struct room_s room[MAXMAPROOMS];
int nrooms; // how many rooms on this map int nrooms; // how many rooms on this map
char *name; // name of this map char *name; // name of this map

44
god.c
View File

@ -32,12 +32,10 @@ int ngodlfs = 0;
void angergod(enum RACE rid, int amt, enum GODANGERREASON why) { void angergod(enum RACE rid, int amt, enum GODANGERREASON why) {
lifeform_t *god; lifeform_t *god;
char lfname[BUFLEN];
int piety; int piety;
int dosay = B_FALSE; int dosay = B_FALSE;
god = findgod(rid); god = findgod(rid);
real_getlfname(god, lfname, B_FALSE);
modpiety(rid, -amt); modpiety(rid, -amt);
piety = getpiety(rid); piety = getpiety(rid);
@ -443,7 +441,7 @@ lifeform_t *godappears(enum RACE rid, cell_t *where) {
lifeform_t *god; lifeform_t *god;
char killedname[BUFLEN],godname[BUFLEN]; char killedname[BUFLEN],godname[BUFLEN];
god = findgod(rid); god = findgod(rid);
real_getlfname(god, godname, B_FALSE); real_getlfname(god, godname, B_FALSE, B_FALSE);
strcpy(killedname, ""); strcpy(killedname, "");
if (!where) { if (!where) {
// somewhere next to the player. // somewhere next to the player.
@ -496,6 +494,8 @@ int godgiftmaybe(enum RACE rid, int fromtemple) {
int rollagain = B_TRUE; int rollagain = B_TRUE;
gotgift = B_TRUE; gotgift = B_TRUE;
killflagsofid(player->flags, F_ASLEEP);
godsay(god->race->id, B_TRUE, "I bestow a gift upon you, mortal!"); godsay(god->race->id, B_TRUE, "I bestow a gift upon you, mortal!");
strcpy(obtogive, ""); strcpy(obtogive, "");
switch (god->race->id) { switch (god->race->id) {
@ -719,7 +719,7 @@ void godsay(enum RACE rid, int says, char *format, ...) {
va_end(args); va_end(args);
god = findgod(rid); god = findgod(rid);
real_getlfname(god, godname, B_FALSE); real_getlfname(god, godname, B_FALSE, B_FALSE);
if (says) { if (says) {
msg("%s%s voice booms out from the heavens:", godname, getpossessive(godname)); more(); msg("%s%s voice booms out from the heavens:", godname, getpossessive(godname)); more();
@ -742,28 +742,30 @@ void pleasegod(enum RACE rid, int amt) {
lifeform_t *lf; lifeform_t *lf;
char lfname[BUFLEN]; char lfname[BUFLEN];
lf = findgod(rid); lf = findgod(rid);
real_getlfname(lf, lfname, B_FALSE); real_getlfname(lf, lfname, B_FALSE, B_FALSE);
modpiety(rid, amt); modpiety(rid, amt);
// announce // announce
if (hasflag(lf->flags, F_PRAYEDTO)) { if (hasflag(lf->flags, F_PRAYEDTO)) {
switch (rid) { if (!isasleep(lf)) {
case R_GODDEATH: switch (rid) {
msg("You feel a thrill of unholy ecstasy."); case R_GODDEATH:
break; msg("You feel a thrill of unholy ecstasy.");
case R_GODMERCY: break;
msg("You feel a sense of peace."); case R_GODMERCY:
break; msg("You feel a sense of peace.");
case R_GODPURITY: break;
msg("You hear a distant choir singing."); case R_GODPURITY:
break; msg("You hear a distant choir singing.");
case R_GODTHIEVES: break;
msg("You feel a guilty pleasure."); case R_GODTHIEVES:
break; msg("You feel a guilty pleasure.");
default: break;
msg("You feel like %s approves of your actions.", lfname); default:
break; msg("You feel like %s approves of your actions.", lfname);
break;
}
} }
godgiftmaybe(rid, B_FALSE); godgiftmaybe(rid, B_FALSE);
} }

32
io.c
View File

@ -658,6 +658,8 @@ cell_t *askcoords(char *prompt, char *subprompt, int targettype, lifeform_t *src
flag_t *f; flag_t *f;
object_t *wep,*o; object_t *wep,*o;
char extrainfo[BIGBUFLEN]; char extrainfo[BIGBUFLEN];
enum SKILLLEVEL lorelev;
lorelev = getlorelevel(player, c->lf->race->raceclass->id);
strcpy(extrainfo, ""); strcpy(extrainfo, "");
getlfnamea(c->lf, buf); getlfnamea(c->lf, buf);
if (lfhasflag(c->lf, F_NAME)) { if (lfhasflag(c->lf, F_NAME)) {
@ -706,13 +708,7 @@ cell_t *askcoords(char *prompt, char *subprompt, int targettype, lifeform_t *src
break; break;
} }
// need a certain amount of iq to recognise drunkenness // obvious things
f = lfhasflag(c->lf, F_DRUNK);
if (f && (iqb >= AT_LTAVERAGE)) {
if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, getdrunktext(f));
}
if (isfleeing(c->lf)) { if (isfleeing(c->lf)) {
if (strlen(extrainfo)) strcat(extrainfo, ", "); if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, "fleeing"); strcat(extrainfo, "fleeing");
@ -779,8 +775,18 @@ cell_t *askcoords(char *prompt, char *subprompt, int targettype, lifeform_t *src
strcat(extrainfo, buf2); strcat(extrainfo, buf2);
} }
// need a certain amount of race knowledge to recognise ai traits
if (lorelev >= PR_SKILLED) {
f = lfhasflag(c->lf, F_BEHAVIOUR);
if (f) {
if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, f->text);
}
}
if ((getallegiance(c->lf) == AL_HOSTILE) && if ((getallegiance(c->lf) == AL_HOSTILE) &&
(getlorelevel(player, c->lf->race->raceclass->id) >= PR_ADEPT)) { (lorelev >= PR_ADEPT)) {
char dangerbuf[BUFLEN]; char dangerbuf[BUFLEN];
float rating; float rating;
rating = comparelfs(player, c->lf); rating = comparelfs(player, c->lf);
@ -2550,7 +2556,7 @@ lifeform_t *askgod(char *prompttext, int onlyprayed) {
continue; continue;
} }
real_getlfname(lf, buf, B_FALSE); real_getlfname(lf, buf, B_FALSE, B_FALSE);
f = hasflag(lf->flags, F_GODOF); f = hasflag(lf->flags, F_GODOF);
snprintf(godof, BUFLEN, " (%s of %s)", (f->val[0] == B_FEMALE) ? "goddess" : "god", f->text); snprintf(godof, BUFLEN, " (%s of %s)", (f->val[0] == B_FEMALE) ? "goddess" : "god", f->text);
strcat(buf, godof); strcat(buf, godof);
@ -3410,7 +3416,7 @@ void describegod(lifeform_t *god) {
assert(god); assert(god);
f = hasflag(god->flags, F_GODOF); f = hasflag(god->flags, F_GODOF);
real_getlfname(god, godname, B_FALSE); real_getlfname(god, godname, B_FALSE, B_FALSE);
snprintf(goddesc, BUFLEN, "(%s of %s)", (f->val[0] == B_FEMALE) ? "goddess" : "god", f->text); snprintf(goddesc, BUFLEN, "(%s of %s)", (f->val[0] == B_FEMALE) ? "goddess" : "god", f->text);
// title // title
@ -4269,7 +4275,7 @@ void docomms_areadangers(char *who, flagpile_t *fp, lifeform_t *lf) {
if (showit) { if (showit) {
char lfname[BUFLEN]; char lfname[BUFLEN];
real_getlfnamea(c->lf, lfname, B_FALSE); real_getlfnamea(c->lf, lfname, B_FALSE, B_TRUE);
msg("\"There is %s living nearby...\"", lfname); more(); msg("\"There is %s living nearby...\"", lfname); more();
ndone++; ndone++;
} }
@ -4697,7 +4703,7 @@ char *makedesc_god(lifeform_t *god, char *retbuf) {
int nretflags,i; int nretflags,i;
f = hasflag(god->flags, F_GODOF); f = hasflag(god->flags, F_GODOF);
real_getlfname(god, godname, B_FALSE); real_getlfname(god, godname, B_FALSE, B_FALSE);
strcpy(retbuf, ""); strcpy(retbuf, "");
@ -11789,7 +11795,7 @@ void showlfstats(lifeform_t *lf, int showall) {
enum COLOUR col; enum COLOUR col;
int piety,n; int piety,n;
god = godlf[i]; god = godlf[i];
real_getlfname(god, godname, B_FALSE); real_getlfname(god, godname, B_FALSE, B_FALSE);
f = lfhasflag(god, F_GODOF); f = lfhasflag(god, F_GODOF);
if (f->val[0] == B_FEMALE) { if (f->val[0] == B_FEMALE) {
strcat(godname, " (Goddess of "); strcat(godname, " (Goddess of ");

168
lf.c
View File

@ -1113,7 +1113,8 @@ int cansee_real(lifeform_t *viewer, lifeform_t *viewee, int uselos) {
flag_t *f; flag_t *f;
int xray = 0; int xray = 0;
int dist; int dist;
int tremordist; int tremordist,smelldist;
int invisible = B_FALSE;
if (gamemode < GM_GAMESTARTED) { if (gamemode < GM_GAMESTARTED) {
return B_TRUE; return B_TRUE;
@ -1130,7 +1131,7 @@ int cansee_real(lifeform_t *viewer, lifeform_t *viewee, int uselos) {
} }
dist = getcelldist(viewer->cell, viewee->cell); dist = getcelldist(viewer->cell, viewee->cell);
f = lfhasflag(viewer, F_TREMORSENSE); f = lfhasflag(viewer, F_TREMORSENSE);
if (f && !isairborne(viewee)) { if (f && !isairborne(viewee) && !isairborne(viewer)) {
if (f->val[0] > 0) { if (f->val[0] > 0) {
tremordist = f->val[0]; tremordist = f->val[0];
} else { } else {
@ -1140,6 +1141,17 @@ int cansee_real(lifeform_t *viewer, lifeform_t *viewee, int uselos) {
tremordist = -1; tremordist = -1;
} }
f = lfhasflag(viewer, F_ENHANCESMELL);
if (f) {
if (f->val[0] > 0) {
smelldist = f->val[0];
} else {
smelldist = dist;
}
} else {
smelldist = -1;
}
// viewer asleep? // viewer asleep?
if (lfhasflag(viewer, F_ASLEEP)) { if (lfhasflag(viewer, F_ASLEEP)) {
// can only 'see' yourself // can only 'see' yourself
@ -1163,24 +1175,29 @@ int cansee_real(lifeform_t *viewer, lifeform_t *viewee, int uselos) {
// viewee is invisible? // viewee is invisible?
if (lfhasflag(viewee, F_INVISIBLE)) { if (lfhasflag(viewee, F_INVISIBLE)) {
if (!lfhasflag(viewer, F_SEEINVIS) && (tremordist < dist)) { invisible = B_TRUE;
return B_FALSE;
}
} }
// cloak of shadows? // cloak of shadows?
o = getequippedob(viewee->pack, BP_SHOULDERS); o = getequippedob(viewee->pack, BP_SHOULDERS);
if (o && hasflagval(o->flags, F_HASBRAND, BR_SHADOWS, NA, NA, NULL)) { if (o && hasflagval(o->flags, F_HASBRAND, BR_SHADOWS, NA, NA, NULL)) {
if (!islit(viewee->cell)) { if (!islit(viewee->cell)) {
if (!lfhasflag(viewer, F_SEEINVIS) && (tremordist < dist)) { invisible = B_TRUE;
return B_FALSE;
}
} }
} }
// viewee hiding? // viewee hiding?
if (lfhasflag(viewee, F_HIDING) && (viewee != viewer)) { if (lfhasflag(viewee, F_HIDING) && (viewee != viewer)) {
if (!lfhasflagval(viewer, F_SPOTTED, viewee->id, NA, NA, NULL)) { if (!lfhasflagval(viewer, F_SPOTTED, viewee->id, NA, NA, NULL)) {
invisible = B_TRUE;
}
}
if (invisible) {
if (lfhasflag(viewer, F_SEEINVIS)) {
} else if ((dist <= tremordist)) {
} else if ((dist <= smelldist)) {
} else {
return B_FALSE; return B_FALSE;
} }
} }
@ -1496,11 +1513,14 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
int cost; int cost;
flag_t *f,*willflag = NULL; flag_t *f,*willflag = NULL;
int power; int power;
int spellblessed = B_UNCURSED;
objecttype_t *sp; objecttype_t *sp;
if (fromob) { if (fromob) {
spellblessed = fromob->blessed;
power = getobspellpower(fromob, lf); power = getobspellpower(fromob, lf);
} else { } else {
spellblessed = B_UNCURSED;
power = getspellpower(lf, sid); power = getspellpower(lf, sid);
// check whether we _can_ cast it. // check whether we _can_ cast it.
// do we have this spell/ability? // do we have this spell/ability?
@ -1712,7 +1732,7 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
} }
} }
// cast the spell // cast the spell. does it take time?
f = hasflag(sp->flags, F_CASTINGTIME); f = hasflag(sp->flags, F_CASTINGTIME);
if (f && !fromob) { if (f && !fromob) {
int castingtime; int castingtime;
@ -1753,7 +1773,7 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
} }
} else { // instant cast } else { // instant cast
addflag(lf->flags, F_CASTINGSPELL, sid, NA, NA, NULL); addflag(lf->flags, F_CASTINGSPELL, sid, NA, NA, NULL);
rv = dospelleffects(lf, sid, power, targlf, targob, targcell, B_UNCURSED, seen, B_FALSE); rv = dospelleffects(lf, sid, power, targlf, targob, targcell, spellblessed, seen, B_FALSE);
f = lfhasflag(lf, F_CASTINGSPELL); f = lfhasflag(lf, F_CASTINGSPELL);
if (f) { if (f) {
killflag(f); killflag(f);
@ -1764,11 +1784,13 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
if (!rv) { if (!rv) {
enum SPELLSCHOOL school; enum SPELLSCHOOL school;
school = getspellschoolknown(lf, sid); school = getspellschoolknown(lf, sid);
if (school != SS_NONE) { if (!fromob) {
enum SKILL skid; if (school != SS_NONE) {
skid = getschoolskill(school); enum SKILL skid;
if (skid != SK_NONE) { skid = getschoolskill(school);
practice(lf, skid, 1); if (skid != SK_NONE) {
practice(lf, skid, 1);
}
} }
} }
if (isplayer(lf)) { if (isplayer(lf)) {
@ -1798,7 +1820,7 @@ int celllitfor(lifeform_t *lf, cell_t *c, int maxvisrange, int nightvisrange) {
if (maxvisrange != UNLIMITED) { if (maxvisrange != UNLIMITED) {
if (dist > maxvisrange) { if (dist > maxvisrange) {
// if it's lit and within our non-ambient-adjusted visrange, it's still ok // if it's lit and within our non-ambient-adjusted visrange, it's still ok
if (islit(c) && (dist <= getvisrange(lf, B_FALSE))) return B_TRUE; if (islit(c) && (dist <= maxvisrange)) return B_TRUE;
else return B_FALSE; else return B_FALSE;
} }
} }
@ -3515,7 +3537,7 @@ void endlfturn(lifeform_t *lf) {
if (ispetof(lf, player)) { if (ispetof(lf, player)) {
if (!canhear(player, lf->cell, 4)) { if (!canhear(player, lf->cell, 4)) {
char realname[BUFLEN]; char realname[BUFLEN];
real_getlfname(lf, realname, B_FALSE); real_getlfname(lf, realname, B_FALSE, B_FALSE);
warn("You feel worried about %s%s.", lfhasflag(lf, F_NAME) ? "" : "your ", noprefix(realname)); warn("You feel worried about %s%s.", lfhasflag(lf, F_NAME) ? "" : "your ", noprefix(realname));
} else if (cantalk(lf)) { } else if (cantalk(lf)) {
sayphrase(lf, SP_ALLY_INPAIN, SV_SHOUT, NA, NULL); sayphrase(lf, SP_ALLY_INPAIN, SV_SHOUT, NA, NULL);
@ -3871,6 +3893,7 @@ void enhanceskills(lifeform_t *lf) {
if (f) { if (f) {
int newdr; int newdr;
newdr = lf->level+2; newdr = lf->level+2;
limit(&newdr, NA, 12);
if (newdr <= f->val[1]) { if (newdr <= f->val[1]) {
// do nothing - your unarmed attack was already stronger or // do nothing - your unarmed attack was already stronger or
// equivilant. // equivilant.
@ -4075,6 +4098,12 @@ void fightback(lifeform_t *lf, lifeform_t *attacker) {
// wake up // wake up
killflagsofid(lf->flags, F_ASLEEP); killflagsofid(lf->flags, F_ASLEEP);
} }
f = lfhasflagval(lf, F_FEIGNFOOLEDBY, attacker->id, NA, NA, NULL);
if (f) {
killflag(f);
}
// monsters might flee, fight back, etc // monsters might flee, fight back, etc
if (!isplayer(lf)) { if (!isplayer(lf)) {
if (isplayer(attacker) && ishirable(lf)) { if (isplayer(attacker) && ishirable(lf)) {
@ -4101,7 +4130,7 @@ void fightback(lifeform_t *lf, lifeform_t *attacker) {
if (isadjacent(lf->cell, attacker->cell)) { if (isadjacent(lf->cell, attacker->cell)) {
turntoface(lf, attacker->cell); turntoface(lf, attacker->cell);
} }
aiattack(lf, attacker, DEF_AIFOLLOWTIME); aiattack(lf, attacker, aigetchasetime(lf));
} }
// any nearby monsters which will help out? // any nearby monsters which will help out?
@ -4109,7 +4138,7 @@ void fightback(lifeform_t *lf, lifeform_t *attacker) {
for (l = lf->cell->map->lf ; l ; l = l->next) { for (l = lf->cell->map->lf ; l ; l = l->next) {
if (!isdead(l) && areallies(l,lf)) { if (!isdead(l) && areallies(l,lf)) {
if (cansee(l, attacker)) { if (cansee(l, attacker)) {
aiattack(l, attacker, DEF_AIFOLLOWTIME); aiattack(l, attacker, aigetchasetime(l));
} }
} }
} }
@ -4288,7 +4317,7 @@ int flee(lifeform_t *lf) {
if (lfhasflag(lf, F_DEBUG)) db = B_TRUE; if (lfhasflag(lf, F_DEBUG)) db = B_TRUE;
real_getlfname(lf, lfname, B_FALSE); real_getlfname(lf, lfname, B_FALSE, B_FALSE);
// are we fleeing? // are we fleeing?
getflags(lf->flags, retflag, &nretflags, F_FLEEFROM, F_NONE); getflags(lf->flags, retflag, &nretflags, F_FLEEFROM, F_NONE);
@ -6991,10 +7020,10 @@ char *getpitverb(lifeform_t *lf, int dir, int onpurpose, int climb) {
} }
char *getlfname(lifeform_t *lf, char *buf) { char *getlfname(lifeform_t *lf, char *buf) {
return real_getlfname(lf, buf, B_TRUE); return real_getlfname(lf, buf, B_TRUE, B_FALSE);
} }
char *real_getlfname(lifeform_t *lf, char *buf, int usevis) { char *real_getlfname(lifeform_t *lf, char *buf, int usevis, int showall) {
char descstring[BUFLEN]; char descstring[BUFLEN];
char jobstring[BUFLEN]; char jobstring[BUFLEN];
char the[6]; char the[6];
@ -7031,11 +7060,13 @@ char *real_getlfname(lifeform_t *lf, char *buf, int usevis) {
// construct job string // construct job string
strcpy(jobstring, ""); strcpy(jobstring, "");
if (!lfhasflag(lf, F_NOJOBTEXT) && !lfhasflag(lf, F_NAME) && !lfhasflag(lf, F_UNIQUE)) { if (showall || isplayer(lf) || (getlorelevel(player, lf->race->raceclass->id) >= PR_BEGINNER)) {
j = getjob(lf); if (!lfhasflag(lf, F_NOJOBTEXT) && !lfhasflag(lf, F_NAME) && !lfhasflag(lf, F_UNIQUE)) {
if (j) { j = getjob(lf);
snprintf(jobstring, BUFLEN, " %s", j->name); if (j) {
jobstring[1] = tolower(jobstring[1]); snprintf(jobstring, BUFLEN, " %s", j->name);
jobstring[1] = tolower(jobstring[1]);
}
} }
} }
@ -7043,7 +7074,7 @@ char *real_getlfname(lifeform_t *lf, char *buf, int usevis) {
snprintf(buf, BUFLEN, "you"); snprintf(buf, BUFLEN, "you");
} else { } else {
//if (isblind(player)) { //if (isblind(player)) {
if (usevis && !cansee(player, lf)) { if (usevis && !cansee(player, lf) && !showall) {
snprintf(buf, BUFLEN, "something"); snprintf(buf, BUFLEN, "something");
} else { } else {
if (lf->race->id == R_DANCINGWEAPON) { if (lf->race->id == R_DANCINGWEAPON) {
@ -7083,17 +7114,17 @@ char *real_getlfname(lifeform_t *lf, char *buf, int usevis) {
} }
char *getlfnamea(lifeform_t *lf, char *buf) { char *getlfnamea(lifeform_t *lf, char *buf) {
return real_getlfnamea(lf, buf, B_TRUE); return real_getlfnamea(lf, buf, B_TRUE, B_FALSE);
} }
char *real_getlfnamea(lifeform_t *lf, char *buf, int usevis) { char *real_getlfnamea(lifeform_t *lf, char *buf, int usevis, int showall) {
if (isplayer(lf)) { if (isplayer(lf)) {
snprintf(buf, BUFLEN, "you"); snprintf(buf, BUFLEN, "you");
} else { } else {
char buf2[BUFLEN]; char buf2[BUFLEN];
char the[6]; char the[6];
real_getlfname(lf, buf2, usevis); real_getlfname(lf, buf2, usevis, showall);
if (lfhasflag(lf, F_NAME) || lfhasflag(lf, F_UNIQUE)) { if (lfhasflag(lf, F_NAME) || lfhasflag(lf, F_UNIQUE)) {
strcpy(the, ""); strcpy(the, "");
@ -7857,7 +7888,7 @@ char *getspeednameshort(int speed, char *buf) {
long getspforpoint(lifeform_t *lf) { long getspforpoint(lifeform_t *lf) {
float mod; float mod;
long amtneeded; float amtneeded;
amtneeded = SKILLXPPERPOINT; amtneeded = SKILLXPPERPOINT;
amtneeded += (50 * lf->totskillpoints); amtneeded += (50 * lf->totskillpoints);
mod = MAXOF(getstatmod(lf, A_IQ), getstatmod(lf, A_WIS)); mod = MAXOF(getstatmod(lf, A_IQ), getstatmod(lf, A_WIS));
@ -8590,6 +8621,29 @@ void giveobflags(lifeform_t *lf, object_t *o, enum FLAG whattype) {
} }
} }
int giverandomobs(lifeform_t *lf, int amt) {
char buf[BUFLEN];
int i,ngiven = 0;
if (!lfhasflag(lf, F_HUMANOID) || lfhasflag(lf, F_NOPACK)) {
return 0;
}
for (i = 0; i < amt; i++) {
if (getrandomob(lf->cell->map, buf)) {
object_t *o;
o = addob(lf->pack, buf);
if (o) {
if (!canpickup(lf, o, o->amt)) {
killob(o);
} else {
ngiven++;
}
}
}
}
return ngiven;
}
flag_t *giveskill(lifeform_t *lf, enum SKILL id) { flag_t *giveskill(lifeform_t *lf, enum SKILL id) {
flag_t *f = NULL, *newf; flag_t *f = NULL, *newf;
@ -10199,6 +10253,12 @@ int haslos(lifeform_t *viewer, cell_t *dest) {
assert(viewer->los || (viewer->nlos == 0)); assert(viewer->los || (viewer->nlos == 0));
/*
if (haslos_fast(viewer, dest)) {
return B_TRUE;
}
return haslosdark(viewer, dest);
*/
return haslos_fast(viewer, dest); return haslos_fast(viewer, dest);
/* /*
// THIS CODE IS NO LONGER EVER USED // THIS CODE IS NO LONGER EVER USED
@ -11351,6 +11411,9 @@ void makepeaceful(lifeform_t *who) {
addflag(who->flags, F_XPVAL, 0, NA, NA, NULL); addflag(who->flags, F_XPVAL, 0, NA, NA, NULL);
killflagsofid(who->flags, F_HOSTILE); killflagsofid(who->flags, F_HOSTILE);
killflagsofid(who->flags, F_HATESALL);
killflagsofid(who->flags, F_HATESRACE);
killflagsofid(who->flags, F_HATESRACEWITHFLAG);
loseaitargets(who); loseaitargets(who);
} }
@ -11760,7 +11823,10 @@ void autoskill(lifeform_t *lf) {
if (isplayer(lf)) { if (isplayer(lf)) {
slev = PR_NOVICE; slev = PR_NOVICE;
} else { } else {
slev = PR_ADEPT; int max;
max = gethitdice(lf)/3;
limit(&max, PR_NOVICE, PR_MASTER);
slev = rnd(PR_NOVICE, max);
} }
for (o = lf->pack->first ; o ; o = o->next) { for (o = lf->pack->first ; o ; o = o->next) {
@ -13220,7 +13286,7 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nclass, int volume,
char distbuf[BUFLEN],distbufbad[BUFLEN]; char distbuf[BUFLEN],distbufbad[BUFLEN];
char dirbuf[BUFLEN]; char dirbuf[BUFLEN];
real_getlfnamea(noisemaker, lfname, B_FALSE); real_getlfnamea(noisemaker, lfname, B_FALSE, B_FALSE);
getdisttext(l->cell, c, distbuf, distbufbad, dirbuf); getdisttext(l->cell, c, distbuf, distbufbad, dirbuf);
slev = getskill(l, SK_LISTEN); slev = getskill(l, SK_LISTEN);
@ -15958,7 +16024,7 @@ void startlfturn(lifeform_t *lf) {
if (isplayer(lf)) { if (isplayer(lf)) {
if (f->val[2] >= 5) { if (f->val[2] >= 5) {
char buf[BUFLEN]; char buf[BUFLEN];
real_getlfnamea(retcell[i]->lf, buf, B_FALSE); real_getlfnamea(retcell[i]->lf, buf, B_FALSE, B_FALSE);
warn("^WYour sixth sense warns you of %s %s you!", buf, warn("^WYour sixth sense warns you of %s %s you!", buf,
(reldir == RD_BACKWARDS) ? "behind" : "beside" ); (reldir == RD_BACKWARDS) ? "behind" : "beside" );
} else if (f->val[2] >= 3) { } else if (f->val[2] >= 3) {
@ -16492,7 +16558,7 @@ void startlfturn(lifeform_t *lf) {
// effects for/on your own flags // effects for/on your own flags
getflags(lf->flags, retflag, &nretflags, F_ATTACHEDTO, F_CANWILL, F_CHARMEDBY, F_CLIMBING, F_FLEEFROM, getflags(lf->flags, retflag, &nretflags, F_ATTACHEDTO, F_CANWILL, F_CHARMEDBY, F_CLIMBING, F_FEIGNFOOLEDBY,F_FLEEFROM,
F_GRABBEDBY, F_GRABBING, F_GUNTARGET, F_BOOSTSPELL, F_FEIGNINGDEATH, F_INJURY, F_GRABBEDBY, F_GRABBING, F_GUNTARGET, F_BOOSTSPELL, F_FEIGNINGDEATH, F_INJURY,
F_NOFLEEFROM, F_PETOF, F_SPOTTED, F_STABBEDBY, F_TARGETCELL, F_TARGETLF, F_NONE); F_NOFLEEFROM, F_PETOF, F_SPOTTED, F_STABBEDBY, F_TARGETCELL, F_TARGETLF, F_NONE);
for (i = 0; i < nretflags; i++) { for (i = 0; i < nretflags; i++) {
@ -16573,6 +16639,14 @@ void startlfturn(lifeform_t *lf) {
if (f->id == F_CLIMBING) { if (f->id == F_CLIMBING) {
if (!lf->cell->type->solid) { if (!lf->cell->type->solid) {
killflag(f); killflag(f);
continue;
}
}
if (f->id == F_FEIGNFOOLEDBY) {
if (!findlf(lf->cell->map, f->val[0])) {
killflag(f);
continue;
} }
} }
@ -16608,16 +16682,18 @@ void startlfturn(lifeform_t *lf) {
targ = c->lf; targ = c->lf;
} }
} }
if (targ && areallies(lf, targ)) { if (targ) {
if (lfhasflag(lf, F_DEBUG)) { if (areallies(lf, targ) || lfhasflagval(lf, F_FEIGNFOOLEDBY, targ->id, NA, NA, NULL)) {
char lfname[BUFLEN]; if (lfhasflag(lf, F_DEBUG)) {
char targname[BUFLEN]; char lfname[BUFLEN];
getlfname(lf, lfname); char targname[BUFLEN];
getlfname(targ, targname); getlfname(lf, lfname);
//msg("db: %s no longer targetting %s.",lfname,targname); getlfname(targ, targname);
dblog("db: %s no longer targetting %s.",lfname,targname);
}
killflag(f);
continue;
} }
killflag(f);
continue;
} }
} // end if f_target or f_targetcell } // end if f_target or f_targetcell
} // end loop through lf flags } // end loop through lf flags
@ -17654,7 +17730,7 @@ int usestairs(lifeform_t *lf, object_t *o, int onpurpose, int climb) {
for (n = 0; n < nadjallies; n++) { for (n = 0; n < nadjallies; n++) {
if (seen[n]) { if (seen[n]) {
char lname[BUFLEN]; char lname[BUFLEN];
real_getlfname(adjally[n], lname, B_FALSE); real_getlfname(adjally[n], lname, B_FALSE, B_FALSE);
msg("%s follows you.", lname); msg("%s follows you.", lname);
} }
} }

5
lf.h
View File

@ -197,9 +197,9 @@ char *getmoveverbother(lifeform_t *lf);
lifeform_t *getnearbypeaceful(lifeform_t *lf); lifeform_t *getnearbypeaceful(lifeform_t *lf);
char *getpitverb(lifeform_t *lf, int dir, int onpurpose, int climb); char *getpitverb(lifeform_t *lf, int dir, int onpurpose, int climb);
char *getlfname(lifeform_t *lf, char *buf); char *getlfname(lifeform_t *lf, char *buf);
char *real_getlfname(lifeform_t *lf, char *buf, int usevis); char *real_getlfname(lifeform_t *lf, char *buf, int usevis, int showall);
char *getlfnamea(lifeform_t *lf, char *buf); char *getlfnamea(lifeform_t *lf, char *buf);
char *real_getlfnamea(lifeform_t *lf, char *buf, int usevis); char *real_getlfnamea(lifeform_t *lf, char *buf, int usevis, int showall);
enum LFSIZE getlfsize(lifeform_t *lf); enum LFSIZE getlfsize(lifeform_t *lf);
float getlfweight(lifeform_t *lf, int withobs); float getlfweight(lifeform_t *lf, int withobs);
object_t *getsecmeleeweapon(lifeform_t *lf); object_t *getsecmeleeweapon(lifeform_t *lf);
@ -247,6 +247,7 @@ long getxpforlev(int level);
void givejob(lifeform_t *lf, enum JOB jobid); void givejob(lifeform_t *lf, enum JOB jobid);
int givemoney(lifeform_t *from, lifeform_t *to, int amt); int givemoney(lifeform_t *from, lifeform_t *to, int amt);
void giveobflags(lifeform_t *lf, object_t *o, enum FLAG whattype); void giveobflags(lifeform_t *lf, object_t *o, enum FLAG whattype);
int giverandomobs(lifeform_t *lf, int amt);
flag_t *giveskill(lifeform_t *lf, enum SKILL id); flag_t *giveskill(lifeform_t *lf, enum SKILL id);
flag_t *giveskilllev(lifeform_t *lf, enum SKILL id, enum SKILLLEVEL slev); flag_t *giveskilllev(lifeform_t *lf, enum SKILL id, enum SKILLLEVEL slev);
void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp); void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp);

218
map.c
View File

@ -173,7 +173,7 @@ map_t *addmap(void) {
} }
a->flags = addflagpile(NULL, NULL); a->flags = addflagpile(NULL, NULL);
a->beingcreated = B_TRUE; a->beingcreated = B_TRUE;
a->lit = B_TRUE; a->illumination = IL_FULLLIT;
a->habitat = findhabitat(H_DUNGEON); // default!!! a->habitat = findhabitat(H_DUNGEON); // default!!!
a->lastplayervisit = -1; a->lastplayervisit = -1;
a->nfixedrooms = 0; a->nfixedrooms = 0;
@ -314,12 +314,8 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int jobok, int
} }
} }
} }
// nonhuman monsters who on dark levels can always see in the dark finalisemonster(lf, NULL, wantflags);
if (!lf->cell->map->lit && !lfhasflag(lf, F_SEEINDARK)) { lf->born = B_TRUE;
if (getraceclass(lf) != RC_HUMANOID) {
addflag(lf->flags, F_SEEINDARK, rnd(3,5), NA, NA, NULL);
}
}
} }
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging //if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
@ -351,23 +347,13 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int jobok, int
if (nadded) (*nadded)++; if (nadded) (*nadded)++;
newlf->born = B_FALSE; newlf->born = B_FALSE;
// initial monster shoudl remember its minions
addflag(lf->flags, F_MINION, newlf->id, NA, NA, NULL);
// if master is asleep, minions will also be asleep finalisemonster(newlf, lf, wantflags);
if (lfhasflag(lf, F_ASLEEP) || (wantflags && hasflag(wantflags, F_ASLEEP))) {
addflag(newlf->flags, F_ASLEEP, NA, ST_ASLEEP, NA, NULL);
}
if (!newlf->cell->map->lit && !lfhasflag(newlf, F_SEEINDARK)) {
if (getraceclass(newlf) != RC_HUMANOID) {
addflag(newlf->flags, F_SEEINDARK, rnd(3,5), NA, NA, NULL);
}
}
// minions never have certain flags.
killflagsofid(newlf->flags, F_DEMANDSBRIBE);
newlf->born = B_TRUE; newlf->born = B_TRUE;
// initial monster should remember its minions
addflag(lf->flags, F_MINION, newlf->id, NA, NA, NULL);
} }
} }
} }
@ -401,16 +387,8 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int jobok, int
if (nadded) (*nadded)++; if (nadded) (*nadded)++;
newlf->born = B_FALSE; finalisemonster(newlf, lf, wantflags);
if (lfhasflag(lf, F_ASLEEP) || (wantflags && hasflag(wantflags, F_ASLEEP))) {
addflag(newlf->flags, F_ASLEEP, NA, ST_ASLEEP, NA, NULL);
}
if (!newlf->cell->map->lit && !lfhasflag(newlf, F_SEEINDARK)) {
if (getraceclass(newlf) != RC_HUMANOID) {
addflag(newlf->flags, F_SEEINDARK, rnd(3,5), NA, NA, NULL);
}
}
newlf->born = B_TRUE; newlf->born = B_TRUE;
} }
} }
@ -422,22 +400,13 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int jobok, int
if (db) dbtime("handling random objects"); if (db) dbtime("handling random objects");
// sometimes give the lf random objects (extra monsters through // sometimes give the lf random objects (extra monsters through
// 'numappears' don't get them). // 'numappears' don't get them).
if (lfhasflag(lf, F_HUMANOID) && !lfhasflag(lf, F_NOPACK)) { if (onein(3)) {
if (rnd(1,3) == 1) { giverandomobs(lf, rnd(1,3));
int nobs = rnd(1,3); while (onein(3)) {
char buf[BUFLEN]; giverandomobs(lf, 1);
int i; }
for (i = 0; i < nobs; i++) {
if (getrandomob(c->map, buf)) {
object_t *o;
o = addob(lf->pack, buf);
if (o && !canpickup(lf, o, o->amt)) {
killob(o);
}
}
}
}
} }
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging //if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
if (db) dbtime("giving torches"); if (db) dbtime("giving torches");
@ -468,13 +437,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int jobok, int
} }
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging //if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
if (wantflags) {
// wantflags?
copyflags(lf->flags, wantflags, NA);
}
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging //if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
lf->born = B_TRUE;
} // end if lf } // end if lf
} }
@ -1308,7 +1271,11 @@ int fix_reachability(map_t *m) {
if (db) dblog(" found unreachable area at %d,%d. will fix it.", if (db) dblog(" found unreachable area at %d,%d. will fix it.",
m->cell[i]->x, m->cell[i]->y); m->cell[i]->x, m->cell[i]->y);
linkexit(m->cell[i], B_TRUE, &nadded); if (linkexit(m->cell[i], B_TRUE, &nadded)) {
// failed!
if (db) dblog(" fix_reachability failed - couldn't fix an unreachable area.");
return B_TRUE;
}
if (nadded) { if (nadded) {
if (db) dblog(" fixed unreachable area by adding %d cells.", nadded); if (db) dblog(" fixed unreachable area by adding %d cells.", nadded);
@ -1617,7 +1584,7 @@ void calclight(map_t *map) {
} }
} else { } else {
//if ((map->depth <= 5) && (c->lit != L_PERMDARK)) { //if ((map->depth <= 5) && (c->lit != L_PERMDARK)) {
if (map->lit && (c->lit != L_PERMDARK)) { if ((map->illumination == IL_FULLLIT) && (c->lit != L_PERMDARK)) {
makelit(c, L_PERMLIGHT, -1); makelit(c, L_PERMLIGHT, -1);
} }
} }
@ -1991,14 +1958,14 @@ void createcave(map_t *map, int depth, map_t *parentmap, int exitdir, object_t *
// is the map lit? // is the map lit?
if (depth == 1) { if (depth == 1) {
map->lit = B_TRUE; map->illumination = IL_FULLLIT;
} else { } else {
int darkchance; int darkchance;
darkchance = depth*15; // ie. level 2 = 30% chance of being dark, level 6 = 90% chance darkchance = depth*15; // ie. level 2 = 30% chance of being dark, level 6 = 90% chance
if (pctchance(darkchance)) { if (pctchance(darkchance)) {
map->lit = B_FALSE; map->illumination = IL_FULLDARK;
} else { } else {
map->lit = B_TRUE; map->illumination = IL_FULLLIT;
} }
} }
@ -2222,14 +2189,14 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
// is the map lit? // is the map lit?
if (depth <= 5) { if (depth <= 5) {
map->lit = B_TRUE; map->illumination = IL_FULLLIT;
} else { } else {
int chance; int chance;
chance = (depth - 5) * 10; chance = (depth - 5) * 10;
if (pctchance(chance)) { if (pctchance(chance)) {
map->lit = B_FALSE; map->illumination = rnd(IL_WELLLIT,IL_FULLDARK);
} else { } else {
map->lit = B_TRUE; map->illumination = IL_FULLLIT;
} }
} }
@ -4148,11 +4115,13 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
} else { } else {
if (db) dblog(" Cannot find a way to link up."); if (db) dblog(" Cannot find a way to link up.");
// debugging - a failure here during fix_reachability is fatal. // debugging - a failure here during fix_reachability is fatal.
/*
if (wantfilled) { if (wantfilled) {
assert(0 == 1); assert(0 == 1);
} }
*/
return B_TRUE;
} }
return B_TRUE;
} }
} else { // we found a way to go without needing to turn. } else { // we found a way to go without needing to turn.
int whichway,sel; int whichway,sel;
@ -4190,7 +4159,6 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
setcelltype(startcell, startcell->habitat->emptycelltype); setcelltype(startcell, startcell->habitat->emptycelltype);
} }
return B_FALSE; return B_FALSE;
} }
@ -4745,6 +4713,9 @@ void finalisemap(map_t *map, object_t *entryob) {
enum OBTYPE upstairtype, downstairtype; enum OBTYPE upstairtype, downstairtype;
int i,d,x,y; int i,d,x,y;
int linkedentry = B_FALSE; int linkedentry = B_FALSE;
char roomlightob[BUFLEN],corridorlightob[BUFLEN];
int roomlightchance = 0;
int corridorlightfreq = 0;
cell_t *c; cell_t *c;
object_t *o,*nexto; object_t *o,*nexto;
// make sure this map has sufficient up/down staircases as defined by its // make sure this map has sufficient up/down staircases as defined by its
@ -4870,12 +4841,130 @@ void finalisemap(map_t *map, object_t *entryob) {
} }
// unlinked stairs? ie ones added from vaults. if so, link them. // unlinked stairs? ie ones added from vaults. if so, link them.
if (hasflag(o->flags, F_CLIMBABLE) && !hasflag(o->flags, F_MAPLINK)) { if (hasflag(o->flags, F_CLIMBABLE) && !hasflag(o->flags, F_MAPLINK)) {
linkstairs(o, NULL); if (o->type->id != OT_PORTAL) {
linkstairs(o, NULL);
}
} }
} }
} }
} }
// if map if not fully lit, scatter light sources around.
switch (map->illumination) {
case IL_FULLLIT: break;
case IL_WELLLIT:
strcpy(roomlightob, "patch of sun moss");
strcpy(corridorlightob, "patch of moon moss");
roomlightchance = 100;
corridorlightfreq = 4;
break;
case IL_DIM:
strcpy(roomlightob, "patch of moon moss");
strcpy(corridorlightob, "patch of moon moss");
roomlightchance = 100;
corridorlightfreq = 6;
break;
case IL_SHADOWY:
strcpy(roomlightob, "patch of moon moss");
strcpy(corridorlightob, "patch of moon moss");
roomlightchance = 50;
corridorlightfreq = 8;
break;
case IL_FULLDARK:
strcpy(roomlightob, "patch of moon moss");
strcpy(corridorlightob, "patch of moon moss");
roomlightchance = 33;
corridorlightfreq = 0;
break;
}
if (roomlightchance) {
for (i = 0; i < map->nrooms; i++) {
if (pctchance(roomlightchance)) {
c = getrandomroomcell(map, i);
addob(c->obpile, roomlightob);
}
}
}
if (corridorlightfreq) {
for (y = 1; y < map->h-1; y += corridorlightfreq) {
for (x = 1; x < map->w-1; x += corridorlightfreq) {
c = getcellat(map, x, y);
if (c && !isroom(c)) {
cell_t *c2;
c2 = getrandomadjcell(c, WE_NOTWALL, B_ALLOWEXPAND);
if (c2) {
addob(c2->obpile, corridorlightob);
}
}
}
}
}
}
void finalisemonster(lifeform_t *lf, lifeform_t *leader, flagpile_t *wantflags) {
flag_t *f;
if (leader) {
// if leader is asleep, minions will also be asleep
if (lfhasflag(leader, F_ASLEEP) || (wantflags && hasflag(wantflags, F_ASLEEP))) {
addflag(lf->flags, F_ASLEEP, NA, ST_ASLEEP, NA, NULL);
}
if ((lf->cell->map->illumination != IL_FULLLIT) && !lfhasflag(lf, F_SEEINDARK)) {
if ((getraceclass(lf) != RC_HUMANOID) && pctchance(75)) {
addflag(lf->flags, F_SEEINDARK, rnd(3,5), NA, NA, NULL);
}
}
// minions never have certain flags.
killflagsofid(lf->flags, F_DEMANDSBRIBE);
}
// random monster behaviours
if (!isundead(lf) && onein(4)) {
switch (rnd(0,6)) {
case 0: // insane
addflag(lf->flags, F_BEHAVIOUR, NA, NA, NA, "insane");
addflag(lf->flags, F_HATESALL, B_TRUE, NA, NA, NULL);
break;
case 1: // hungry
addflag(lf->flags, F_BEHAVIOUR, NA, NA, NA, "hungry");
addflag(lf->flags, F_WANTSOBFLAG, F_EDIBLE, B_COVETS, NA, NULL);
break;
case 2: // timid
addflag(lf->flags, F_BEHAVIOUR, NA, NA, NA, "timid");
f = lfhasflag(lf, F_MORALE);
if (f) {
f->val[0] /= 2;
} else {
addflag(lf->flags, F_FLEEONDAM, B_TRUE, NA, NA, NULL);
}
break;
case 3: // drugged
addflag(lf->flags, F_BEHAVIOUR, NA, NA, NA, "drugged");
killflagsofid(lf->flags, F_FLEEONDAM);
killflagsofid(lf->flags, F_FLEEONHPPCT);
addflag(lf->flags, F_NOFLEE, B_TRUE, NA, NA, NULL);
break;
case 4: // drunk
addflag(lf->flags, F_BEHAVIOUR, NA, NA, NA, "drunk");
addflag(lf->flags, F_DRUNK, rnd(2,5), NA, NA, NULL);
break;
case 5: // determined
addflag(lf->flags, F_BEHAVIOUR, NA, NA, NA, "determined");
addflag(lf->flags, F_FOLLOWTIME, (DEF_AIFOLLOWTIME*2), NA, NA, NULL);
break;
case 6: // lazy
addflag(lf->flags, F_BEHAVIOUR, NA, NA, NA, "lazy");
addflag(lf->flags, F_FOLLOWTIME, (DEF_AIFOLLOWTIME/4), NA, NA, NULL);
break;
}
}
if (wantflags) {
copyflags(lf->flags, wantflags, NA);
}
} }
celltype_t *findcelltype(enum CELLTYPE cid) { celltype_t *findcelltype(enum CELLTYPE cid) {
@ -6436,7 +6525,8 @@ void makelit(cell_t *c, enum LIGHTLEV how, int howlong) {
if ((gamemode == GM_GAMESTARTED) && (c->lit != how)) { if ((gamemode == GM_GAMESTARTED) && (c->lit != how)) {
lifeform_t *lf; lifeform_t *lf;
for (lf = c->map->lf ; lf ; lf = lf->next) { for (lf = c->map->lf ; lf ; lf = lf->next) {
if (haslos(lf, c) || haslosdark(lf, c)) { //if (haslos(lf, c) || haslosdark(lf, c)) {
if (haslos(lf, c)) {
setlosdirty(lf); setlosdirty(lf);
} }
} }
@ -6655,7 +6745,7 @@ int remove_deadends(map_t *m, int howmuch) {
void set_scanned_glyph(int targettype, void *what, char *descappend, char *desc, glyph_t *glyph) { void set_scanned_glyph(int targettype, void *what, char *descappend, char *desc, glyph_t *glyph) {
if (targettype == TT_MONSTER) { if (targettype == TT_MONSTER) {
if (desc) { if (desc) {
real_getlfnamea((lifeform_t *)what, desc, B_FALSE); real_getlfnamea((lifeform_t *)what, desc, B_FALSE, B_FALSE);
strcat(desc, descappend); strcat(desc, descappend);
} }
if (glyph) { if (glyph) {

1
map.h
View File

@ -73,6 +73,7 @@ void expand_cave(map_t *map, int numpasses);
void explodesinglecell(cell_t *c, int dam, int killwalls, object_t *o, cell_t *centre); void explodesinglecell(cell_t *c, int dam, int killwalls, object_t *o, cell_t *centre);
void explodecells(cell_t *c, int dam, int killwalls, object_t *o, int range, int dirtype, int wantannounce); void explodecells(cell_t *c, int dam, int killwalls, object_t *o, int range, int dirtype, int wantannounce);
void finalisemap(map_t *map, object_t *entryob); void finalisemap(map_t *map, object_t *entryob);
void finalisemonster(lifeform_t *lf, lifeform_t *leader, flagpile_t *wantflags);
celltype_t *findcelltype(enum CELLTYPE cid); celltype_t *findcelltype(enum CELLTYPE cid);
celltype_t *findcelltypebyname(char *name); celltype_t *findcelltypebyname(char *name);
habitat_t *findhabitat(enum HABITAT id); habitat_t *findhabitat(enum HABITAT id);

6
move.c
View File

@ -1116,6 +1116,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
if (newcell->map != lf->cell->map) { if (newcell->map != lf->cell->map) {
changedlev = B_TRUE; changedlev = B_TRUE;
setlosdirty(lf);
if (isplayer(lf)) { if (isplayer(lf)) {
// remember the time which we exitted this map. // remember the time which we exitted this map.
lf->cell->map->lastplayervisit = curtime; lf->cell->map->lastplayervisit = curtime;
@ -1209,6 +1210,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
// update light // update light
if ((isplayer(lf) && changedlev) || lfproduceslight(lf)) { if ((isplayer(lf) && changedlev) || lfproduceslight(lf)) {
calclight(lf->cell->map); calclight(lf->cell->map);
setlosdirty(lf);
} }
//precalclos(lf); //precalclos(lf);
@ -1498,7 +1500,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
} }
if (preseenbyplayer && !cansee(player, lf) && !changedlev) { if (preseenbyplayer && !cansee(player, lf) && !changedlev) {
if (areenemies(player, lf)) { if (areenemies(player, lf)) {
real_getlfnamea(lf, lfname, B_FALSE); real_getlfnamea(lf, lfname, B_FALSE, B_FALSE);
msg("%s moves out of view.", lfname); msg("%s moves out of view.", lfname);
} }
} }
@ -3110,7 +3112,7 @@ int walkoffmap(lifeform_t *lf, int dir, int onpurpose) {
for (n = 0; n < nadjallies; n++) { for (n = 0; n < nadjallies; n++) {
if (seen[n]) { if (seen[n]) {
char lname[BUFLEN]; char lname[BUFLEN];
real_getlfname(adjally[n], lname, B_FALSE); real_getlfname(adjally[n], lname, B_FALSE, B_FALSE);
msg("%s follows you.", lname); msg("%s follows you.", lname);
} }
} }

154
objects.c
View File

@ -970,7 +970,9 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
if (where->where) { if (where->where) {
if ((ot->material->id == MT_WATER) || (ot->id == OT_SPLASHWATER)) { if ((ot->material->id == MT_WATER) || (ot->id == OT_SPLASHWATER)) {
if (where->where->type->id == CT_DIRT) { if (where->where->type->id == CT_DIRT) {
ot = findot(OT_MUDPOOL); if (!hasob(where->where->obpile, OT_MUDPOOL)) {
ot = findot(OT_MUDPOOL);
}
} }
} }
} }
@ -4650,7 +4652,7 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
} }
if (who) { if (who) {
char lfname[BUFLEN]; char lfname[BUFLEN];
real_getlfnamea(who, lfname, B_FALSE); real_getlfnamea(who, lfname, B_FALSE, B_FALSE);
snprintf(buf, BUFLEN, "a %s%s scent",adjective,r->name); snprintf(buf, BUFLEN, "a %s%s scent",adjective,r->name);
} else { } else {
snprintf(buf, BUFLEN, "%s%s scent",adjective, r->name ); snprintf(buf, BUFLEN, "%s%s scent",adjective, r->name );
@ -4944,6 +4946,7 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
} }
// blessed status // blessed status
// ie. a ->blessed<- flaming +5 silver sword of pyromania
if (!hasflag(o->flags, F_NOBLESS) && wantblesscurse) { if (!hasflag(o->flags, F_NOBLESS) && wantblesscurse) {
if (showall || isblessknown(o)) { if (showall || isblessknown(o)) {
switch (o->blessed) { switch (o->blessed) {
@ -4973,26 +4976,23 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
strcat(localbuf, "partially eaten "); strcat(localbuf, "partially eaten ");
} }
// condition
// material changed? // include mods
if (o->material != o->type->material) { // ie. a blessed ->damaged<- flaming +5 silver sword of pyromania
switch (o->material->id) { if (wantcondition) {
case MT_GOLD: if (!hasflag(o->flags, F_NOOBDAMTEXT)) {
strcat(localbuf, "golden "); getobconditionname(o, buf2);
break; if (strlen(buf2) > 0) {
case MT_WOOD: strcat(localbuf, buf2);
strcat(localbuf, "wooden ");
break;
case MT_ICE: // we'll use the 'frozen' obmod instead
break;
default:
strcat(localbuf, o->material->name);
strcat(localbuf, " "); strcat(localbuf, " ");
break; }
} }
} }
// include mods (ie. a flaming sword)
// include mods
// ie. a blessed damaged ->flaming<- +5 silver sword of pyromania
if (wantpremods) { if (wantpremods) {
obmod_t *om; obmod_t *om;
for (om = firstobmod ; om; om = om->next) { for (om = firstobmod ; om; om = om->next) {
@ -5006,18 +5006,8 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
} }
} }
// condition // enchantments
if (wantcondition) { // ie. a blessed damaged flaming ->+5<- silver sword of pyromania
if (!hasflag(o->flags, F_NOOBDAMTEXT)) {
getobconditionname(o, buf2);
if (strlen(buf2) > 0) {
strcat(localbuf, buf2);
strcat(localbuf, " ");
}
}
}
// include enchantments (ie. a blessed +5 sword)
f = hasflag(o->flags, F_BONUS); f = hasflag(o->flags, F_BONUS);
if (f && (f->known || showall)) { if (f && (f->known || showall)) {
char buf2[BUFLENSMALL]; char buf2[BUFLENSMALL];
@ -5028,7 +5018,6 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
strcat(localbuf, buf2); strcat(localbuf, buf2);
} }
} }
// special rings // special rings
if (isidentified(o)) { if (isidentified(o)) {
switch (o->type->id) { switch (o->type->id) {
@ -5048,6 +5037,25 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
} }
} }
// material changed?
// ie. a blessed damaged flaming +5 ->silver<- sword of pyromania
if (o->material != o->type->material) {
switch (o->material->id) {
case MT_GOLD:
strcat(localbuf, "golden ");
break;
case MT_WOOD:
strcat(localbuf, "wooden ");
break;
case MT_ICE: // we'll use the 'frozen' obmod instead
break;
default:
strcat(localbuf, o->material->name);
strcat(localbuf, " ");
break;
}
}
if (issecretdoor(o)) { if (issecretdoor(o)) {
if (showall) { if (showall) {
strcat(localbuf, "secret "); strcat(localbuf, "secret ");
@ -5060,10 +5068,12 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
} }
// object name // object name
// ie. a blessed flaming +5 silver ->sword<- of pyromania
strcat(localbuf, pluralname); strcat(localbuf, pluralname);
free(pluralname); free(pluralname);
// include mods if identified - ie. xxx of pyromania // include mods if identified
// ie. a blessed flaming +5 silver sword ->of pyromania<-
for (br = firstbrand; br; br = br->next) { for (br = firstbrand; br; br = br->next) {
if (hasflagval(o->flags, F_HASBRAND, br->id, NA, NA, NULL)) { if (hasflagval(o->flags, F_HASBRAND, br->id, NA, NA, NULL)) {
flag_t *brf; flag_t *brf;
@ -5146,9 +5156,19 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
} }
if (istried(o)) { if (istried(o)) {
flag_t *f2;
if (strlen(triedbuf)) strcat(triedbuf, ", "); if (strlen(triedbuf)) strcat(triedbuf, ", ");
else strcpy(triedbuf, " ["); else strcpy(triedbuf, " [");
strcat(triedbuf, "tried"); f2 = hasflag(o->flags, F_SCROLLNEEDSOB);
if (f2) {
if ((f2->val[0] == B_IFNOTBLESSED) && !isblessed(o)) {
strcat(triedbuf, "tried");
} else {
strcat(triedbuf, "tried on object");
}
} else {
strcat(triedbuf, "tried");
}
} }
if (!isknown(o)) { if (!isknown(o)) {
if (lfhasflagval(player, F_FAILEDINSPECT, o->type->id, NA, NA, NULL)) { if (lfhasflagval(player, F_FAILEDINSPECT, o->type->id, NA, NA, NULL)) {
@ -8064,7 +8084,10 @@ int obsfallthrough(cell_t *c, object_t *pit) {
getobname(pit,downholename, 1); getobname(pit,downholename, 1);
if (belowcell) { if (belowcell) {
uphole = hasobwithflagval(belowcell->obpile, F_PIT, D_UP, NA, NA, NULL); char oid[BUFLENSMALL];
sprintf(oid, "%ld",pit->id);
uphole = findmapobwithflagval(belowcell->map, F_MAPLINK, NA, NA, NA, oid);
assert(uphole);
getobname(uphole,upholename, 1); getobname(uphole,upholename, 1);
} }
@ -8479,11 +8502,6 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
// certain wands always used the blessed version of spells // certain wands always used the blessed version of spells
// certain wands have different effects when cursed // certain wands have different effects when cursed
switch (o->type->id) { switch (o->type->id) {
case OT_WAND_LIGHT:
if (iscursed(o)) {
spelltocast = OT_S_DARKNESS;
}
break;
case OT_WAND_DIGGING: case OT_WAND_DIGGING:
if (isplayer(lf) && !isknown(o)) { if (isplayer(lf) && !isknown(o)) {
msg("This is a wand of digging!"); more(); msg("This is a wand of digging!"); more();
@ -8493,7 +8511,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
default: default:
break; break;
} }
dospelleffects(lf, spelltocast, power, where ? where->lf : NULL, NULL, where, isblessed(o), &willid, B_FALSE); dospelleffects(lf, spelltocast, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid, B_FALSE);
// special wands // special wands
} else if (o->type->id == OT_WAND_WONDER) { } else if (o->type->id == OT_WAND_WONDER) {
int power; int power;
@ -8529,10 +8547,10 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
dospelleffects(lf, OT_S_LEVITATION, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid, B_FALSE); dospelleffects(lf, OT_S_LEVITATION, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid, B_FALSE);
break; break;
case 5: // dispersal case 5: // dispersal
dospelleffects(lf, OT_S_DISPERSAL, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid, B_FALSE); dospelleffects(lf, OT_S_DISPERSAL, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid, B_FALSE);
break; break;
case 6: // flash case 6: // flash
dospelleffects(lf, OT_S_FLASH, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid, B_FALSE); dospelleffects(lf, OT_S_FLASH, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid, B_FALSE);
break; break;
case 7: // light case 7: // light
dospelleffects(lf, OT_S_LIGHT, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid, B_FALSE); dospelleffects(lf, OT_S_LIGHT, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid, B_FALSE);
@ -8550,34 +8568,34 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
dospelleffects(lf, OT_S_HASTE, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid, B_FALSE); dospelleffects(lf, OT_S_HASTE, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid, B_FALSE);
break; break;
case 12: // pull case 12: // pull
dospelleffects(lf, OT_S_SUCK, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid, B_FALSE); dospelleffects(lf, OT_S_SUCK, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid, B_FALSE);
break; break;
case 13: // blast case 13: // blast
dospelleffects(lf, OT_S_AIRBLAST, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid, B_FALSE); dospelleffects(lf, OT_S_AIRBLAST, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid, B_FALSE);
break; break;
case 14: // slow case 14: // slow
dospelleffects(lf, OT_S_SLOW, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid, B_FALSE); dospelleffects(lf, OT_S_SLOW, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid, B_FALSE);
break; break;
case 15: // sleep case 15: // sleep
dospelleffects(lf, OT_S_SLEEP, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid, B_FALSE); dospelleffects(lf, OT_S_SLEEP, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid, B_FALSE);
break; break;
case 16: // gas case 16: // gas
dospelleffects(lf, OT_S_CLOUDKILL, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid, B_FALSE); dospelleffects(lf, OT_S_CLOUDKILL, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid, B_FALSE);
break; break;
case 17: // dark case 17: // dark
dospelleffects(lf, OT_S_DARKNESS, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid, B_FALSE); dospelleffects(lf, OT_S_DARKNESS, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid, B_FALSE);
break; break;
case 18: // stone case 18: // stone
dospelleffects(lf, OT_S_PETRIFY, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid, B_FALSE); dospelleffects(lf, OT_S_PETRIFY, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid, B_FALSE);
break; break;
case 19: // fireball case 19: // fireball
dospelleffects(lf, OT_S_FIREBALL, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid, B_FALSE); dospelleffects(lf, OT_S_FIREBALL, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid, B_FALSE);
break; break;
case 20: // poly case 20: // poly
dospelleffects(lf, OT_S_POLYMORPH, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid, B_FALSE); dospelleffects(lf, OT_S_POLYMORPH, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid, B_FALSE);
break; break;
case 21: // teleport case 21: // teleport
dospelleffects(lf, OT_S_TELEPORT, power, lf , NULL, lf->cell, o->blessed, &willid, B_FALSE); dospelleffects(lf, OT_S_TELEPORT, power, lf , NULL, lf->cell, B_UNCURSED, &willid, B_FALSE);
break; break;
case 22: // create banana peel case 22: // create banana peel
if (where->type->solid) { if (where->type->solid) {
@ -8594,9 +8612,6 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
if (isplayer(lf) || cansee(player, lf)) { if (isplayer(lf) || cansee(player, lf)) {
// tell player // tell player
makeknown(o->type->id); makeknown(o->type->id);
if (iscursed(o)) {
o->blessknown = B_TRUE;
}
if (isplayer(lf)) { if (isplayer(lf)) {
real_getobname(o, obname, 1, B_FALSE, B_TRUE, B_FALSE, B_TRUE, B_FALSE); // don't adjust for blindness real_getobname(o, obname, 1, B_FALSE, B_TRUE, B_FALSE, B_TRUE, B_FALSE); // don't adjust for blindness
msg("This is %s!",obname); msg("This is %s!",obname);
@ -10119,22 +10134,21 @@ int readsomething(lifeform_t *lf, object_t *o) {
} }
// ask for a target object of any type if scroll is unknown? // ask for a target object of any type if scroll is unknown?
switch (o->type->id) { f = hasflag(o->flags, F_SCROLLNEEDSOB);
case OT_SCR_IDENTIFY: if (f) {
case OT_SCR_MENDING: switch (f->val[0]) {
if (isblessed(o)) { case B_ALWAYS:
needsob = B_FALSE;
} else {
needsob = B_TRUE; needsob = B_TRUE;
} break;
break; case B_IFNOTBLESSED:
case OT_SCR_ENCHANT: if (isblessed(o)) {
case OT_SCR_REPLENISHMENT: needsob = B_FALSE;
needsob = B_TRUE; } else {
break; needsob = B_TRUE;
default: }
needsob = B_FALSE; break;
break; default: break;
}
} }
if (!isknown(o) && willid) { if (!isknown(o) && willid) {
@ -10787,7 +10801,7 @@ void setobcreatedby(object_t *o, lifeform_t *lf) {
if (!lf) { if (!lf) {
return; return;
} }
real_getlfnamea(lf, lfname, B_FALSE); real_getlfnamea(lf, lfname, B_FALSE, B_TRUE);
addflag(o->flags, F_CREATEDBY, lf->id, NA, NA, lfname); addflag(o->flags, F_CREATEDBY, lf->id, NA, NA, lfname);
} }
@ -11482,7 +11496,7 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
if (thrower) { if (thrower) {
getlfname(thrower, throwername); getlfname(thrower, throwername);
real_getlfname(thrower, realthrowername, B_FALSE); real_getlfname(thrower, realthrowername, B_FALSE, B_FALSE);
if (isplayer(thrower)) { if (isplayer(thrower)) {
strcpy(throwernamea, throwername); strcpy(throwernamea, throwername);

6
save.c
View File

@ -297,6 +297,7 @@ map_t *loadmap(char *basefile) {
int x,y; int x,y;
int db = B_TRUE; int db = B_TRUE;
enum HABITAT habitatid; enum HABITAT habitatid;
int illum;
lifeform_t *l; lifeform_t *l;
object_t *o; object_t *o;
map_t *m; map_t *m;
@ -333,7 +334,8 @@ map_t *loadmap(char *basefile) {
fscanf(f, "seed:%u\n",&m->seed); // seed fscanf(f, "seed:%u\n",&m->seed); // seed
fscanf(f, "lastplayervisit:%ld\n",&m->lastplayervisit); fscanf(f, "lastplayervisit:%ld\n",&m->lastplayervisit);
fscanf(f, "dims:%d,%d\n",&m->w, &m->h); // map dimensons fscanf(f, "dims:%d,%d\n",&m->w, &m->h); // map dimensons
fscanf(f, "lit:%d\n",&m->lit); fscanf(f, "illumination:%d\n",&illum);
m->illumination = illum;
fscanf(f, "nextmaps:\n"); fscanf(f, "nextmaps:\n");
for (i = 0; i < MAXDIR_ORTH; i++) { for (i = 0; i < MAXDIR_ORTH; i++) {
fscanf(f, "%d\n",&m->nextmap[i]); // map dimensons fscanf(f, "%d\n",&m->nextmap[i]); // map dimensons
@ -916,7 +918,7 @@ int savemap(map_t *m) {
fprintf(f, "seed:%u\n",m->seed); // seed fprintf(f, "seed:%u\n",m->seed); // seed
fprintf(f, "lastplayervisit:%ld\n",m->lastplayervisit); fprintf(f, "lastplayervisit:%ld\n",m->lastplayervisit);
fprintf(f, "dims:%d,%d\n",m->w, m->h); // map dimensons fprintf(f, "dims:%d,%d\n",m->w, m->h); // map dimensons
fprintf(f, "lit:%d\n",m->lit); // seed fprintf(f, "illumination:%d\n",m->illumination); // seed
fprintf(f, "nextmaps:\n"); fprintf(f, "nextmaps:\n");
for (i = 0; i < MAXDIR_ORTH; i++) { for (i = 0; i < MAXDIR_ORTH; i++) {
fprintf(f, "%d\n",m->nextmap[i] ); // map dimensons fprintf(f, "%d\n",m->nextmap[i] ); // map dimensons

View File

@ -598,7 +598,7 @@ enum SHOPRETURN shoppurchase(lifeform_t *lf, object_t *vm, int starty, char *top
y++; y++;
// ask what to do // ask what to do
mvwprintw(mainwin, y, 0, "What will you %s (ESC when done)? ", (shopmode == BUY) ? "buy" : "examine"); mvwprintw(mainwin, y, 0, "What will you %s (ESC=done, ?=toggle action)? ", (shopmode == BUY) ? "buy" : "examine");
ch = getch(); ch = getch();
if (ch == 27) { if (ch == 27) {

23
spell.c
View File

@ -67,7 +67,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
flag_t *f; flag_t *f;
getlfname(user, username); getlfname(user, username);
real_getlfname(user,killername, B_FALSE); real_getlfname(user,killername, B_FALSE, B_FALSE);
// defaults // defaults
strcpy(damstr,""); strcpy(damstr,"");
@ -333,7 +333,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
} else { } else {
if (slev >= PR_EXPERT) { if (slev >= PR_EXPERT) {
// overwrite name // overwrite name
real_getlfnamea(inway, thismovetext, B_FALSE); real_getlfnamea(inway, thismovetext, B_FALSE, B_FALSE);
} }
movetext[0] = strdup(thismovetext); movetext[0] = strdup(thismovetext);
movetextcount[0] = 1; movetextcount[0] = 1;
@ -347,7 +347,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
if (getnoisedetails(lf, N_WALK, thismovetext, NULL, &vol)) continue; if (getnoisedetails(lf, N_WALK, thismovetext, NULL, &vol)) continue;
if (slev >= PR_EXPERT) { if (slev >= PR_EXPERT) {
// overwrite name // overwrite name
real_getlfnamea(lf, thismovetext, B_FALSE); real_getlfnamea(lf, thismovetext, B_FALSE, B_FALSE);
} }
if (canhear(user, lf->cell, vol)) { if (canhear(user, lf->cell, vol)) {
// already have this text? // already have this text?
@ -3392,6 +3392,14 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
objecttype_t *sp; objecttype_t *sp;
flag_t *casttype = NULL; flag_t *casttype = NULL;
// sometimes change spellid based on blessed status
if (blessed == B_CURSED) {
switch (spellid) {
case OT_S_LIGHT: spellid = OT_S_DARKNESS;
default: break;
}
}
sp = findot(spellid); sp = findot(spellid);
if (caster) { if (caster) {
@ -3404,6 +3412,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (seenbyplayer) *seenbyplayer = B_FALSE; if (seenbyplayer) *seenbyplayer = B_FALSE;
if (caster) { if (caster) {
if (hasflag(sp->flags, F_ONGOING)) { if (hasflag(sp->flags, F_ONGOING)) {
if (lfhasflagval(caster, F_BOOSTSPELL, spellid, NA, NA, NULL)) { if (lfhasflagval(caster, F_BOOSTSPELL, spellid, NA, NA, NULL)) {
@ -4025,7 +4034,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (!isimmuneto(c->lf->flags, DT_FIRE, B_FALSE)) { if (!isimmuneto(c->lf->flags, DT_FIRE, B_FALSE)) {
msg("%s burn%s!",buf,isplayer(c->lf) ? "" : "s"); msg("%s burn%s!",buf,isplayer(c->lf) ? "" : "s");
} }
real_getlfname(caster, realcname, B_FALSE); real_getlfname(caster, realcname, B_FALSE, B_TRUE);
snprintf(damstring, BUFLEN, "%s%s wave of fire", realcname, getpossessive(realcname)); snprintf(damstring, BUFLEN, "%s%s wave of fire", realcname, getpossessive(realcname));
losehp(c->lf, rolldie(2,10), DT_FIRE, caster, damstring); losehp(c->lf, rolldie(2,10), DT_FIRE, caster, damstring);
} }
@ -6706,7 +6715,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else { } else {
char dambuf[BUFLEN]; char dambuf[BUFLEN];
char cname[BUFLEN]; char cname[BUFLEN];
real_getlfname(caster, cname, B_FALSE); real_getlfname(caster, cname, B_FALSE, B_TRUE);
snprintf(dambuf, BUFLEN, "%s%s infinite death spell", cname, getpossessive(cname)); snprintf(dambuf, BUFLEN, "%s%s infinite death spell", cname, getpossessive(cname));
losehp(l, 500, DT_NECROTIC, NULL, dambuf); losehp(l, 500, DT_NECROTIC, NULL, dambuf);
} }
@ -6722,7 +6731,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else { } else {
char dambuf[BUFLEN]; char dambuf[BUFLEN];
char cname[BUFLEN]; char cname[BUFLEN];
real_getlfname(caster, cname, B_FALSE); real_getlfname(caster, cname, B_FALSE, B_TRUE);
snprintf(dambuf, BUFLEN, "%s%s infinite death spell", cname, getpossessive(cname)); snprintf(dambuf, BUFLEN, "%s%s infinite death spell", cname, getpossessive(cname));
losehp(caster, 500, DT_NECROTIC, NULL, dambuf); losehp(caster, 500, DT_NECROTIC, NULL, dambuf);
} }
@ -7862,7 +7871,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
char distbuf[BUFLEN],dirbuf[BUFLEN]; char distbuf[BUFLEN],dirbuf[BUFLEN];
char lfname[BUFLEN]; char lfname[BUFLEN];
real_getlfnamea(c->lf, lfname, B_FALSE); real_getlfnamea(c->lf, lfname, B_FALSE, B_TRUE);
getdisttext(caster->cell, c, distbuf, NULL, dirbuf); getdisttext(caster->cell, c, distbuf, NULL, dirbuf);
sprintf(ptext, "%s: %s (%s to the %s, held by %s)", sprintf(ptext, "%s: %s (%s to the %s, held by %s)",
mapname, obname, distbuf, dirbuf, lfname); mapname, obname, distbuf, dirbuf, lfname);