- [+] firebug should deal 1 fire damage to anything on the ground

- [+] f_damagegroundobs v0=dam, v1=damtype
    - [+] add a similar thing ice wraith (they cause cold damage)
- [+] psionic spells:  baffle and disorient too similar?  make one a
      lower level ?
    - [+] make disorient face them away from you!
- [+] ekrub shouldn't get angry for crushing glass underfoot
    - [+] OR... warn before you do this if you worship ekrub
- [+] don't drip water while inside a wall (ie. ethereal)
- [+] don't show "[tried on xxx]" for objects in store inventories!
- [+] make "i bestow a gift" msg change depending on god
- [+] potion of etherealness spell disappating twice?
    - [+] ie. stopspell being called twice.
    - [+] spell effect now chacks for existing noncorporealness
- [+] different god msg if they are angered but still pleased
    - [+] "don't do that again!"
    - [+] "ahem!"
    - [+] "i won't tolerate further transgressions"
    - [+] etc
- [+] io.c not showing that druid is vegetarian.
    - [+] show this only if ilfetime !=  FROMRACE
    - [+] don't show it otherwise, since it's a racial trait.
    - [+] change hasflag_real to have "int lifetimeexception"
    - [+] same with:
        - [+] VEGERATIRNA
        - [+] CARNIVORE
        - [+] PARTVEGETARIAN
        - [+] F_SIZE??
        - [+] VISRANGEMOD
- [+] stickstosnakes - make this not affect the CASTER's equiped
      weapon, but it doesnt affect weapons of others.
    - [+] implemment
    - [+] make spell description describe this.
- [+] make safebox not be stealable
This commit is contained in:
Rob Pearce 2012-02-04 23:26:16 +00:00
parent c1bccc652c
commit 0ce77ec00b
14 changed files with 291 additions and 134 deletions

View File

@ -519,9 +519,6 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
angergodmaybe(R_GODMERCY, 25, GA_ATTACKALLY);
angergodmaybe(R_GODPURITY, 100, GA_ATTACKALLY);
switch (getalignment(attacktarget)) {
case AL_EVIL:
angergodmaybe(R_GODDEATH, 20, GA_ATTACKALLY); // even more
break;
case AL_GOOD:
angergodmaybe(R_GODPURITY, 20, GA_ATTACKALLY); // even more
break;

14
data.c
View File

@ -3100,12 +3100,13 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL);
addot(OT_S_PURIFYFOOD, "purify food", "Removes rot or poison from food or drink.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addot(OT_S_PURIFYFOOD, "purify food", "Changes any kind of harmful food or drink into a harmless equivilant.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ENCHANTMENT, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL);
addot(OT_S_STICKTOSNAKE, "sticks to snakes", "Transforms all seen wooden weapons into snakes.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addot(OT_S_STICKTOSNAKE, "sticks to snakes", "Transforms all rod-shaped objects in sight into allied snakes.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "This spell does not affect the caster's weapon.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
@ -3454,7 +3455,7 @@ void initobjects(void) {
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
// l2
addot(OT_S_DISORIENT, "disorient", "Spins the target around to face a different direction. This will sometimes also make them dizzy.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addot(OT_S_DISORIENT, "disorient", "Spins the target around to face away from the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 10, NA, NA, NULL);
@ -4390,6 +4391,7 @@ void initobjects(void) {
addflag(lastot->flags, F_VALUE, 150, NA, NA, NULL);
addflag(lastot->flags, F_GLYPH, C_YELLOW, '(', NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOSTEAL, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 15, 15, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
@ -7888,7 +7890,7 @@ void initrace(void) {
addflag(lastrace->flags, F_SACRIFICEOB, OT_BANDAGE, NA, 30, "OB IS consumed by a shaft of holy light.");
addflag(lastrace->flags, F_SACRIFICEOBCLASS, OC_FOOD, NA, 3, "OB IS consumed by a shaft of holy light.");
addrace(R_GODDEATH, "Hecta", 100, '@', C_BOLDMAGENTA, MT_BONE, RC_GOD, "The skeletal god of death is garbed in a cloak made of pure shadow. and weilds an enormous scythe.");
addrace(R_GODDEATH, "Hecta", 100, '@', C_BOLDMAGENTA, MT_BONE, RC_GOD, "The skeletal god of Death is garbed in a cloak made of pure shadow. and weilds an enormous scythe.");
setbodytype(lastrace, BT_HUMANOID);
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, NA, NA, "80");
@ -8045,7 +8047,7 @@ void initrace(void) {
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_NONE, NA, NA, "raises her palms");
addflag(lastrace->flags, F_CASTCHANCE, 75, NA, NA, NULL);
// god abilities
addflag(lastrace->flags, F_GODOF, B_FEMALE, NA, NA, "Mercy");
addflag(lastrace->flags, F_GODOF, B_FEMALE, NA, NA, "Mercy & Forgiveness");
addflag(lastrace->flags, F_FLEEONHPPCT, 10, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_S_CUREPOISON, NA, NA, "pw:10;");
addflag(lastrace->flags, F_CANWILL, OT_S_HEALINGMAJ, NA, NA, "pw:10;");
@ -11395,6 +11397,7 @@ void initrace(void) {
addflag(lastrace->flags, F_STARTATT, A_STR, AT_LTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_TOUCHBURN, 3, NA, NULL);
addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 3, NA, "flares its flames^crackling flames");
addflag(lastrace->flags, F_DAMAGEGROUNDOBS, 2, DT_FIRE, NA, NULL);
addflag(lastrace->flags, F_MORALE, 5, NA, NA, NULL);
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addrace(R_GLOWBUG, "glowbug", 1, 'i', C_WHITE, MT_FLESH, RC_INSECT, "Glowbugs are tiny flying creatures, magically producing light from their bodies.");
@ -11692,6 +11695,7 @@ void initrace(void) {
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_HASATTACK, OT_TOUCHCHILL, 7, NA, NULL);
addflag(lastrace->flags, F_DTVULN, DT_FIRE, NA, NA, NULL);
addflag(lastrace->flags, F_DAMAGEGROUNDOBS, 4, DT_COLD, B_TRUE, NULL);
addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "shoddy cloak");
addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 3, NA, "screeches^a screech");
addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL);

7
defs.h
View File

@ -2151,6 +2151,7 @@ enum FLAG {
// just convert the object)
F_NOBLESS, // can't be blessed or cursed
F_NOQUALITY, // can't be masterwork / shoddy
F_NOSTEAL, // this object can't be stolen, blown away, etc.
F_SALTED, // this corpse has been salted and will not decay.
F_CORPSEOF, // this is a corpse of montype val0.
// text is how it died.
@ -2533,6 +2534,8 @@ enum FLAG {
F_HOMEMAP, // which map did this lf get created on?
F_TOOKACTION, // lf purposely took action in their last turn.
F_JUSTENTERED, // lf just entered a new map.
F_DAMAGEGROUNDOBS, // lf causes v0 damage of type v1 to ground objects
// if v2 is TRUE, this happens even when lf is airborne
F_MOVED, // lf purposely walked/flew/swum/moved in prev turn
F_HASBEENMOVED, // an object moved this lf since their last turn.
F_HOTFEET, // target takes v0 damage of type v1 unless they move.
@ -2651,8 +2654,8 @@ enum FLAG {
F_NOSKILL, // lifeform CANNOT ever learn skill v0
F_LFSUFFIX, // text = suffix. eg. "skeleton"
F_VISRANGE, // how far you can see (in the light)
F_VISRANGEMOD, // modifications to visrange
F_NIGHTVISRANGEMOD, // modifications to nightvisrange
F_VISRANGEMOD, // v0:modifications to visrange
F_NIGHTVISRANGEMOD, // v0:modifications to nightvisrange
F_GUNTARGET, // current projectile weapon target
// v0 is guntarget id.
// text is targetting string (ie. Orc [50%])

16
flag.c
View File

@ -637,14 +637,14 @@ int flagcausesstatredraw(lifeform_t *lf, enum FLAG fid) {
}
flag_t *hasflag(flagpile_t *fp, int id) {
return hasflag_real(fp, id, NA, NULL);
return hasflag_real(fp, id, NA, NULL, NA);
}
flag_t *hasflagknown(flagpile_t *fp, int id) {
return hasflag_real(fp, id, B_TRUE, NULL);
return hasflag_real(fp, id, B_TRUE, NULL, NA);
}
flag_t *hasflag_real(flagpile_t *fp, int id, int wantknown, flag_t *exception) {
flag_t *hasflag_real(flagpile_t *fp, int id, int wantknown, flag_t *exception, int lifetimeexception) {
flag_t *f,*foundflag = NULL, *searchfrom = NULL;
lifeform_t *owner;
int pos;
@ -704,6 +704,7 @@ flag_t *hasflag_real(flagpile_t *fp, int id, int wantknown, flag_t *exception) {
while (f && (f->id == id)) {
int valid = B_TRUE;
if (f == exception) valid = B_FALSE;
if ((lifetimeexception != NA) && (f->lifetime == lifetimeexception)) valid = B_FALSE;
if ((wantknown != NA) && (f->known != wantknown)) valid = B_FALSE;
if (owner && (f->lifetime == FROMJOB) && !getjob(owner)) valid = B_FALSE;
//if (owner && (f->lifetime == FROMSKILL) && !getskill(owner, xxx)) valid = B_FALSE;
@ -743,11 +744,11 @@ flag_t *hasflag_real(flagpile_t *fp, int id, int wantknown, flag_t *exception) {
flag_t *hasflagval(flagpile_t *fp, int id, int val1, int val2, int val3, char *text) {
return hasflagval_real(fp, id, val1, val2, val3, text, B_FALSE); // doesn't have to be known
return hasflagval_real(fp, id, val1, val2, val3, text, B_FALSE, NA); // doesn't have to be known
}
flag_t *hasflagvalknown(flagpile_t *fp, int id, int val1, int val2, int val3, char *text) {
return hasflagval_real(fp, id, val1, val2, val3, text, B_TRUE); // must be known
return hasflagval_real(fp, id, val1, val2, val3, text, B_TRUE, NA); // must be known
}
int getcounter(flagpile_t *fp) {
@ -759,7 +760,7 @@ int getcounter(flagpile_t *fp) {
return 0;
}
flag_t *hasflagval_real(flagpile_t *fp, int id, int val1, int val2, int val3, char *text, int wantknown) {
flag_t *hasflagval_real(flagpile_t *fp, int id, int val1, int val2, int val3, char *text, int wantknown, int lifetimeexception) {
flag_t *f,*foundflag = NULL, *searchfrom = NULL;
lifeform_t *owner;
int pos;
@ -816,7 +817,8 @@ flag_t *hasflagval_real(flagpile_t *fp, int id, int val1, int val2, int val3, ch
// now find a valid one
f = searchfrom;
while (f && (f->id == id)) {
if (owner && (f->lifetime == FROMJOB) && !getjob(owner)) {
if ((lifetimeexception != NA) && (f->lifetime == lifetimeexception)) {
} else if (owner && (f->lifetime == FROMJOB) && !getjob(owner)) {
// invalid
} else if ( ((val1 == NA) || (f->val[0] == val1)) &&
((val2 == NA) || (f->val[1] == val2)) &&

4
flag.h
View File

@ -25,10 +25,10 @@ cell_t *getflagpilelocation(flagpile_t *fp);
int getflags(flagpile_t *fp, flag_t **retflag, int *nretflags, ... );
flag_t *hasflag(flagpile_t *fp, int id);
flag_t *hasflagknown(flagpile_t *fp, int id);
flag_t *hasflag_real(flagpile_t *fp, int id, int wantknown, flag_t *exception);
flag_t *hasflag_real(flagpile_t *fp, int id, int wantknown, flag_t *exception, int lifetimeexception);
flag_t *hasflagval(flagpile_t *fp, int id, int val1, int val2, int val3, /*@null@*/ char *text);
flag_t *hasflagvalknown(flagpile_t *fp, int id, int val1, int val2, int val3, /*@null@*/ char *text);
flag_t *hasflagval_real(flagpile_t *fp, int id, int val1, int val2, int val3, /*@null@*/ char *text, int wantknown);
flag_t *hasflagval_real(flagpile_t *fp, int id, int val1, int val2, int val3, /*@null@*/ char *text, int wantknown, int lifetimeexception);
int istransitoryflag(flag_t *f);
int killflagsofid(flagpile_t *fp, enum FLAG fid);
void killflag(flag_t *f);

88
god.c
View File

@ -62,20 +62,30 @@ void angergod(enum RACE rid, int amt, enum GODANGERREASON why) {
} else if (rid == R_GODNATURE) {
godsay(rid, B_TRUE, "You dare destroy my creations?"); break;
} else {
godsay(rid, B_TRUE, "You dare destroy my symbols?"); break;
godsay(rid, B_TRUE, "You dare desecrate my symbols?"); break;
}
case GA_ASSAULT:
godsay(rid, B_TRUE, "You dare attack one of my innocent servants?"); break;
if (rid == R_GODDEATH) {
godsay(rid, B_TRUE, "You dare attack one of my servants?"); break;
} else {
godsay(rid, B_TRUE, "You dare attack an innocent?"); break;
}
case GA_COWARD:
godsay(rid, B_TRUE, "Coward!"); break;
case GA_EAT:
godsay(rid, B_TRUE, "That is NOT acceptable for consumption!"); break;
case GA_HERESY:
godsay(rid, B_TRUE, "Heresy!"); break;
if (rid == R_GODFIRE) {
godsay(rid, B_TRUE, "HERESY!"); break;
} else if (rid == R_GODMAGIC) {
godsay(rid, B_TRUE, "One's mundanity is offensive!"); break;
} else {
godsay(rid, B_TRUE, "Heresy!"); break;
}
case GA_MERCY:
godsay(rid, B_TRUE, "You allowed your foe to escape!"); break;
godsay(rid, B_TRUE, "You allowed my sacrifice to escape!"); break;
case GA_MONEY:
godsay(rid, B_TRUE, "Where is your sense of greed?"); break;
godsay(rid, B_TRUE, "Where is your sense of greed?!"); break;
case GA_MURDER:
godsay(rid, B_TRUE, "You have taken a life!"); break;
case GA_PRAY: dosay = B_TRUE; break;
@ -84,18 +94,35 @@ void angergod(enum RACE rid, int amt, enum GODANGERREASON why) {
case GA_RACE:
godsay(rid, B_TRUE, "Your form offends me!"); break;
case GA_SPELL:
godsay(rid, B_TRUE, "Your magic offends me!"); break;
if (rid == R_GODBATTLE) {
godsay(rid, B_TRUE, "A true warrior does not resort to magic!"); break;
} else if (rid == R_GODFIRE) {
godsay(rid, B_TRUE, "NO COLD MAGIC!"); break;
} else if (rid == R_GODDEATH) {
godsay(rid, B_TRUE, "The stink of your vile magic offends me!"); break;
} else if (rid == R_GODLIFE) {
godsay(rid, B_TRUE, "I will not tolerate such evil magics!"); break;
} else {
godsay(rid, B_TRUE, "Your magic offends me!"); break;
}
}
// announce
if (plev == PL_ANGRY) { // minor bad stuff
godsay(rid,dosay, "You have angered me, mortal!");
} else if (plev == PL_FURIOUS) { // major bad stuff
godsay(rid,dosay, "You go too far, mortal!");
} else if (plev == PL_ENRAGED) { // god will attack
godsay(rid,dosay, "You will regret that!");
} else { // not angry yet.
godsay(rid, dosay, "You are testing my patience, mortal!");
switch (plev) {
case PL_ENRAGED:
godsay(rid,dosay, "Witness the wrath of a god!");
break;
case PL_FURIOUS:
godsay(rid,dosay, "You go too far, mortal!");
break;
case PL_ANGRY:
godsay(rid,dosay, "You have angered me, mortal!");
break;
case PL_INDIFFERENT: // ie. not angry yet...
godsay(rid, dosay, "You are testing my patience, mortal!");
break;
default: // ie. still happy
break;
}
// bad stuff
@ -784,7 +811,38 @@ int godgiftmaybe(enum RACE rid, int fromtemple) {
killflagsofid(player->flags, F_ASLEEP);
godsay(god->race->id, B_TRUE, "I bestow a gift upon you, mortal!");
switch (god->race->id) {
case R_GODPURITY:
godsay(god->race->id, B_TRUE, "I bestow a gift upon you, mortal!");
break;
case R_GODTHIEVES:
godsay(god->race->id, B_TRUE, "Loyalty has its rewards...");
break;
case R_GODDEATH:
godsay(god->race->id, B_TRUE, "Your service has impressed me...");
break;
case R_GODFIRE:
godsay(god->race->id, B_TRUE, "DESTROY IN MY NAME!");
break;
case R_GODLIFE:
godsay(god->race->id, B_TRUE, "Use this gift to spread the joy of life!");
break;
case R_GODMERCY:
godsay(god->race->id, B_TRUE, "As you have shown mercy, so shall you receive it!");
break;
case R_GODNATURE:
godsay(god->race->id, B_TRUE, "Harvest nature's bounty!");
break;
case R_GODBATTLE:
godsay(god->race->id, B_TRUE, "Gather up the spoils of battle!");
break;
case R_GODMAGIC:
godsay(god->race->id, B_TRUE, "One has earned a reward!");
break;
default:
break;
}
strcpy(obtogive, "");
switch (god->race->id) {
case R_GODBATTLE:

100
io.c
View File

@ -1736,7 +1736,7 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
break;
case F_RESISTMAG:
if (isplayer(lf)) { // don't know if monsters get it
msg("You feel %simmune to magic.", hasflag_real(lf->flags, F_RESISTMAG, NA, f) ? "more " : "");
msg("You feel %simmune to magic.", hasflag_real(lf->flags, F_RESISTMAG, NA, f, NA) ? "more " : "");
donesomething = B_TRUE;
}
break;
@ -2366,7 +2366,7 @@ int announceflagloss(lifeform_t *lf, flag_t *f) {
break;
case F_RESISTMAG:
if (isplayer(lf)) { // don't know if monsters lose it
if (hasflag_real(lf->flags, F_RESISTMAG, NA, f)) {
if (hasflag_real(lf->flags, F_RESISTMAG, NA, f, NA)) {
msg("You feel less immune to magic.");
} else {
msg("You are no longer immune to magic.");
@ -11436,6 +11436,7 @@ void showlfstats(lifeform_t *lf, int showall) {
}
} else if (mode == 'e') {
int nfound = 0,luckmod;
enum LFSIZE racesize,cursize;
x = 0; // override
// down a line.
centre(mainwin, C_WHITE, y, "EFFECTS");
@ -11529,6 +11530,19 @@ void showlfstats(lifeform_t *lf, int showall) {
y++;
}
f = hasflag(lf->race->flags, F_SIZE);
if (f) {
racesize = f->val[0];
} else {
racesize = SZ_HUMAN; // default
}
cursize = getlfsize(lf);
if (cursize != racesize) {
mvwprintw(mainwin, y, 0, "%s body has been magically %s.", your(lf), (cursize > racesize) ? "enlarged" : "shrunken");
y++;
}
// show racial effects
if (hasjob(lf, J_PIRATE)) {
mvwprintw(mainwin, y, 0, "%s can hold %s liquor well.", you(lf), isplayer(lf) ? "Your" : "its");
@ -11562,8 +11576,8 @@ void showlfstats(lifeform_t *lf, int showall) {
mvwprintw(mainwin, y, 0, "%s %s deaf.", you(lf), is(lf));
y++;
}
f = lfhasknownflag(lf, F_ENHANCESMELL);
if (f && (f->lifetime != FROMRACE)) {
f = hasflag_real(lf->flags, F_ENHANCESMELL, B_TRUE, NULL, FROMRACE);
if (f) {
mvwprintw(mainwin, y, 0, "%s %s an enhanced sense of smell.", you(lf), isplayer(lf) ? "have" : "has");
y++;
}
@ -11573,8 +11587,8 @@ void showlfstats(lifeform_t *lf, int showall) {
y++;
}
f = lfhasknownflag(lf, F_HEAVYBLOW);
if (f && (f->lifetime != FROMRACE)) {
f = hasflag_real(lf->flags, F_HEAVYBLOW, B_TRUE, NULL, FROMRACE);
if (f) {
snprintf(buf, BUFLEN,"%s%s attacks knock enemies back.", you(lf), getpossessive(you(lf)));
mvwprintw(mainwin, y, 0, buf);
y++;
@ -11613,43 +11627,67 @@ void showlfstats(lifeform_t *lf, int showall) {
mvwprintw(mainwin, y, 0, "%s %s %s resistant to magic.", you(lf), is(lf), adjective);
y++;
}
f = lfhasknownflag(lf, F_TREMORSENSE);
if (f && (f->lifetime != FROMRACE)) {
f = hasflag_real(lf->flags, F_TREMORSENSE, B_TRUE, NULL, FROMRACE);
if (f) {
mvwprintw(mainwin, y, 0, "%s can 'see' by sensing vibrations around %s.", you(lf), you(lf));
y++;
}
f = lfhasflag(lf, F_STENCH);
if (f && (f->known) && (f->lifetime != FROMRACE)) {
mvwprintw(mainwin, y, 0, "%s smell%s terrible.", you(lf), isplayer(lf) ? "" : "s");
y++;
}
f = lfhasknownflag(lf, F_SEEINDARK);
if (f && (f->known) && (f->lifetime != FROMRACE)) {
f = hasflag_real(lf->flags, F_SEEINDARK, B_TRUE, NULL, FROMRACE);
if (f) {
mvwprintw(mainwin, y, 0, "%s can see in the dark.", you(lf));
y++;
}
f = lfhasknownflag(lf, F_SEEINVIS);
if (f && (f->known) && (f->lifetime != FROMRACE)) {
f = hasflag_real(lf->flags, F_SEEINVIS, B_TRUE, NULL, FROMRACE);
if (f) {
mvwprintw(mainwin, y, 0, "%s can see invisible things.", you(lf));
y++;
}
f = lfhasknownflag(lf, F_SPIDERCLIMB);
if (f && (f->known) && (f->lifetime != FROMRACE)) {
f = hasflag_real(lf->flags, F_SPIDERCLIMB, B_TRUE, NULL, FROMRACE);
if (f) {
mvwprintw(mainwin, y, 0, "%s adhesive skin allows %s to climb walls.", your(lf), you(lf));
y++;
}
f = lfhasknownflag(lf, F_SIXTHSENSE);
if (f && (f->known) && (f->lifetime != FROMRACE)) {
f = hasflag_real(lf->flags, F_SIXTHSENSE, B_TRUE, NULL, FROMRACE);
if (f) {
mvwprintw(mainwin, y, 0, "%s will be warned about nearby enemies.", you(lf));
y++;
}
f = lfhasknownflag(lf, F_STABILITY);
if (f && (f->known) && (f->lifetime != FROMRACE)) {
f = hasflag_real(lf->flags, F_STABILITY, B_TRUE, NULL, FROMRACE);
if (f) {
mvwprintw(mainwin, y, 0, "%s will not fall on slippery ground.", you(lf));
y++;
}
f = lfhasknownflag(lf, F_XRAYVIS);
if (f && (f->known) && (f->lifetime != FROMRACE)) {
// only show eating habits if not inherited from race
f = hasflag_real(lf->flags, F_CARNIVORE, B_TRUE, NULL, FROMRACE);
if (f) {
mvwprintw(mainwin, y, 0, "%s %s a carnivore (will not eat non-meat products).", you(lf), is(lf));
y++;
}
f = hasflag_real(lf->flags, F_VEGETARIAN, B_TRUE, NULL, FROMRACE);
if (f) {
mvwprintw(mainwin, y, 0, "%s %s a vegetarian (will not eat meat).", you(lf), is(lf));
y++;
}
f = hasflag_real(lf->flags, F_PARTVEGETARIAN, B_TRUE, NULL, FROMRACE);
if (f) {
mvwprintw(mainwin, y, 0, "%s %s a part vegetarian (will only eat meat when hunger).", you(lf), is(lf));
y++;
}
f = hasflag_real(lf->flags, F_VISRANGEMOD, B_TRUE, NULL, FROMRACE);
if (f) {
mvwprintw(mainwin, y, 0, "%s vision range has been %d.", your(lf), (f->val[0] > 0) ? "increased" : "decreased");
y++;
}
f = hasflag_real(lf->flags, F_NIGHTVISRANGEMOD, B_TRUE, NULL, FROMRACE);
if (f) {
mvwprintw(mainwin, y, 0, "%s night vision range has been %d.", your(lf), (f->val[0] > 0) ? "increased" : "decreased");
y++;
}
f = hasflag_real(lf->flags, F_XRAYVIS, B_TRUE, NULL, FROMRACE);
if (f) {
mvwprintw(mainwin, y, 0, "%s can see through walls.", you(lf));
y++;
}
@ -11845,8 +11883,8 @@ void showlfstats(lifeform_t *lf, int showall) {
mvwprintw(mainwin, y, 0, "%s identity is obscured.", your(lf));
y++;
}
f = lfhasknownflag(lf, F_AWARENESS);
if (f && (f->lifetime != FROMRACE)) {
f = hasflag_real(lf->flags, F_AWARENESS, B_TRUE, NULL, FROMRACE);
if (f) {
mvwprintw(mainwin, y, 0, "%s can see things which are behind %s.", you(lf), you(lf));
y++;
}
@ -12114,8 +12152,8 @@ void showlfstats(lifeform_t *lf, int showall) {
mvwprintw(mainwin, y, 0, "%s %s paralyzed.", you(lf), is(lf));
y++;
}
f = lfhasflag(lf, F_PHOTOMEM);
if (f && (f->known) && (f->lifetime != FROMRACE)) {
f = hasflag_real(lf->flags, F_PHOTOMEM, B_TRUE, NULL, FROMRACE);
if (f) {
mvwprintw(mainwin, y, 0, "%s do not forget your surroundings.", you(lf));
y++;
}
@ -12146,8 +12184,8 @@ void showlfstats(lifeform_t *lf, int showall) {
y++;
}
f = lfhasflag(lf, F_STENCH);
if (f && (f->known) && (f->lifetime != FROMRACE)) {
f = hasflag_real(lf->flags, F_STENCH, B_TRUE, NULL, FROMRACE);
if (f) {
mvwprintw(mainwin, y, 0, "%s %s emitting a foul stench, nauseating those nearby.", you(lf), is(lf));
y++;
}

5
lf.c
View File

@ -1828,7 +1828,7 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
break;
case SS_DEATH:
pleasegodmaybe(R_GODDEATH, getspelllevel(sid));
angergodmaybe(R_GODPURITY, getspelllevel(sid)*5, GA_SPELL);
angergodmaybe(R_GODLIFE, getspelllevel(sid)*5, GA_SPELL);
break;
case SS_FIRE:
pleasegodmaybe(R_GODFIRE, getspelllevel(sid)*2);
@ -17334,7 +17334,6 @@ void startlfturn(lifeform_t *lf) {
}
if (isdead(lf)) return;
// effects for/on your own flags
getflags(lf->flags, retflag, &nretflags, F_ATTACHEDTO, F_CANWILL, F_CHARMEDBY, F_CLIMBING, F_FEIGNFOOLEDBY,F_FLEEFROM,
F_GRABBEDBY, F_GRABBING, F_HIDING, F_BOOSTSPELL, F_FEIGNINGDEATH, F_HPDRAIN, F_INJURY,
@ -17554,6 +17553,8 @@ int steal(lifeform_t *lf, obpile_t *op, enum FLAG wantflag) {
} else if (!canpickup(lf, o, 1)) {
// can't pick it up
ok = B_FALSE;
} else if (hasflag(o->flags, F_NOSTEAL)) {
ok = B_FALSE;
} else if ((wantflag != F_NONE) && !hasflag(o->flags, wantflag)) {
// don't have the right flag
ok = B_FALSE;

11
map.c
View File

@ -6010,6 +6010,17 @@ object_t *hascloseddoor(cell_t *c) {
return NULL;
}
int hascrushableob(cell_t *c, lifeform_t *lf) {
object_t *o;
if (lfhasflag(lf, F_CAREFULMOVE)) {
return B_FALSE;
}
for (o = c->obpile->first ; o; o = o->next) {
if (cancrush(lf, o)) return B_TRUE;
}
return B_FALSE;
}
lifeform_t *haslf(cell_t *c) {
if (c->lf && !isdead(c->lf)) {
return c->lf;

1
map.h
View File

@ -121,6 +121,7 @@ int getslipperyness(cell_t *c, object_t **slipob);
cell_t *getstairdestination(object_t *o, int *madenewmap);
object_t *hasenterableobject(cell_t *c);
object_t *hascloseddoor(cell_t *c);
int hascrushableob(cell_t *c, lifeform_t *lf);
lifeform_t *haslf(cell_t *c);
int hasknownobject(cell_t *c);
int hasobject(cell_t *c);

89
move.c
View File

@ -281,8 +281,17 @@ int celldangerous(lifeform_t *lf, cell_t *cell, int onlyifknown, enum ERROR *err
}
if (include_nonobvious) {
for (o = cell->obpile->first ; o ; o = o->next) {
// don't walk on sharp objects without boots
if (!onlyifknown || (wis >= AT_AVERAGE)) {
if (wis >= AT_GTAVERAGE) {
// don't walk onto crushable objects if you worship ekrub
if (isplayer(lf) && cancrush(lf, o) && !lfhasflag(lf, F_CAREFULMOVE)) {
if (error) {
*error = E_AVOIDOB;
rdata = o;
}
return B_TRUE;
}
} if (wis >= AT_AVERAGE) {
// don't walk on sharp objects without boots
if (hasflag(o->flags, F_SHARP)) {
if (!getequippedob(lf->pack, BP_FEET)) {
if (error) {
@ -1098,6 +1107,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
lifeform_t *l;
int didmsg = B_FALSE;
flag_t *f;
enum FLAG flying;
int changedlev = B_FALSE;
room_t *preroom = NULL, *postroom = NULL;
int preshop = -1;
@ -1105,6 +1115,8 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
int prewater = B_FALSE;
int preseenbyplayer = B_FALSE;
vault_t *v;
flag_t *retflag[MAXCANDIDATES];
int nretflags,i;
assert(newcell);
@ -1268,7 +1280,8 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
}
// check ground objects
if (!isairborne(lf)) {
flying = isairborne(lf);
if (flying == F_NONE) {
for (o = newcell->obpile->first ; o ; o = nexto ) {
nexto = o->next;
@ -1320,42 +1333,36 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
}
}
f = hasflag(o->flags, F_CRUSHABLE);
if (f && !lfhasflag(lf, F_CAREFULMOVE)) {
enum LFSIZE crushsize;
crushsize = f->val[0];
if (!lfhasflag(lf, F_CAREFULMOVE) && cancrush(lf, o)) {
// crush it
getobname(o, obname, 1);
if (getlfsize(lf) >= crushsize) {
// crunch it broken glass
getobname(o, obname, 1);
// special case
if (o->type->id == OT_BROKENGLASS) {
if (o->amt > 1) {
char *newname;
// we want 'xx steps on some pieces of broken glass'
// not 'xx steps on 5 pieces of broken glass'
newname = makeplural(obname);
newname = strrep(newname, "a ", "some ", NULL);
strcpy(obname, newname);
free(newname);
}
// special case
if (o->type->id == OT_BROKENGLASS) {
if (o->amt > 1) {
char *newname;
// we want 'xx steps on some pieces of broken glass'
// not 'xx steps on 5 pieces of broken glass'
newname = makeplural(obname);
newname = strrep(newname, "a ", "some ", NULL);
strcpy(obname, newname);
free(newname);
}
if (isplayer(lf)) {
msg("You crush %s underfoot.",obname);
didmsg = B_TRUE;
} else if (haslos(player, newcell)) {
msg("%s crushes %s.",lfname, obname);
didmsg = B_TRUE;
}
// kill object which is being crushed.
removeob(o, o->amt);
if (isplayer(lf)) {
angergodmaybe(R_GODNATURE, 10, GA_ATTACKOBJECT);
}
continue;
}
if (isplayer(lf)) {
msg("You crush %s underfoot.",obname);
didmsg = B_TRUE;
} else if (haslos(player, newcell)) {
msg("%s crushes %s.",lfname, obname);
didmsg = B_TRUE;
}
// kill object which is being crushed.
removeob(o, o->amt);
if (isplayer(lf)) {
angergodmaybe(R_GODNATURE, 10, GA_ATTACKOBJECT);
}
continue;
} // end if crushable
if ((o->type->id == OT_VINE) && !hasjob(lf, J_DRUID)) {
@ -1516,6 +1523,16 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
msg("%s moves out of view.", lfname);
}
}
getflags(lf->flags, retflag, &nretflags, F_DAMAGEGROUNDOBS, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
// will we cause damage to ground objects ?
if (!isairborne(lf) || (f->val[2] == B_TRUE)) {
damageallobs(NULL, lf->cell->obpile, f->val[0], f->val[1], lf);
}
}
// status bar
if ((prespeed != postspeed) && isplayer(lf)) {
statdirty = B_TRUE;

View File

@ -1975,8 +1975,10 @@ void addobsinradius(cell_t *centre, int radius, int dirtype, char *name, int all
for (i = 0; i < ncells; i++) {
c = cell[i];
if (allowdupes || !hasob(c->obpile, ot->id)) {
addob(c->obpile, name);
if (!c->type->solid) {
if (allowdupes || !hasob(c->obpile, ot->id)) {
addob(c->obpile, name);
}
}
}
}
@ -4783,7 +4785,7 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
char localbuf[BUFLEN];
char buf2[BUFLEN];
char triedbuf[BUFLEN];
int venditem = B_FALSE;
int shopitem = B_FALSE;
flag_t *f;
brand_t *br;
int hasunknownmod = B_FALSE;
@ -4793,16 +4795,12 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
int nretflags = 0;
// default to normal name
if (hasflag(o->flags, F_VENDITEM)) {
venditem = B_TRUE;
if (hasflag(o->flags, F_SHOPITEM)) {
shopitem = B_TRUE;
}
where = getoblocation(o);
if (venditem) {
showall = B_TRUE;
}
f = hasflag(o->flags, F_TRAIL);
if (f) {
race_t *r = NULL;
@ -5357,8 +5355,9 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
}
// show if we've tried this
if (gamemode == GM_GAMESTARTED) {
if (!shopitem && (gamemode == GM_GAMESTARTED)) {
knowledge_t *k;
strcpy(triedbuf, "");
if (hasflag(o->flags, F_BEINGUSED)) {
@ -5423,8 +5422,7 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
}
// in a shop?
f = hasflag(o->flags, F_SHOPITEM);
if (f) {
if (shopitem) {
char pricebuf[BUFLEN];
// get price for _player_
snprintf(pricebuf, BUFLEN, " [$%d%s]", (int)getshopprice(o, player), o->pile->owner ? ", unpaid" : "");
@ -13183,7 +13181,7 @@ void timeeffectsob(object_t *o) {
object_t *splash;
ourcell = getoblocation(o);
// drip
if (!hasobwithflag(ourcell->obpile, F_DEEPWATER)) {
if (!ourcell->type->solid && !hasobwithflag(ourcell->obpile, F_DEEPWATER)) {
splash = addob(ourcell->obpile, "splash of water");
}
}
@ -13847,6 +13845,19 @@ int wepdullable(object_t *o) {
}
int cancrush(lifeform_t *lf, object_t *o) {
flag_t *f;
f = hasflag(o->flags, F_CRUSHABLE);
if (f) {
enum LFSIZE crushsize;
crushsize = f->val[0];
if (getlfsize(lf) >= crushsize) {
return B_TRUE;
}
}
return B_FALSE;
}
int willshatter(enum MATERIAL mat) {
switch (mat) {
case MT_GLASS:

View File

@ -289,6 +289,7 @@ int usefountaincharge(object_t *o, flag_t *drinkflag);
int validatehiddennames(void);
int validateobs(void);
int wepdullable(object_t *o);
int cancrush(lifeform_t *lf, object_t *o);
int willshatter(enum MATERIAL mat);
#endif

43
spell.c
View File

@ -4,6 +4,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ai.h"
#include "attack.h"
#include "defs.h"
#include "flag.h"
@ -5188,12 +5189,11 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else {
int newdir;
// make them face a random (different) direction
newdir = getrandomdirexcept(DT_COMPASS, target->facing);
newdir = getdiraway(targcell, caster->cell, NULL, B_FALSE, DT_ORTH, B_FALSE);
setfacing(target, newdir);
// ai loses target info
killflagsofid(target->flags, F_TARGETLF);
killflagsofid(target->flags, F_TARGETCELL);
loseaitargets(target);
// announce
if (isplayer(target)) {
@ -5205,11 +5205,6 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
msg("%s spins around to face %s.", tname, getdirname(target->facing));
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
// make them dizzy?
if (pctchance(power*10)) {
confuse(target, 2);
}
}
} else if (spellid == OT_S_DETECTLIFE) {
if (!target) {
@ -8363,9 +8358,11 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
for (o = op->first ; o ; o = nexto) {
nexto = o->next;
if ((getobunitweight(o) <= 5) ||
((isweapon(o)) && (isequipped(o))) ) {
poss[nposs++] = o;
if (!hasflag(o->flags, F_NOSTEAL)) {
if ((getobunitweight(o) <= 5) ||
((isweapon(o)) && (isequipped(o))) ) {
poss[nposs++] = o;
}
}
}
@ -8548,11 +8545,25 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
flag_t *f;
target = caster;
if (lfhasflag(target, F_NONCORPOREAL)) {
if (frompot) {
if (isplayer(caster)) nothinghappens();
} else {
fizzle(caster);
}
return B_TRUE;
}
if (isplayer(target) || cansee(player, target)) {
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
howlong = getspellduration(5,10,blessed) + (power/2);
f = addtempflag(target->flags, F_NONCORPOREAL, B_TRUE, NA, NA, NULL, howlong);
f->obfrom = OT_S_PASSWALL;
breakgrabs(target, B_TRUE, B_TRUE);
} else if ((spellid == OT_S_POLYMORPH) || (spellid == OT_S_SHAPESHIFT)) {
race_t *r = NULL;
@ -9004,7 +9015,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
f = hasflag(targob->flags, F_CHARGES);
if (!f) {
nothinghappens();
if (isplayer(caster)) nothinghappens();
return B_TRUE;
}
@ -9621,7 +9632,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
poss[nposs++] = caster->los[i];
}
}
// for each cell we can see...
// for each cell we can see... (including our own)
for (i = 0; i < caster->nlos; i++) {
c = poss[i];
if (c->lf) {
@ -9629,7 +9640,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
for (o = c->lf->pack->first ; o ; o = nexto) {
nexto = o->next;
if ( hasflag(o->flags, F_RODSHAPED) &&
isequipped(o) &&
(!isequipped(o) || (c->lf != caster)) &&
(o->blessed == B_UNCURSED) &&
!hasflag(o->flags, F_HASBRAND)) {
char obname[BUFLEN];
@ -9672,7 +9683,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
for (o = c->obpile->first ; o ; o = nexto) {
lifeform_t *snake = NULL;
nexto = o->next;
if (hasflag(o->flags, F_RODSHAPED) && !isblessed(o)) {
if ( hasflag(o->flags, F_RODSHAPED) &&
(o->blessed == B_UNCURSED) &&
!hasflag(o->flags, F_HASBRAND)) {
cell_t *newcell = NULL;
char obname[BUFLEN];