- [+] weakness spell should half melee damage.

- [+] quaffed a potion of polymorph self... and nothing happened!
- [+] only killing undead should please the god of life, not just
      killing anything evil
- [+] klikirak shouldn't get angry when you take cold damage!
- [+] fire sohuld convert flammable celltypes to another type:
    - [+] wood -> stone floor with pit
    - [+] carpet > stone
- [+] increase flamepillar range
- [+] warning before killing firebug on wood/carpet, if wisdom is
      at_high or above, and animal lore is high enough.
- [+] make f_twohanded only apply up to a given lf size.
    - [+] implement
    - [+] then add "istwohandedfor(wep, lf)"
    - [+] then fix up ob defs in data.c
- [+] unnatural growth/shrinkage spells should be temporary too (like
      potion)
- [+] random polymorph code
    - [+] stay at the same TR, or one higher/lower! (same for player
          random polymorph)  
- [+] elephant - friendly to mammoans
- [+] mammoth
- [+] pixie (then pixie, dryad sprite = sylvan / fae)
- [+] naiad / nixie
    - [+] blue 'n'
    - [+] low power charm to lure into water
    - [+] dagger/javelin
    - [+] throwing net
    - [+] resist magic 25%
- [+] droid - zapper
- [+] hoverscout (levitates, summons monsters)
- [+] skellion - floating flaming skull, scream attack, flame melee
- [+] fire primality should cast flame burst.
- [+] don't modify monster hp based on fitness.
- [+] storm primality / wind primality
    - [+] very fast
    - [+] 2 attacks - 1d5 each time. (pummel with debris / zapper)
    - [+] permenant windshield
    - [+] lesser:
        - [+] lightningbolt (lesser, 2d6)
        - [+] sleetstorm (lesser, 1-2 cold and slow movement)
    - [+] greater
        - [+] chain lightning (greater, 3d6)
        - [+] hailstorm (greater, 1d6 cold and 1d4-5d4 depending on
              power)
- [+] naiad (water sprite) - 'n' -blue
    - [+] good
    - [+] aquatic
    - [+] water spirit
    - [+] charm spell
- [+] ling parasite - green 'x'
    - [+] turns one corpse into a zombie (dies in the process)
- [+] add onion object.
- [+] roc
- [+] "crystal cur" - canine. only bashing works
    - [+] gems for corpses.
- [+] bug: monsters not using spells. fixed.
    - [+] test NOSPELLS bug with rapidivy
    - [+] test low IQ spells with storm primality
- [+] make hitdice be d8 rather than d4
    - [+] change F_HITDICE
    - [+] add constant HITDIESIDES
    - [+] redo all definitions in data.c
This commit is contained in:
Rob Pearce 2012-03-11 01:39:33 +00:00
parent a6aab1afe1
commit 0a7aeec362
19 changed files with 1186 additions and 388 deletions

2
ai.c
View File

@ -1292,7 +1292,7 @@ int ai_inventory_mgt(lifeform_t *lf, int *canattack) {
// do we have a better firearm ?
curgun = getfirearm(lf);
if (curwep && hasflag(curwep->flags, F_TWOHANDED)) {
if (curwep && istwohandedfor(curwep, lf)) {
// we are using a two handed weapon. don't
// check for guns.
} else {

View File

@ -257,6 +257,21 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
}
}
}
// high wisdom will prevent you from starting fires
if (getattrbracket(getattr(lf, A_WIS), A_WIS, NULL) >= AT_HIGH) {
if (hasflag(c->type->material->flags, F_FLAMMABLE)) {
if (getlorelevel(player, c->lf->race->raceclass->id) >= PR_BEGINNER) {
if (c->lf->race->id == R_FIREBUG) {
char victimname[BUFLEN],buf[BUFLEN];
getlfname(c->lf, victimname);
snprintf(buf, BUFLEN, "Attacking %s might start a fire - proceed anyway?",victimname);
if (!warnabout(buf)) {
return B_TRUE;
}
}
}
}
}
if (lfhasflag(lf, F_HASNEWLEVEL)) {
if (!warnabout(TEXT_WARN_ATTACK_NOXP)) {
@ -2258,6 +2273,13 @@ int getdamroll(object_t *o, lifeform_t *victim, flag_t *damflag) {
}
}
if (o->pile->owner) {
int pct;
sumflags(o->pile->owner->flags, F_MELEEDAMPCT, &pct, NULL, NULL);
if (pct != 0) {
dam = pctof(f->val[0], dam);
}
}
return dam;
}

975
data.c

File diff suppressed because it is too large Load Diff

Binary file not shown.

30
data/vaults/antnest.vlt Normal file
View File

@ -0,0 +1,30 @@
@id:antnest
@map
##ddddddd##
#dd.....dd#
dd.......dd
O.........d
dd.......dd
#dd.....dd#
##ddddddd##
@end
@legend
#:cell:SOLID
d:cell:dirt wall
.:cell:dirt
O:exit
@end
@flags
scatter(3,1,-4,-2) ob:random food:7-10
scatter(3,1,-4,-2) mon:queen ant:1:100
scatter(2,1,-2,-2) cell:dirt wall:5-6
goesin:dungeon
goesin:cave
mayrotate
rarity:uncommon
maintainedge
entertext:You enter a giant ant nest!
@end

View File

@ -0,0 +1,28 @@
@id:troll_cave
@map
###########
####....###
###......##
.O........#
###......##
####....###
###########
@end
@legend
#:cell:SOLID
O:ob:boulder
O:exit
@end
@flags
scatter(3,1,-4,-2) ob:cooked corpse:7-10
scatter(3,1,-4,-2) ob:bone:3-5
scatter(3,1,-4,-2) mon:random troll:2-4:100
goesin:dungeon
goesin:cave
mayrotate
rarity:veryrare
maintainedge
@end

View File

@ -3,9 +3,9 @@
####x####
#.......#
#.ww_ww.#
#.ww.ww.#
x._.p._.x
#.ww.ww.#
#.ww_ww.#
x.__p__.x
#.ww_ww.#
#.ww_ww.#
#.......#
####x####

57
defs.h
View File

@ -383,6 +383,8 @@ enum SHOPACTION {
#define RANDOM (-2610)
#define AUTO (-7654)
#define HEAVYWEPKG (5)
#define HITDIESIDES (8)
// how quickly the game clock increments
// 1 = roughly 30 secs per turn
@ -957,7 +959,9 @@ enum RACE {
R_ANDROID,
R_BOTRIOT,
R_BOTSECURITY,
R_DROID,
R_FLAMETURRET,
R_HOVERSCOUT,
// human monsters
R_BANDITLDR,
R_BANDIT,
@ -1007,6 +1011,7 @@ enum RACE {
R_LIZARDMAN,
R_MALIK,
R_MINOTAUR,
R_NAIAD,
R_OGRA,
R_OGRE,
R_OGREWARHULK,
@ -1018,11 +1023,14 @@ enum RACE {
R_ORCN,
R_ORK,
R_PEGASUS,
R_PIXIE,
R_POLTERGEIST,
R_PRIMALFIRE,
R_PRIMALFIREL,
R_PRIMALSTONE,
R_PRIMALSTONEL,
R_PRIMALSTORM,
R_PRIMALSTORML,
R_SANDMAN,
R_SASQUATCH,
R_SATYR,
@ -1070,10 +1078,12 @@ enum RACE {
R_BEARGRIZZLY,
R_BILCO,
R_CHICKEN,
R_CRYSTALCUR,
R_DOG,
R_DOGBLINK,
R_DOGDEATH,
R_DOGWAR,
R_ELEPHANT,
R_GYRFALCON,
R_HAWK,
R_HAWKYOUNG,
@ -1081,9 +1091,11 @@ enum RACE {
R_HAWKFROST,
R_FROG,
R_LEECH,
R_MAMMOTH,
R_NEWT,
R_PORCUPINE,
R_RAT,
R_ROC,
R_SLUG,
R_SNAIL,
R_SNAKE,
@ -1128,11 +1140,12 @@ enum RACE {
R_GRIDDLER,
R_LURKINGHORROR,
R_ICEDEMON,
R_NECRONTRAPPER,
R_NECRONREAPER,
R_NECRONSOWER,
R_NECRONEXTERMINATOR,
R_NECRONHARVESTER,
R_LINGEXTERMINATOR,
R_LINGHARVESTER,
R_LINGPARASITE,
R_LINGREAPER,
R_LINGSOWER,
R_LINGTRAPPER,
R_QUASIT,
// undead
R_GHAST,
@ -1144,6 +1157,7 @@ enum RACE {
R_REVENANT,
R_SKELETON,
R_SKELETONFIRE,
R_SKELLION,
R_WRAITHICE,
R_ZOMBIE,
// special
@ -1237,6 +1251,7 @@ enum MATERIAL {
MT_SILVER = 28,
MT_DRAGONWOOD = 29,
MT_DIRT = 30,
MT_CRYSTAL = 31,
};
// Object Types
@ -1351,6 +1366,7 @@ enum OBTYPE {
OT_MUSHROOMTOAD,
OT_MUSHROOMSTUFFED,
OT_NUT,
OT_ONION,
OT_PASSIONFRUIT,
OT_POISONSAC,
OT_PSITRUFFLE,
@ -1377,6 +1393,7 @@ enum OBTYPE {
OT_POT_ELEMENTIMMUNE,
OT_POT_ETHEREALNESS,
OT_POT_EXPERIENCE,
OT_POT_FISHLUNG,
OT_POT_FURY,
OT_POT_GASEOUSFORM,
OT_POT_GROWTH,
@ -1827,6 +1844,7 @@ enum OBTYPE {
OT_MELTEDWAX,
OT_SOGGYPAPER,
OT_FLESHCHUNK,
OT_TUSK,
// trail objects
OT_FOOTPRINT,
OT_SCENT,
@ -1971,7 +1989,9 @@ enum OBTYPE {
OT_CLAWS,
OT_DRILL,
OT_FISTS,
OT_AIRFISTS,
OT_HOOKHAND, // for pirate
OT_SAWBLADE,
OT_STING,
OT_BUTT,
OT_HOOF,
@ -1979,12 +1999,14 @@ enum OBTYPE {
OT_TEETH,
OT_TEETHSM,
OT_TENTACLE,
OT_TRAMPLE,
OT_TONGUE,
OT_ZAPPER,
// monster weapons
OT_ACIDATTACK,
OT_TOUCHBURN,
OT_TOUCHCHILL,
OT_TOUCHCONFUSE,
OT_TOUCHHOLY,
OT_TOUCHNECROTIC,
OT_TOUCHPARALYZE,
@ -2370,7 +2392,7 @@ enum FLAG {
F_HITCONFER, // hitting with this gives flagid=v0
// with timeleft = text ("min-max")
// unless you pass a val1 skillcheck, diff val2
// if val1 = SC_NONE, no check.
// if val1 = NA, no check.
// MUST ALSO HAVE HITCONFERVALS.
F_HITCONFERVALS,// specifies values for conferred flag.
F_ACTIVATED, // val0 = is this object turned on?
@ -2599,7 +2621,8 @@ enum FLAG {
F_ARMOURIGNORE, // armour has no effect
F_ARMOURPIERCE, // goes through armour. armour can't reduce the
// damage dealt to less than v0.
F_TWOHANDED, // weapon uses two hands to weild
F_TWOHANDED, // weapon uses two hands to weild, if lf is size v0
// or smaller.
F_NEEDSSPACE, // weapon needs space to swing - 75% chance of hitting
// a wall if used with < 3 empty cells around you
// gun flags
@ -2701,6 +2724,7 @@ enum FLAG {
// OR
// eating this object gives it.
// player only flags
F_DONEBURNMSG, // tells the game not to say 'the {celltype} burns!'
F_DONEDARKMSG, // tells the game not to say 'it is very dark here'
F_DONELISTEN, // supress further 'you hear xx' messages this turn.
// lifeform flags / lf flags / monster flags
@ -2754,6 +2778,7 @@ enum FLAG {
F_HASBEENMOVED, // an object moved this lf since their last turn.
F_HOTFEET, // target takes v0 damage of type v1 unless they move.
// text = killed by xxx
F_MELEEDAMPCT, // all melee damage is changed to v0% of value.
F_WASROBBED, // your stuff was stolen while you were
// unconscious. announce it when you wake up.
F_WOKENBY, // at the start of your next turn, you will wake up
@ -3020,9 +3045,16 @@ enum FLAG {
F_SPELLCASTTEXT, // text is announcement for spellcast
// if text is empty, then don't announce
// this lf's spell casting at all.
// if v0 != OT_NONE, only use text for spellid v0
// if v0 != OT_NONE, only use text
// for spellid v0
// if v2 is 'appendyou' " at xxx" will
// be appended.
F_SPELLCASTCONTTEXT, // text is announcement for "xx continues
// casting a spell".
// if v0 != OT_NONE, only use text
// for spellid v0
F_SPELLCASTTIME, // override F_CASTINGTIME to v0 when this lf
// casts spellid v1.
F_AISPELLTARGETOVERRIDE, // when casting spellid v0, this lf will
// use v1 (ST_xxx) instead of what the AICASTTOxxx
// flag specifies.
@ -3041,8 +3073,9 @@ enum FLAG {
F_NUMAPPEAR, // when randomly appearing, can have > 1. val[0] = min, val[1] = max
F_MINIONS, // val0 % chance of appearing with v1-v2 lf of type text
F_HITDICE, // text = xdy+z to roll for maxhp per level.
// if v0 is set, this overrides text as maxhp.
F_HITDICE, // v0 = number of hitdice to roll per level
// v1 = +xxx
// v2 = hitdie sides, if NA, use HITDIESIDES
F_TR, // v0 = threat rating of this race.
F_MAXHPMOD, // maxhp = pctof(v0, maxhp)
F_MPDICE, // val0: # d4 to roll for maxmp per level. val1: +xx
@ -3115,7 +3148,8 @@ enum FLAG {
F_NOINJURIES, // this race cannot sustain injuries.
F_NOATTACK, // this lf can't attack
F_NOPACK, // this race cannot hold objects
F_NOSPELLS, // this race cannot cast spells
F_NOSPELLS, // this race cannot cast spells (except for ones
// with FROMRACE)
F_NOPRINTS, // this race doesn't leave footprints
F_INDUCEFEAR, // causes fear when you attack it
F_POISONCORPSE, // lf's corpse will be poisonous
@ -3164,6 +3198,7 @@ enum FLAG {
F_CAFFEINATED, // can't sleep.
F_CANEATRAW, // lf can eat raw food with no issues
F_CANCAST, // can cast the spell val0 (need MP)
F_CASTWITHOUTIQ, // can cast spells even eith low iq.
F_CANHEARLF, // you can hear lifeform id v0 (show their glyph)
// this flag does not get announced.
F_LOWHPABIL, // will automatically use the ability v0 when

6
doc/add_eatconfer.txt Normal file
View File

@ -0,0 +1,6 @@
data.c:
add the f_eatconfer flag to the race.
lf.c:
in eat(), specify what happens when you eat the corpse but
already have this flag.

View File

@ -6,11 +6,12 @@ UNI_SOLID = deep water
^ = trap / dangerous thing
) = weapon
------------------------------------------------
A = avian / bird
a = ant
A = avian / bird
b = small roBot
B = bat
c = cockatrice / chicken / small bird
C = celestial / divine ?
C = celestial / divine ?
d = canine/dog
D = ?
e = eye or floating thing
@ -29,7 +30,7 @@ L = lich, or other powerful undead ?
m = mutant / magic creature
M = mummy
n = small humanoid / nymph / sprite
N = necron
N = ling / alieN creature
o = orc
O = monstrous humanoid (ie. ogre)
P = gastropod
@ -40,7 +41,9 @@ r = rodent
R = robot
s = snake
S = spider
t = troll
T = walkingtree-like monster (dryad, treant)
u = ? make this be horse? if so, change pegasus.
U = unearthly/horrific creature
v = ?
V = vampire
@ -48,7 +51,7 @@ w = small wyrm
W = large wyrm
x = small creature/monster
X = unknown thing!
y/Y = air related creatures like clouds of gas, air elemental
y/Y = air/dust related creatures like clouds of gas, air elemental, sandman
z = lizard-like creature
Z = undead
; = fish

14
flag.c
View File

@ -1383,6 +1383,20 @@ void timeeffectsflag(flag_t *f, int howlong) {
}
}
int flagtomaxhp(flag_t *f) {
int hp;
int nsides = HITDIESIDES;
if (f->val[2] > 0) {
nsides = f->val[2];
}
hp = f->val[0] * nsides;
if (f->val[1] > 0) {
hp += f->val[1];
}
return hp;
}
cell_t *getflagpilelocation(flagpile_t *fp) {
cell_t *where = NULL;
// everyone who can see this cell recalcs their los

1
flag.h
View File

@ -23,6 +23,7 @@ int flagcausesloscalc(enum FLAG fid);
int flagcausesredraw(lifeform_t *lf, enum FLAG fid);
int flagcausesstatredraw(lifeform_t *lf, enum FLAG fid);
int flagstacks(enum FLAG fid);
int flagtomaxhp(flag_t *f);
cell_t *getflagpilelocation(flagpile_t *fp);
int getflags(flagpile_t *fp, flag_t **retflag, int *nretflags, ... );
flag_t *hasflag(flagpile_t *fp, int id);

29
io.c
View File

@ -5589,9 +5589,20 @@ char *makedesc_ob(object_t *o, char *retbuf) {
if (isknown(o)) {
// weapons?
if (isfirearm(o)) {
flag_t *ff, *ff2;
sprintf(buf, "It is a %s firearm.\n", hasflag(o->flags, F_TWOHANDED) ? "two-handed" : "single handed");
flag_t *ff, *ff2,*twohandf;
twohandf = hasflag(o->flags, F_TWOHANDED);
sprintf(buf, "It is a %s firearm.\n", twohandf ? "two-handed" : "single handed");
strncat(retbuf, buf, HUGEBUFLEN);
if ((twohandf->val[0] > 0) && (twohandf->val[0] < SZ_ENORMOUS)) {
char sizebuf[BUFLEN];
sprintf(sizebuf, "%s", getsizetext(twohandf->val[0] + 1));
capitalise(sizebuf);
sprintf(buf2, "@%s creatures can weild it in one hand.\n", sizebuf);
strncat(retbuf, buf2, HUGEBUFLEN);
}
f = hasflag(o->flags, F_ACCURACY);
if (f) {
int acc,accnum;
@ -5645,12 +5656,15 @@ char *makedesc_ob(object_t *o, char *retbuf) {
sprintf(buf, "@It takes %d turn%s to reload.\n", ff2->val[0], (ff2->val[0] == 1) ? "" : "s");
strncat(retbuf, buf, HUGEBUFLEN);
} else if (isweapon(o) && isknown(o)) {
flag_t *damflag;
flag_t *damflag,*twohandf;
int delay;
int critchance;
twohandf = hasflag(o->flags, F_TWOHANDED);
snprintf(buf, BUFLEN, "%s %s weapon",
(o->type->obclass->id == OC_WEAPON) ? "It is a" : "It can be used as a",
hasflag(o->flags, F_TWOHANDED) ? "two-handed" : "single handed");
twohandf ? "two-handed" : "single handed");
damflag = hasflag(o->flags, F_DAM);
if (damflag) {
//int bonus = 0;
@ -5688,6 +5702,13 @@ char *makedesc_ob(object_t *o, char *retbuf) {
strcat(buf, buf2);
//dicetotext(f->val[0], f->val[1], f->val[2], NULL, NULL, dicebuf, NULL);
if ((twohandf->val[0] > 0) && (twohandf->val[0] < SZ_ENORMOUS)) {
char sizebuf[BUFLEN];
sprintf(sizebuf, "%s", getsizetext(twohandf->val[0] + 1));
capitalise(sizebuf);
sprintf(buf2, "@%s creatures can weild it in one hand.\n", sizebuf);
strcat(buf, buf2 );
}
sprintf(buf2, "@It has a base Damage Rating of %d",dr);
strcat(buf, buf2);

173
lf.c
View File

@ -358,7 +358,7 @@ int calcxp(lifeform_t *lf) {
// -- hitdice
f = lfhasflag(lf, F_HITDICE);
if (f) {
maxhdroll = roll(f->text);
maxhdroll = flagtomaxhp(f);
} else {
maxhdroll = 4;
}
@ -634,17 +634,21 @@ int cancast(lifeform_t *lf, enum OBTYPE oid, int *mpcost) {
} else if ((f = lfhasflagval(lf, F_CANCAST, oid, NA, NA, NULL)) != NULL) {
int cost,power;
// override!
// can only cast innate racial spels?
if ((ot->obclass->id == OC_SPELL) && lfhasflag(lf, F_NOSPELLS)) {
reason = E_NOSPELLS;
return B_FALSE;
if (f->lifetime != FROMRACE) {
reason = E_NOSPELLS;
return B_FALSE;
}
}
// need >animal intelligence to cast spells
if (ot->obclass->id == OC_SPELL) {
if (getattrbracket(getattr(lf, A_IQ), A_IQ, NULL) <= IQ_ANIMAL) {
reason = E_LOWIQ;
return B_FALSE;
if (!lfhasflag(lf, F_CASTWITHOUTIQ)) {
reason = E_LOWIQ;
return B_FALSE;
}
}
}
@ -1441,7 +1445,7 @@ int canweild(lifeform_t *lf, object_t *o) {
flag_t *retflag[MAXCANDIDATES];
int nretflags;
weildloc = getweildloc(o, &otherloc, NULL);
weildloc = getweildloc(o, lf, &otherloc, NULL);
// already weilding it?
if (o && isequipped(o)) {
@ -1501,7 +1505,7 @@ int canweild(lifeform_t *lf, object_t *o) {
if (o) {
int i;
getflags(o->flags, retflag, &nretflags, F_ATTREQ, F_TWOHANDED, F_NONE);
getflags(o->flags, retflag, &nretflags, F_ATTREQ, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f->id == F_ATTREQ) {
@ -1509,18 +1513,20 @@ int canweild(lifeform_t *lf, object_t *o) {
if (!meetsattreq(lf, f, o, NULL)) {
return B_FALSE;
}
} else if (f->id == F_TWOHANDED) {
}
}
if (istwohandedfor(o, lf)) {
if (getlfsize(lf) <= f->val[0]) {
// need both hands free...
if (!hasbp(lf, otherloc)) {
reason = E_NOHANDS;
return B_FALSE;
}
}
}
}
reason = E_OK;
// trying to fight unarmed, but no unarmed attack?
@ -1881,7 +1887,10 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
}
// cast the spell. does it take time?
f = hasflag(sp->flags, F_CASTINGTIME);
f = hasflag(sp->flags, F_CASTINGTIME) ;
if (!f) {
f = lfhasflagval(lf, F_SPELLCASTTIME, NA, sp->id, NA, NULL);
}
if (f && !fromob) {
int castingtime;
char tempbuf[BUFLEN];
@ -2250,6 +2259,7 @@ int checkfordrowning(lifeform_t *lf, object_t *o) {
addflag(lf->flags, F_NODEATHANNOUNCE, B_TRUE, NA, NA, NULL);
lf->hp = 0;
getobnametruebase(o, obname, o->amt);
lf->lastdamtype = DT_DIRECT;
setlastdam(lf, obname);
setkillverb(lf, "Drowned");
} else {
@ -2943,7 +2953,7 @@ void die(lifeform_t *lf) {
awardxpfor(lf,100);
if ((getalignment(lf) == AL_EVIL) || isundead(lf)) {
pleasegodmaybe(R_GODPURITY, 5);
pleasegodmaybe(R_GODLIFE, 10);
if (isundead(lf)) pleasegodmaybe(R_GODLIFE, 10);
} else if (getalignment(lf) == AL_GOOD) {
pleasegodmaybe(R_GODDEATH, 5);
} else { // ie. neutral
@ -3415,12 +3425,9 @@ void dumpmonsters(void) {
int thishd;
thishd = gettrrace(r);
if (thishd == wanthd) {
int ndice,nsides,bonus,min,max;
int max;
f = hasflag(r->flags, F_HITDICE);
texttodice(f->text ? f->text : DEF_HITDICE, &ndice,&nsides,&bonus);
min = ndice + bonus;
max = (ndice*nsides) + bonus;
max = flagtomaxhp(f);
dblog("\t%s (%d hp)",r->name, max);
}
}
@ -3940,13 +3947,29 @@ int eat(lifeform_t *lf, object_t *o) {
getobname(o, obname, 1);
getlfname(lf, lfname);
// is this a corpse?
cf = hasflag(o->flags, F_CORPSEOF);
if (cf) {
corpserace = findrace(cf->val[0]);
// special case
if (lf->race->id == R_LINGPARASITE) {
if (isplayer(lf)) {
msg("You crawl inside %s.", obname);
} else if (cansee(player, lf)) {
msg("%s crawls inside %s.", lfname, obname);
}
// die, but animate the zombie!
addflag(lf->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL);
addflag(lf->flags, F_NODEATHANNOUNCE, B_TRUE, NA, NA, NULL);
setlastdam(lf, "merging with a corpse");
lf->lastdamtype = DT_DIRECT;
lf->hp = 0;
makezombie(o);
return B_FALSE;
}
}
// get total nutrition
nutrition = getnutrition(o);
@ -5854,6 +5877,7 @@ void gainxp(lifeform_t *lf, long amt) {
amtneeded = getspforpoint(lf);
assert(amtneeded > 0);
// would you gain more than 5 levels? probably a bug!
if (((lf->skillxp + amt) / amtneeded) >= 3) {
raise(SIGINT);
}
@ -7068,11 +7092,6 @@ int gethearingrange(lifeform_t *lf) {
int gettrrace(race_t *r) {
flag_t *f;
f = hasflag(r->flags, F_TR);
/*
int ndice,nsides,bonus;
texttodice(f->text ? f->text : DEF_HITDICE, &ndice,&nsides,&bonus);
return ((ndice*nsides)+bonus) / 4;
*/
return f->val[0];
}
@ -7727,7 +7746,6 @@ int getnoisedetails(lifeform_t *lf, enum NOISETYPE nid, flag_t *noiseflag,
return B_FALSE;
}
} else if (nid == N_SONICBOLT) {
if (volume) *volume = 5;
if (heartext) strcpy(heartext, "a ear-splitting burst of sound!");
if (seetext) strcpy(seetext, "emits an ear-splitting burst of sound!");
@ -10597,6 +10615,11 @@ void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp) {
// give one extra rank of skill in this weapon
sk = getobskill(o->flags);
giveskill(lf, sk->id);
// warriors get another rank
if (hasjob(lf, J_WARRIOR)) {
giveskill(lf, sk->id);
}
}
}
} // end if lf && selectweapon
@ -11095,7 +11118,9 @@ int injure(lifeform_t *lf, enum BODYPART where, enum DAMTYPE damtype) {
} else if (cansee(player, lf)) {
msg("^%c%s%s heart is pierced!", getlfcol(lf, CC_VBAD), lfname, getpossessive(lfname));
}
if (lf->hp > 0) lf->hp = 0;
if (lf->hp > 0) {
lf->hp = 0;
}
} else {
inj = IJ_CHESTBLEED; desc = strdup("chest is bleeding^damage from enemies is increased"); break;
}
@ -12171,11 +12196,12 @@ int isfreebp(lifeform_t *lf, enum BODYPART bp) {
// check for 2handed weapons in other hand too
if (bp == BP_WEAPON) otherbp = BP_SECWEAPON;
else otherbp = BP_WEAPON;
o = hasobwithflagval(lf->pack, F_EQUIPPED, otherbp, NA, NA, NULL);
if (o && hasflag(o->flags, F_TWOHANDED)) {
return B_FALSE;
if (o) {
if (istwohandedfor(o, lf)) {
return B_FALSE;
}
}
}
return B_TRUE;
@ -12910,6 +12936,9 @@ object_t *addtrail(lifeform_t *lf, cell_t *where, int dir, int doprints, int dos
if (lfhasflag(lf, F_NOPRINTS)) {
doprints = B_FALSE;
}
if (getraceclass(lf) == RC_ROBOT) {
doscents = B_FALSE;
}
// footprints first
if (doprints) {
@ -13132,9 +13161,15 @@ lifeform_t *makezombie(object_t *o) {
lf = addlf(where, r->id, 1);
addflag(lf->flags, F_LFSUFFIX, B_TRUE, NA, NA, "zombie");
addflag(lf->flags, F_GLYPH, C_GREY, 'Z', NA, NULL);
killflagsofid(lf->flags, F_GLYPH);
addflag(lf->flags, F_GLYPH, C_BLUE, 'Z', NA, NULL);
addflag(lf->flags, F_UNDEAD, B_TRUE, NA, NA, NULL);
killflagsofid(lf->flags, F_CORPSETYPE);
killflagsofid(lf->flags, F_EXTRACORPSE);
addflag(lf->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL);
killflagsofid(lf->flags, F_DTIMMUNE);
killflagsofid(lf->flags, F_DTVULN);
killflagsofid(lf->flags, F_DTRESIST);
addflag(lf->flags, F_DTIMMUNE, DT_COLD, NA, NA, NULL);
addflag(lf->flags, F_DTIMMUNE, DT_POISONGAS, NA, NA, NULL);
addflag(lf->flags, F_DTIMMUNE, DT_DECAY, NA, NA, NULL);
@ -13152,6 +13187,9 @@ lifeform_t *makezombie(object_t *o) {
addflag(lf->flags, F_HEADLESS, B_TRUE, NA, NA, NULL);
}
killflagsofid(lf->flags, F_XPVAL);
addflag(lf->flags, F_XPVAL, 0, NA, NA, NULL);
killflagsofid(lf->flags, F_WANTSBETTERWEP);
killflagsofid(lf->flags, F_WANTSBETTERARM);
killflagsofid(lf->flags, F_WANTSOBFLAG);
@ -13166,6 +13204,9 @@ lifeform_t *makezombie(object_t *o) {
addflag(lf->flags, F_ACTIONSPEED, SP_SLOW, NA, NA, NULL);
lf->baseatt[A_IQ] = rollattr(IQ_MINDLESS);
lf->att[A_IQ] = lf->baseatt[A_IQ];
killflagsofid(lf->flags, F_REVIVETIMER);
// no magic
lf->maxmp = 0;
@ -14297,6 +14338,8 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml
f->val[0] -= amt;
// they die when their FAKE hp drops below 0
if (f->val[0] <= 0) {
setlastdam(lf, "disappation");
lf->lastdamtype = DT_DIRECT;
lf->hp = 0;
}
} else {
@ -14415,7 +14458,7 @@ void losehpeffects(lifeform_t *lf, int dam, enum DAMTYPE damtype, lifeform_t *fr
}
}
}
if (fromlf) {
if (fromlf && isplayer(fromlf)) {
angergodmaybe(R_GODFIRE, 25, GA_HERESY);
}
} else if (damtype == DT_FIRE) {
@ -18258,6 +18301,7 @@ void startlfturn(lifeform_t *lf) {
killflagsofid(lf->flags, F_JUSTENTERED);
killflagsofid(lf->flags, F_UNSEENATTACKER);
killflagsofid(lf->flags, F_DONELISTEN);
killflagsofid(lf->flags, F_DONEBURNMSG);
killflagsofid(lf->flags, F_NOSWAP);
movedlastturn = 0;
movedlastturn += killflagsofid(lf->flags, F_HASBEENMOVED);
@ -19296,7 +19340,6 @@ void startlfturn(lifeform_t *lf) {
f->val[1]--;
if (f->val[1] <= 0) {
resizelf(lf, f->val[0]);
killflag(f);
continue;
}
}
@ -20401,7 +20444,7 @@ void unsummon(lifeform_t *lf, int vanishobs) {
addflag(lf->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL);
f = lfhasflag(lf, F_UNSUMMONOB);
if (f) {
if (f && strlen(f->text)) {
strcpy(unsummonob, f->text);
} else {
strcpy(unsummonob, "puff of smoke");
@ -20940,6 +20983,14 @@ int validateraces(void) {
goterror = B_TRUE;
}
if (hasflag(r->flags, F_CANCAST) && !hasflag(r->flags, F_CASTWITHOUTIQ)) {
if (getattr(lf, A_IQ) <= IQ_ANIMAL) {
printf("ERROR in race '%s' - has F_CANCAST but iq is too low. might need f_castwithoutiq?\n", r->name);
goterror = B_TRUE;
}
}
for (f = r->flags->first ; f ; f = f->next) {
if (f->id == F_RNDSPELLCOUNT) {
if (!hasflag(r->flags, F_RNDSPELLSCHOOL) && !hasflag(r->flags, F_RNDSPELLPOSS)) {
@ -21094,11 +21145,14 @@ int resizelf(lifeform_t *lf, enum LFSIZE newsize) {
object_t *o,*nexto;
getlfname(lf, lfname);
killflagsofid(lf->flags, F_SIZETIMER);
f = hasflag(lf->race->flags, F_SIZE);
if (f) {
racesize = f->val[0];
}
origsize = getlfsize(lf);
if (origsize == newsize) {
@ -21136,9 +21190,9 @@ int resizelf(lifeform_t *lf, enum LFSIZE newsize) {
for (o = lf->pack->first ; o ; o = nexto) {
nexto = o->next;
// object is now the wrong size?
if (isequipped(o) && isarmour(o)) {
if (!armourfits(lf, o, NULL)) {
if (isequipped(o)) {
// object is now the wrong size?
if (isarmour(o) && !armourfits(lf, o, NULL)) {
char obname[BUFLEN];
getobname(o, obname, o->amt);
if (isplayer(lf)) {
@ -21150,12 +21204,47 @@ int resizelf(lifeform_t *lf, enum LFSIZE newsize) {
unequipeffects(lf, o);
if (isplayer(lf)) statdirty = B_TRUE; // might have impacted AR
}
if (isweapon(o)) {
flag_t *f;
// wasn't twohanded before, but is now?
if (istwohandedfor(o, lf)) {
f = hasflag(o->flags, F_TWOHANDED);
if ((f->val[0] > 0) && (origsize > f->val[0])) {
if (isplayer(lf)) {
char obname[BUFLEN];
getobname(o, obname, o->amt);
msg("Your %s %s now too heavy to weild in one hand!", noprefix(obname),
(o->amt == 1) ? "is" : "are");
}
// just drop it - this avoids complication if you have something in your
// other hand.
drop(o, o->amt);
continue;
}
} else {
// was twohanded before, but isn't now?
f = hasflag(o->flags, F_TWOHANDED);
if ((f->val[0] < 0) || (origsize <= f->val[0])) {
flag_t *f2;
if (isplayer(lf)) {
char obname[BUFLEN];
getobname(o, obname, o->amt);
msg("You can now weild your %s in one hand!", noprefix(obname));
}
f2 = hasflagval(o->flags, F_EQUIPPED, BP_SECWEAPON, NA, NA, NULL);
if (f2) killflag(f2);
}
}
}
}
// object is now too big to hold?
if (canpickup(lf, o, o->amt) == E_TOOBIG) {
drop(o, o->amt);
continue;
if (!canpickup(lf, o, o->amt)) {
if (reason == E_TOOBIG) {
drop(o, o->amt);
continue;
}
}
}
@ -21877,7 +21966,7 @@ int weild(lifeform_t *lf, object_t *o) {
}
// anything else weilded?
weildloc = getweildloc(o, &otherloc, &twohanded);
weildloc = getweildloc(o, lf, &otherloc, &twohanded);
// firearm in regular hand?
// note: this is the same logic as in canweild()
@ -21903,7 +21992,7 @@ int weild(lifeform_t *lf, object_t *o) {
// ask if we want to use our other hand.
if (!twohanded && hasbp(lf, otherloc)) {
oo = getequippedob(lf->pack, weildloc);
if (getskill(lf, SK_TWOWEAPON) && oo && !hasflag(oo->flags, F_TWOHANDED)) {
if (getskill(lf, SK_TWOWEAPON) && oo && !istwohandedfor(oo, lf)) {
char ch;
if (isplayer(lf)) {
char buf2[BUFLEN];
@ -22047,7 +22136,7 @@ int weild(lifeform_t *lf, object_t *o) {
// now weild this
addflag(o->flags, F_EQUIPPED, weildloc, -1, -1, NULL);
if (hasflag(o->flags, F_TWOHANDED)) {
if (istwohandedfor(o, lf)) {
addflag(o->flags, F_EQUIPPED, otherloc, -1, -1, NULL);
}

22
map.c
View File

@ -48,6 +48,8 @@ extern enum GAMEMODE gamemode;
extern int needredraw;
extern int noredraw;
extern int notime;
extern long curtime;
cell_t *addcell(map_t *m, int x, int y) {
@ -218,7 +220,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int randomjobok
if (nadded) *nadded = 0;
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
/*if gamemode == GM_GAMESTARTED checkallflags(player->cell->map); */
// ie. don't create mosnters on closed doors!
if (!cellwalkable(NULL, c, NULL)) {
@ -279,10 +281,10 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int randomjobok
}
}
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
//if gamemode == GM_GAMESTARTED checkallflags(player->cell->map); // debugging
lf = addlf(c, r->id, getrandommonlevel(r, c->map));
if (db) dbtime("finished lf addition");
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
//if gamemode == GM_GAMESTARTED checkallflags(player->cell->map); // debugging
if (lf) {
flag_t *f;
@ -348,7 +350,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int randomjobok
}
generatealignment(lf);
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
//if gamemode == GM_GAMESTARTED checkallflags(player->cell->map); // debugging
if (autogen) {
// sometimes start off hiding/asleep in new maps
@ -398,6 +400,8 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int randomjobok
// adjust hostility based on player's race
if ((player->race->id == R_AVIAD) && hasflag(lf->flags, F_AVIAN)) {
killflagsofid(lf->flags, F_HOSTILE);
} else if ((player->race->id == R_MAMMOAN) && (lf->race->id == R_ELEPHANT)) {
killflagsofid(lf->flags, F_HOSTILE);
} else {
// adjust hostility based on player's alignment
switch (getalignment(player)) {
@ -423,7 +427,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int randomjobok
}
lf->born = B_TRUE;
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
//if gamemode == GM_GAMESTARTED checkallflags(player->cell->map); // debugging
// appears in groups?
if (db) dbtime("handling groups");
@ -5473,6 +5477,14 @@ void finalisemonster(lifeform_t *lf, lifeform_t *leader, flagpile_t *wantflags,
if (lfhasflag(lf, F_ASLEEP)) {
killflagsofid(lf->flags, F_FLYING);
killflagsofid(lf->flags, F_HIDING);
} else {
if (hasflag(lf->race->flags, F_NATURALFLIGHT) && !lfhasflag(lf, F_FLYING)) {
if (cancast(lf, OT_S_FLIGHT, NULL)) {
notime = B_TRUE;
castspell(lf, OT_S_FLIGHT, lf, NULL, lf->cell, NULL, NULL);
notime = B_FALSE;
}
}
}
// automatic spells

39
nexus.c
View File

@ -748,6 +748,7 @@ void donextturn(map_t *map) {
f->val[2]--;
if (f->val[2] <= 0) {
// spell triggers!
char *p;
char buf[BUFLEN];
int lfid,mapid,x,y,power;
@ -801,7 +802,10 @@ void donextturn(map_t *map) {
char lfname[BUFLEN];
// still going...
getlfname(who, lfname);
f2 = lfhasflag(who,F_SPELLCASTTEXT);
f2 = lfhasflagval(who,F_SPELLCASTCONTTEXT, f->val[0], NA, NA, NULL);
if (!f2) {
f2 = lfhasflagval(who,F_SPELLCASTCONTTEXT, OT_NONE, NA, NA, NULL);
}
if (f2 && strlen(f2->text)) {
msg("%s %s.", lfname, f2->text);
} else {
@ -1436,35 +1440,46 @@ int rolldie(int ndice, int sides) {
int rollhitdice(lifeform_t *lf, int wantmax) {
flag_t *f;
int ndice, nsides = 4, plus = 0;
int ndice, nsides = HITDIESIDES, plus = 0;
int myroll = 0;
float mod;
int maxroll;
float pctofmax;
int db = B_FALSE;
int myfitness;
f = hasflag(lf->flags, F_HITDICE);
if (f) {
texttodice(f->text, &ndice, &nsides, &plus);
ndice = f->val[0];
if (f->val[1] > 0) {
plus = f->val[1];
}
if (f->val[2] > 0) {
nsides = f->val[2];
}
} else {
ndice = 1;
nsides = 4;
plus = 0;
}
maxroll = (ndice * nsides) + plus;
if (wantmax) {
myroll = (ndice * nsides) + plus;
myroll = maxroll;
} else {
myroll = rolldie(ndice, nsides) + plus;
}
mod = 100 + getstatmod(lf, A_CON);
if (db) dblog("rollhitdice() - mod is +%0.0f%%",mod);
if (db) dblog("TOTAL: %d",myroll);
// modify for fitness/con
myroll = pctof(mod, myroll);
if (db) dblog(" -> modified to: %d",myroll);
if (isplayer(lf)) {
pctofmax = ((float)myroll / (float) maxroll) * 100.0;
myfitness = getattr(lf, A_CON);
if (pctofmax < myfitness) {
myroll = pctof(myfitness, maxroll);
if (db) dblog(" -> modified by fitness to: %d",myroll);
}
}
limit(&myroll, 1, NA);
return myroll;

View File

@ -1722,11 +1722,13 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum
rf = hasflag(corpserace->flags, F_HITDICE);
if (rf) {
int maxhp;
maxhp = roll(rf->text);
maxhp = flagtomaxhp(f);
f->val[0] = maxhp;
f->val[1] = maxhp;
}
}
} else if (o->type->id == OT_HEAD) {
flag_t *rf, *cf;
@ -4465,6 +4467,7 @@ int getmaterialvalue(enum MATERIAL mat) {
case MT_METAL:
return 5;
case MT_SILVER:
case MT_CRYSTAL:
return 6;
case MT_GOLD:
case MT_DRAGONWOOD:
@ -4731,7 +4734,7 @@ char *getobequipinfo(object_t *o, char *buf) {
f = hasflag(o->flags,F_EQUIPPED);
if (f) {
if (f->val[0] == BP_WEAPON) {
if (hasflag(o->flags, F_TWOHANDED)) {
if (istwohandedfor(o, o->pile->owner)) {
strcat(buf, " (two-handed weapon)");
} else if (ismeleeweapon(o)) {
strcat(buf, " (weapon)");
@ -4739,7 +4742,7 @@ char *getobequipinfo(object_t *o, char *buf) {
strcat(buf, " (makeshift weapon)");
}
} else if (f->val[0] == BP_SECWEAPON) {
if (hasflag(o->flags, F_TWOHANDED)) {
if (istwohandedfor(o, o->pile->owner)) {
strcat(buf, " (two-handed weapon)");
} else if (isshield(o)) {
strcat(buf, " (shield)");
@ -6416,7 +6419,7 @@ char *gettopobname(cell_t *c, char *retbuf) {
return retbuf;
}
enum BODYPART getweildloc(object_t *o, enum BODYPART *otherloc, int *twohanded) {
enum BODYPART getweildloc(object_t *o, lifeform_t *lf, enum BODYPART *otherloc, int *twohanded) {
enum BODYPART weildloc;
if (o) {
if (hasflag(o->flags, F_FIREARM)) {
@ -6425,7 +6428,7 @@ enum BODYPART getweildloc(object_t *o, enum BODYPART *otherloc, int *twohanded)
weildloc = BP_WEAPON;
}
if (twohanded) {
if (hasflag(o->flags, F_TWOHANDED)) {
if (istwohandedfor(o, lf)) {
*twohanded = B_TRUE;
} else {
*twohanded = B_FALSE;
@ -7250,6 +7253,18 @@ int issmellableob(object_t *o) {
return B_FALSE;
}
int istwohandedfor(object_t *o, lifeform_t *lf) {
flag_t *f;
f = hasflag(o->flags, F_TWOHANDED);
if (f) {
// twohanded for everyone
if (f->val[0] <= 0) return B_TRUE;
if (!lf) return B_TRUE;
if (getlfsize(lf) <= f->val[0]) return B_TRUE;
}
return B_FALSE;
}
int isweapon(object_t *o) {
if (o->type->obclass->id == OC_WEAPON) {
return B_TRUE;
@ -10364,6 +10379,20 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, object_t *o, enum BLESSTYPE
}
gainlevel(lf, B_TRUE);
break;
case OT_POT_FISHLUNG:
if (getmr(lf) && skillcheck(lf, SC_RESISTMAG, 30, 0)) {
if (isplayer(lf)) {
msg("You lungs feel momentarily watery.");
}
break;
}
// how long for?
i = geteffecttime(50,100,potblessed);
if (!lfhasflag(lf, F_BREATHWATER)) {
addtempflag(lf->flags, F_BREATHWATER, B_TRUE, NA, NA, NULL, i);
}
break;
case OT_POT_FURY:
lf->stamina = getmaxstamina(lf);
@ -11641,6 +11670,7 @@ int shatter(object_t *o, int hitlf, char *damstring, lifeform_t *fromlf) {
break;
case OT_POT_ELEMENTIMMUNE:
case OT_POT_ETHEREALNESS:
case OT_POT_FISHLUNG:
case OT_POT_GASEOUSFORM:
case OT_POT_GROWTH:
case OT_POT_LEVITATION:
@ -12541,7 +12571,7 @@ int real_fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int sp
glyph_t *gl;
gl = getglyph(o);
anim(where, srcloc, gl->ch, gl->colour);
msg("%s %s reflected away from %s!", obname, (o->amt == 1) ? "is" : "are", targetname);
msg("%s %s reflected away from %s!", obname, (amt == 1) ? "is" : "are", targetname);
}
// adjust target
where = srcloc;
@ -13145,21 +13175,34 @@ void timeeffectsob(object_t *o) {
// does object's material change cell type?
if (o->material->id == MT_FIRE) {
if (hasflag(location->type->material->flags, F_FLAMMABLE)) {
int changed = B_FALSE;
enum OBTYPE burnoid = OT_NONE;
if (haslos(player, location)) {
if (!lfhasflag(player, F_DONEBURNMSG)) {
msg("The %s burns!", location->type->name);
addflag(player->flags, F_DONEBURNMSG, B_TRUE, NA, NA, NULL);
needredraw = B_TRUE;
}
}
// burn by changing celltype...
switch (location->type->id) {
case CT_GRASS:
setcelltype(location, CT_DIRT);
burnoid = OT_ASH;
break;
case CT_FLOORWOOD:
setcelltype(location, CT_CORRIDOR);
burnoid = OT_HOLEINGROUND;
break;
default:
// stone floor
setcelltype(location, CT_CORRIDOR);
burnoid = OT_ASH;
break;
}
if (changed && haslos(player, location)) {
msg("The %s burns!", location->type->name);
needredraw = B_TRUE;
if (burnoid != OT_NONE) {
addobfast(location->obpile, burnoid);
}
//setcelltype(location, CT_CORRIDOR);
addob(location->obpile, "pile of ash");
}
}
@ -14316,6 +14359,7 @@ int willshatter(enum MATERIAL mat) {
switch (mat) {
case MT_GLASS:
case MT_ICE:
case MT_CRYSTAL:
return B_TRUE;
default: break;
}

View File

@ -151,7 +151,7 @@ int getstairdirection(object_t *o);
enum SKILLLEVEL gettechlevel(enum OBTYPE oid);
int getthrowdam(object_t *o);
char *gettopobname(cell_t *c, char *retbuf);
enum BODYPART getweildloc(object_t *o, enum BODYPART *otherloc, int *twohanded);
enum BODYPART getweildloc(object_t *o, lifeform_t *lf, enum BODYPART *otherloc, int *twohanded);
int hasedibleob(obpile_t *op);
object_t *hasequippedobid(obpile_t *op, enum OBTYPE oid);
object_t *hasknownob(obpile_t *op, enum OBTYPE oid);
@ -212,6 +212,7 @@ int issmellableob(object_t *o);
int isthrownmissile(object_t *o);
knowledge_t *istried(object_t *o);
knowledge_t *istriedot(objecttype_t *ot);
int istwohandedfor(object_t *o, lifeform_t *lf);
int isweapon(object_t *o);
int iswearable(object_t *o);
void killallobs(obpile_t *op);

90
spell.c
View File

@ -615,7 +615,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
if (corpse) {
getobname(corpse, obname, o->amt);
if (isimmuneto(corpse->flags, DT_FIRE, B_FALSE)) {
msg("You attempt to cook %s, but it won't heat up.", obname);
msg("^wYou attempt to cook %s, but it won't heat up.^n", obname);
cooktime += getactspeed(user);
ncooked++;
} else {
@ -1715,6 +1715,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
takedamage(shield, roll("1d3"), DT_DIRECT);
} else if (abilid == OT_A_SNATCH) {
object_t *o = NULL;
flag_t *f;
if (!targcell) {
int dirch;
@ -1747,7 +1748,11 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
return B_TRUE;
}
// setting v0 to spellid just in case pickup() changes flags
addflag(user->flags, F_NOTIME, OT_A_SNATCH, NA, NA, NULL);
pickup(user, o, 1, B_TRUE, B_TRUE);
f = lfhasflagval(user, F_NOTIME, OT_A_SNATCH, NA, NA, NULL);
if (f) killflag(f);
} else if (abilid == OT_A_SONICBOLT) {
int volume;
@ -6600,7 +6605,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
for (o = c->obpile->first ; o ; o = o->next) {
if (o->type->id == OT_HAILSTORM) {
flag_t *f;
f = hasflag(o->flags, F_WALKDAM);
f = hasflagval(o->flags, F_WALKDAM, DT_PROJECTILE, NA, NA, NULL);
if (f) {
changeflagtext(f, dambuf);
}
@ -8974,7 +8979,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if ((spellid == OT_S_POLYMORPH) || (spellid == OT_S_SHAPESHIFT)) {
race_t *r = NULL;
if (frompot || (spellid == OT_S_SHAPESHIFT)) {
if (caster && (frompot || (spellid == OT_S_SHAPESHIFT))) {
target = caster;
} else {
target = targcell->lf;
@ -9000,27 +9005,33 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
//if ((caster == target) && getforcedspellrace(caster, spellid, buf)) {
if (caster && getforcedspellrace(caster, spellid, buf)) {
if (getforcedspellrace(target, spellid, buf)) {
r = findracebyname(buf);
} else {
if (spellid == OT_S_POLYMORPH) {
if (lfhasflag(caster, F_CONTROL)) {
int dorandom = B_FALSE;
if (caster && lfhasflag(caster, F_CONTROL)) {
if (power < 5) {
power = 5;
}
}
if (isplayer(caster) && (power >= 5)) {
if (isplayer(target)) { // ie. polymorphing yourself
askstring("What will you become", '?', buf, BUFLEN, NULL);
if (power >= 5) { // controlled
if (isplayer(caster)) {
if (isplayer(target)) { // ie. polymorphing yourself
askstring("What will you become", '?', buf, BUFLEN, NULL);
} else {
char buf2[BUFLEN];
char targname[BUFLEN];
getlfname(target, targname);
snprintf(buf2, BUFLEN, "What will you transform %s into", targname);
askstring(buf2, '?', buf, BUFLEN, NULL);
}
r = findracebyname(buf);
} else {
char buf2[BUFLEN];
char targname[BUFLEN];
getlfname(target, targname);
snprintf(buf2, BUFLEN, "What will you transform %s into", targname);
askstring(buf2, '?', buf, BUFLEN, NULL);
// TODO: select based on player damage, etc
dorandom = B_TRUE;
}
r = findracebyname(buf);
} else { // random
if (isplayer(target) && lfhasflag(target, F_CONTROL)) {
askstring("What will you become", '?', buf, BUFLEN, NULL);
@ -9028,14 +9039,25 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// make sure race is valid:
if (r && !canpolymorphto(r->id)) r = NULL;
}
} else {
dorandom = B_TRUE;
}
}
if (!r) {
// random race, but not the same!
r = target->race;
while ((r == target->race) || !canpolymorphto(r->id)) {
r = getrandomrace(NULL, NA);
}
if (!r || dorandom) {
int forcedepth;
// want a random race with similar Threat Rating to the
// target's current one.
//
// normally tr range is (depth/2) +/- RARITYVARIANCELF
//
// so for a given tr, ask for:
//
// depth = tr*2
forcedepth = gettr(target)*2;
r = target->race;
while ((r == target->race) || !canpolymorphto(r->id)) {
r = getrandomrace(NULL, forcedepth);
}
}
} else if (spellid == OT_S_SHAPESHIFT) {
@ -9749,6 +9771,10 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
fizzle(caster);
return B_TRUE;
}
// revert in a little while...
addflag(target->flags, F_SIZETIMER, origsize, power*10, NA, NULL);
if (isplayer(target) || cansee(player, target)) {
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
@ -10159,23 +10185,13 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// get list of possible snakes
for (r = firstrace ; r ; r = r->next) {
if (strstr(r->name, " snake")) {
flag_t *f;
f = hasflag(r->flags, F_HITDICE);
if (f) {
int ndice,nsides,bonus,maxroll;
texttodice(f->text, &ndice,&nsides,&bonus);
maxroll = ndice * nsides + bonus;
// ie. 1hd needs power 2
// ie. 2hd needs power 4
// ie. 3hd needs power 6
// ie. 4hd needs power 8
if (power >= (maxroll/4)) {
raceposs[nraceposs++] = r;
}
int tr;
tr = gettrrace(r);
if (power >= tr*2) {
raceposs[nraceposs++] = r;
}
}
}
/*
poss[0] = caster->cell;
@ -11320,6 +11336,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
howlong = getspellduration(5,10,blessed) + power;
f = addtempflag(target->flags, F_ATTRMOD, A_STR, power*-15, NA, NULL, howlong);
f->obfrom = OT_S_WEAKEN;
f = addtempflag(target->flags, F_MELEEDAMPCT, 50, NA, NA, NULL, howlong);
f->obfrom = OT_S_WEAKEN;
if (seenbyplayer) *seenbyplayer = B_TRUE;
} else {
@ -12444,7 +12462,7 @@ int getspellrange(lifeform_t *lf, enum OBTYPE spellid, int power) {
range = power;
break;
case OT_S_FLAMEPILLAR:
range = power;
range = 3+(power/2);
break;
case OT_S_LIGHTNINGBOLT:
range = (power*3);