diff --git a/ai.c b/ai.c index bf29cdc..c4fba14 100644 --- a/ai.c +++ b/ai.c @@ -18,7 +18,8 @@ extern enum ERROR reason; int wantdb = B_TRUE; -enum OBTYPE aigetattackspell(lifeform_t *lf) { + +enum OBTYPE aigetattackspell(lifeform_t *lf, lifeform_t *victim) { flag_t *f; enum OBTYPE poss[MAXPILEOBS]; int nposs = 0; @@ -29,25 +30,51 @@ enum OBTYPE aigetattackspell(lifeform_t *lf) { } for (f = lf->flags->first ; f ; f = f->next) { - if (f->id == F_CANWILL) { - poss[nposs] = f->val[0]; - nposs++; - } else if (f->id == F_CANCAST) { + if ((f->id == F_CANCAST) || (f->id == F_CANWILL)) { objecttype_t *ot; ot = findot(f->val[0]); if (cancast(lf, f->val[0], NULL)) { - if (hasflag(ot->flags, F_AICASTATVICTIM) || hasflag(ot->flags, F_AICASTATSELF) || hasflag(ot->flags, F_AICASTANYWHERE)) { + int ok = B_FALSE; + if (hasflag(ot->flags, F_AICASTATVICTIM)) { + int range; + range = getspellrange(f->val[0]); + if ((range == UNLIMITED) || (getcelldist(lf->cell, victim->cell) <= range)) { + if (db) { + dblog(".oO { spell possibility: %s }", ot ? ot->name : "?unkownspell?"); + } + ok = B_TRUE; + } + } else if (hasflag(ot->flags, F_AICASTATSELF) || hasflag(ot->flags, F_AICASTANYWHERE)) { if (db) { dblog(".oO { spell possibility: %s }", ot ? ot->name : "?unkownspell?"); } - //TODO :ooo only add if we have an AICAST flag! - poss[nposs] = f->val[0]; - nposs++; + ok = B_TRUE; + } else if (hasflag(ot->flags, F_AICASTATADJVICTIM) && + (getcelldist(lf->cell,victim->cell) == 1)) { + if (ot->id == OT_A_GRAB) { + if (lfhasflag(lf, F_GRABBING) || lfhasflag(lf, F_GRABBEDBY) || + lfhasflag(victim, F_GRABBING) || lfhasflag(victim, F_GRABBEDBY)) { + } else { + ok = B_TRUE; + } + } else { + ok = B_TRUE; + } + } else if (hasflag(ot->flags, F_AICASTNEXTTOVICTIM) && + (getcelldist(lf->cell,victim->cell) == 1)) { + ok = B_TRUE; } else { if (db) { dblog(".oO { cant cast %s - dont know where to target it }", ot ? ot->name : "?unkownspell?"); } } + + if (ok) { + if (aispellok(lf, ot, victim)) { + poss[nposs] = f->val[0]; + nposs++; + } + } } else { if (db) { if (ot) { @@ -77,6 +104,18 @@ void aigetspelltarget(lifeform_t *lf, objecttype_t *spelltype, lifeform_t *victi if (spelllf) *spelllf = victim; if (spellcell) *spellcell = victim->cell; if (spellob) *spellob = NULL; + } else if (hasflag(spelltype->flags, F_AICASTNEXTTOVICTIM)) { + if (getcelldist(lf->cell, victim->cell) <= 1) { + if (spelllf) *spelllf = NULL; + if (spellcell) *spellcell = lf->cell; + if (spellob) *spellob = NULL; + } + } else if (hasflag(spelltype->flags, F_AICASTATADJVICTIM)) { + if (getcelldist(lf->cell, victim->cell) <= 1) { + if (spelllf) *spelllf = victim; + if (spellcell) *spellcell = victim->cell; + if (spellob) *spellob = NULL; + } } else if (hasflag(spelltype->flags, F_AICASTATSELF)) { if (spelllf) *spelllf = lf; if (spellcell) *spellcell = lf->cell; @@ -181,6 +220,18 @@ void aimove(lifeform_t *lf) { if (!weild(lf, bestgun)) return; } + // do we have better ammo? + if (curgun) { + object_t *curammo; + curammo = getammo(lf); + if (!curammo) { + for (o = lf->pack->first ; o ; o = o->next) { + testammo(lf, o); // doesn't take any time. + if (getammo(lf)) break; + } + } + } + // do we have better armour? for (bp = BP_RIGHTHAND ; bp < MAXBODYPARTS; bp++) { object_t *curarm; @@ -228,7 +279,7 @@ void aimove(lifeform_t *lf) { // reset F_TARGET lifetime to full. f->lifetime = AI_FOLLOWTIME; - if (db) dblog(".oO { i can see my target (at %d,%d). will 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 last known loc f->val[1] = target->cell->x; f->val[2] = target->cell->y; @@ -236,8 +287,13 @@ void aimove(lifeform_t *lf) { goingtomove = B_TRUE; + // drink boost potions + if (!useitemwithflag(lf, F_AIBOOSTITEM)) { + return; + } + // can we attack with spells (ie. ones which target the victim)? - spell = aigetattackspell(lf); + spell = aigetattackspell(lf, target); if (spell != OT_NONE) { int spellfailed = B_FALSE; lifeform_t *spelllf = NULL; @@ -288,27 +344,42 @@ void aimove(lifeform_t *lf) { aigetspelltarget(lf, st, target, &spelllf, &spellcell, &spellob); } - - if (!spellfailed && !castspell(lf, spell, spelllf, spellob, spellcell)) { + if (spellfailed) { + if (db) dblog(".oO { cast spell/ability failed (1)! }"); + } else { + if (getschool(spell) == SS_ABILITY) { + spellfailed = useability(lf, spell, spelllf, spellcell); + } else { + spellfailed = castspell(lf, spell, spelllf, spellob, spellcell); + } + } + if (spellfailed) { + if (db) dblog(".oO { cast spell/ability tried but failed (2)! }"); + } else { // spell succesful return; - } else { - if (db) dblog(".oO { cast spell failed! }"); } } // if not adjacent, check for guns, wands, throwing - if (goingtomove && (getcelldist(lf->cell, target->cell) > 1)) { + if (goingtomove && (getcelldist(lf->cell, target->cell) > 1) && haslof(lf, target->cell)) { // can we attack by firing something? gun = getfirearm(lf); if (goingtomove && gun && getammo(lf)) { + if (db) { + char gunname[BUFLEN]; + getobname(gun, gunname, gun->amt); + dblog(".oO { will fire my gun (%s) at target. }",gunname); + } setguntarget(lf, target); if (!shoot(lf)) { // succesful return; } else { - if (db) dblog(".oO { shoot gun failed! }"); + if (db) dblog(".oO { shoot gun failed! reason = %d }", reason); } + } else { + if (db) dblog(".oO { not firing out gun }"); } // can we attack by throwing something? @@ -500,6 +571,12 @@ void aimove(lifeform_t *lf) { // need to heal? if ((lf->hp < lf->maxhp) || ((lf->mp < lf->maxmp) && lfhasflag(lf, F_RESTHEALMPAMT)) ) { + if (lf->hp < (lf->maxhp/2)) { + if (!useitemwithflag(lf, F_AIHEALITEM)) { + return; + } + } + if (db) dblog(".oO { resting }"); rest(lf, B_TRUE); } @@ -523,6 +600,21 @@ int aipickup(lifeform_t *lf, object_t *o) { } +int aispellok(lifeform_t *lf, objecttype_t *st, lifeform_t *victim) { + if ((st->id == OT_S_BLINDNESS) && isblind(victim)) { + return B_FALSE; + } + if ((st->id == OT_S_PAIN) && lfhasflag(victim, F_PAIN)) { + return B_FALSE; + } + if ((st->id == OT_A_SPRINT) && lfhasflag(lf, F_SPRINTING)) { + return B_FALSE; + } + + return B_TRUE; +} + + object_t *hasbetterarmour(lifeform_t *lf, obpile_t *op) { object_t *o; @@ -709,4 +801,3 @@ int lookforobs(lifeform_t *lf, int covetsonly) { return B_FALSE; } - diff --git a/ai.h b/ai.h index 86e4e30..3da002c 100644 --- a/ai.h +++ b/ai.h @@ -1,10 +1,11 @@ #include "defs.h" -enum OBTYPE aigetattackspell(lifeform_t *lf); +enum OBTYPE aigetattackspell(lifeform_t *lf, lifeform_t *victim); void aigetspelltarget(lifeform_t *lf, objecttype_t *spelltype, lifeform_t *victim, lifeform_t **spelllf, cell_t **spellcell, object_t **spellob); object_t * aigetwand(lifeform_t *lf); void aimove(lifeform_t *lf); int aipickup(lifeform_t *lf, object_t *o); +int aispellok(lifeform_t *lf, objecttype_t *st, lifeform_t *victim); object_t *hasbetterarmour(lifeform_t *lf, obpile_t *op); object_t *hasbetterweapon(lifeform_t *lf, obpile_t *op); int lookforobs(lifeform_t *lf, int covetsonly); diff --git a/attack.c b/attack.c index 42a3936..e0ae7b4 100644 --- a/attack.c +++ b/attack.c @@ -8,6 +8,8 @@ #include "flag.h" #include "io.h" #include "lf.h" +#include "map.h" +#include "move.h" #include "nexus.h" #include "objects.h" #include "text.h" @@ -15,6 +17,47 @@ extern lifeform_t *player; +int applyarmourdamage(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damtype) { + object_t *armour; + int adam; + int damtaken = 0; + if ((damtype == DT_ACID) || hasflag(wep->flags, F_ARMOURPIERCE)) { + // ALL of damage reduction goes towards armour + adam = dam; + } else { + // some of damage reduction goes towards armour + adam = (dam / 2); + } + // pick a random piece of armour + armour = getrandomarmour(lf); + if (armour) { + damtaken = takedamage(armour,adam, damtype); + } + return damtaken; +} + +void applyarmourdamreduction(lifeform_t *lf, object_t *wep, int reduceamt, int *dam, enum DAMTYPE damtype) { + int db = B_FALSE; + + // armour can't stop armour-piercing weapons + if (hasflag(wep->flags, F_ARMOURPIERCE)) { + reduceamt = 0; + } + + if (db) { + if (reduceamt > 0) { + dblog("Armour reduces dam by %d to %d.",reduceamt,dam); + } else { + dblog("No armour dam reduction."); + } + } + if (dam && (reduceamt >= 0)) { + *dam -= reduceamt; + if (*dam < 0) *dam = 0; + } +} + + int attackcell(lifeform_t *lf, cell_t *c) { // anyone there? if so just attack. if (c->lf) { @@ -45,10 +88,11 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) { object_t *wep; obpile_t *op = NULL; int attacktime; - int acc; int hit = B_FALSE; + int critical = 0; char wepname[BUFLEN]; - int ev; + //int acc; + //int ev; int i; int willheal = B_FALSE; @@ -61,7 +105,16 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) { // get names getlfname(lf, attackername); - getlfname(victim, victimname); + + if (lf == victim) { + if (isplayer(lf)) { + strcpy(victimname, "yourself"); + } else { + strcpy(victimname, "itself"); + } + } else { + getlfname(victim, victimname); + } if (aidb) dblog(".oO { trying to attack %s }", victimname); @@ -89,25 +142,10 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) { taketime(lf, attacktime); - acc = getlfaccuracy(lf); - - // modify for defender's evasion - ev = getevasion(victim); - acc -= ev; - - // metal weapon versus magnetic shield? - if (lfhasflag(victim, F_MAGSHIELD) && ismetal(wep->material->id)) { - acc -= 45; - } - - if (acc < 0) acc = 0; - if (acc > 100) acc = 100; - - if (aidb) dblog(".oO { my modified chance to hit is %d %% }", acc); - // did you hit? ndam = 0; - if (rnd(1,100) <= acc) { + if (rolltohit(lf, victim, &critical)) { + int n; hit = B_TRUE; if (aidb) dblog(".oO { i hit! }"); @@ -122,7 +160,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) { o = addob(lf->pack, "glowing flask"); if (o) { getobname(o, buf, o->amt); - msglower("%c - %s.",o->letter, buf); + msgnocap("%c - %s.",o->letter, buf); } else { // add to the ground o = addob(lf->cell->obpile, "glowing flask"); @@ -143,12 +181,18 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) { // determine damage //if (unarmed && (unarmedflag->val[0] != NA)) { - if (unarmedflag) { - // this mosnter's unarmed attack will - // override normal damage calculation - dam[ndam] = getdamrollfromflag(unarmedflag); - } else { - dam[ndam] = getdamroll(wep, victim); + // ie. if critical is 0, do this once. + // if critical is 1, do this twice. + // etc. + dam[ndam] = 0; + for (n = 0; n < critical+1; n++) { + if (unarmedflag) { + // this mosnter's unarmed attack will + // override normal damage calculation + dam[ndam] += getdamrollfromflag(unarmedflag); + } else { + dam[ndam] += getdamroll(wep, victim); + } } if (aidb) dblog("rolled dam[%d] = %d",ndam,dam[ndam]); @@ -175,7 +219,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) { } // determine extra damage - getextradam(wep, &dam[ndam], &damtype[ndam]); + getextradam(wep, &dam[0], &damtype[0], &ndam); } } else { hit = B_FALSE; @@ -185,24 +229,26 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) { if (ndam > 0) { + flag_t *f; for (i = 0; i < ndam; i++) { - float reducepct; - int ar; int reduceamt; dblog("initial dam[%d] = %d",i,dam[i]); + if (lfhasflag(lf, F_HEAVYBLOW)) { + dam[i] = (int)((float)dam[i] * 1.5); + dblog("heavy blow makes dam[%d] = %d",i,dam[i]); + } + // modify based on resistances adjustdamlf(victim, &dam[i], damtype[i]); dblog("adjusted for lf to dam[%d] = %d",i,dam[i]); // modify for defender's armour - ar = getarmourrating(victim); - reducepct = getdamreducepct(ar); - reduceamt = (int) ceil((reducepct / 100.0) * (float)dam[i]); + reduceamt = getarmourdamreduction(victim, wep, dam[i], damtype[i]); + + applyarmourdamreduction(victim, wep, reduceamt, &dam[i], damtype[i]); - dam[i] -= reduceamt; - if (dam[i] < 0) dam[i] = 0; dblog("reduced by armour to dam[%d] = %d",i,dam[i]); // will this hit be fatal? @@ -287,7 +333,9 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) { if (wep && !unarmedflag) { char wepname[BUFLEN]; getobname(wep, wepname, 1); - sprintf(buf, "%s^weilding %s",attackername, wepname); + sprintf(buf, "%s^%s %s",attackername, + (lf == victim) ? "using" : "weilding", + wepname); } else { strcpy(buf, attackername); } @@ -296,20 +344,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) { // victim's armour loses hp if (reduceamt) { - object_t *armour; - int adam; - if (damtype[i] == DT_ACID) { - // ALL of damage reduction goes towards armour - adam = reduceamt; - } else { - // some of damage reduction goes towards armour - adam = (reduceamt / 2); - } - // pick a random piece of armour - armour = getrandomarmour(victim); - if (armour) { - takedamage(armour,adam, damtype[i]); - } + applyarmourdamage(victim, wep, reduceamt, damtype[i]); } } } // end foreach damtype @@ -319,7 +354,6 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) { if (!isdead(victim)) { if (unarmedflag) { - flag_t *f; f = lfhasflag(lf, F_FREEZINGTOUCH); if (f) { // victim turns to ice for a while! @@ -327,6 +361,45 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) { killflag(f); } } + + f = lfhasflag(lf, F_QUICKBITE); + if (f) { + if (isbleeding(victim)) { + int dam; + char lfname[BUFLEN]; + dam = rolldie(f->val[0], f->val[1]) + f->val[2]; + getlfname(lf, lfname); + losehp_real(victim, dam, DT_BITE, lf, lfname, B_FALSE); + if (isplayer(victim) || haslos(player, victim->cell)) { + msg("%s bites %s!", lfname, victimname); + } + } + } + + f = lfhasflag(lf, F_PACKATTACK); + if (f) { + int dir; + cell_t *c; + int nmatched = 0; + // count adjacent allies of name xx + for (dir = DC_N; dir <= DC_NW; dir++) { + c = getcellindir(victim->cell, dir); + if (c && c->lf) { + if (strcasestr(c->lf->race->name, f->text)) { + nmatched++; + } + } + } + if (nmatched >= f->val[2]) { + char damstring[BUFLEN]; + sprintf(damstring, "a %s pack", f->text); + losehp(victim, f->val[0], f->val[1], lf, damstring); + if (isplayer(victim) || haslos(player, victim->cell)) { + msg("The %s pack attacks %s!", f->text, victimname); + } + } + } + } } else { // miss! if (aidb) dblog(".oO { i missed! }"); @@ -349,6 +422,18 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) { msg("%s misses %s.", buf, victimname); } } + + if (lfhasflag(victim, F_DODGES)) { + flag_t *f; + cell_t *adj; + + f = addflag(victim->flags, F_NOTIME, B_TRUE, NA, NA, NULL); + adj = getrandomadjcell(victim->cell, WE_NOTSOLID); + moveto(lf, adj); + msg("%s dodge%s!",victimname,isplayer(victim) ? "" : "s"); + killflag(f); + + } } fightback(victim, lf); } @@ -445,7 +530,8 @@ int attackob(lifeform_t *lf, object_t *o) { // don't need to check for blessed vs mosnters // determine extra damage - getextradam(wep, &dam[ndam], &damtype[ndam]); + getextradam(wep, &dam[0], &damtype[0], &ndam); + for (i = 0; i < ndam; i++) { // announce the hit @@ -473,6 +559,16 @@ int attackob(lifeform_t *lf, object_t *o) { youhear(lf->cell, "sounds of fighting"); } + if ((i == 0) && unarmedflag) { + char buf[BUFLEN]; + sprintf(buf, "punching %s", obname); + if ( losehp(lf, 1, DT_BASH, lf, buf)) { + if (isplayer(lf)) { + msg("Ow!"); + } + } + } + // object loses hp takedamage(o, dam[i], damtype[i]); @@ -481,6 +577,21 @@ int attackob(lifeform_t *lf, object_t *o) { // special weapon effects wepeffects(wep, obloc); + // weapon gets damaged ? + if (!unarmedflag && wep && (ndam > 0)) { + switch (damtype[0]) { + case DT_PIERCE: + case DT_SLASH: + // weapon gets duller + if (rnd(1,2)) makeduller(wep, 1); + break; + default: + break; + } + } + + // hitting an object with our hands will hurt + // get rid of temp unarmed object pile if (op) { killobpile(op); @@ -489,6 +600,20 @@ int attackob(lifeform_t *lf, object_t *o) { return B_FALSE; } +// returns the amount of damage the armour blocked... +int getarmourdamreduction(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damtype) { + int reduceamt = 0; + float reducepct; + int ar; + + ar = getarmourrating(lf); + reducepct = getdamreducepct(ar); + reduceamt = (int) ceil((reducepct / 100.0) * (float)dam); + + if (reduceamt < 0) reduceamt = 0; + return reduceamt; +} + // returns a const char * char *getattackverb(enum DAMTYPE damtype, int dam, int maxhp) { @@ -597,6 +722,12 @@ char *getattackverb(enum DAMTYPE damtype, int dam, int maxhp) { } else { return "freeze"; } + } else if (damtype == DT_UNARMED) { + if (rnd(1,2) == 1) { + return "punch"; + } else { + return "hit"; + } } else if (damtype == DT_TOUCH) { return "touch"; } @@ -635,12 +766,13 @@ enum DAMTYPE getdamtype(object_t *wep) { return dt; } -int getextradam(object_t *wep, int *dam, enum DAMTYPE *damtype) { +int getextradam(object_t *wep, int *dam, enum DAMTYPE *damtype, int *ndam) { flag_t *f; for (f = wep->flags->first ; f ; f = f->next) { if (f->id == F_ONFIRE) { - *dam = rnd(5,10); // TODO: don't hardcode? - *damtype = DT_FIRE; + *(dam + *ndam) = rolldie(2,8); + *(damtype + *ndam) = DT_FIRE; + (*ndam)++; } } return *dam; @@ -667,7 +799,7 @@ char *getkillverb(lifeform_t *victim, enum DAMTYPE damtype, int dam, int maxhp) if (lfhasflagval(victim, F_NOBODYPART, BP_HEAD, NA, NA, NULL)) { return "bisect"; } else { - if (rnd(1,3)) { + if (rnd(1,3) == 1) { return "behead"; } else { return "bisect"; @@ -771,9 +903,8 @@ int getdamroll(object_t *o, lifeform_t *victim) { } } else { - // TODO wepaon does damage based on weight - // weapon does no damage - dam = 0; + // TODO wepaon does bashing damage based on weight + dam = rnd(1,2); } // modify for bonus @@ -938,10 +1069,58 @@ obpile_t *getunarmedweapon(lifeform_t *lf,flag_t **uflag) { return op; } +int rolltohit(lifeform_t *lf, lifeform_t *victim, int *critical) { + int acc,ev; + object_t *wep; + obpile_t *op = NULL; + int gothit; + + if (critical) { + *critical = 0; + } + + acc = getlfaccuracy(lf); + wep = getattackwep(lf, &op, NULL); + + // modify for defender's evasion + ev = getevasion(victim); + acc -= ev; + + // metal weapon versus magnetic shield? + if (lfhasflag(victim, F_MAGSHIELD) && ismetal(wep->material->id)) { + acc -= 45; + } + + if (critical) { + if (rnd(1,20) == 20) *critical = 1; + } + + if (acc < 0) acc = 0; + if (acc > 100) acc = 100; + + //if (aidb) dblog(".oO { my modified chance to hit is %d %% }", acc); + if (rnd(1,100) <= acc) { + gothit = B_TRUE; + } else { + if (critical && *critical) { + // turn a miss into a hit + gothit = B_TRUE; + } else { + gothit = B_FALSE; + } + + } + + if (op) killobpile(op); + return gothit; +} + void wepeffects(object_t *wep, cell_t *where) { flag_t *f; lifeform_t *victim; + lifeform_t *owner; + owner = wep->pile->owner; victim = where->lf; if (!where) return; @@ -1024,6 +1203,12 @@ void wepeffects(object_t *wep, cell_t *where) { } } // end if dampct > 50 } + } else if ((f->id == F_HEAVYBLOW) && victim && owner) { + int dir; + // knock back victim + dir = getdirtowards(owner->cell, victim->cell, victim, B_FALSE); + knockback(victim, dir , 2, owner); + f->known = B_TRUE; } } } diff --git a/attack.h b/attack.h index 03a7749..5a5aac6 100644 --- a/attack.h +++ b/attack.h @@ -1,12 +1,15 @@ #include "defs.h" +int applyarmourdamage(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damtype); +void applyarmourdamreduction(lifeform_t *lf, object_t *wep, int reduceamt, int *dam, enum DAMTYPE damtype); int attackcell(lifeform_t *lf, cell_t *c); int attacklf(lifeform_t *lf, lifeform_t *victim); int attackob(lifeform_t *lf, object_t *o); +int getarmourdamreduction(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damtype); char *getattackverb(enum DAMTYPE damtype, int dam, int maxhp); object_t *getattackwep(lifeform_t *lf, obpile_t **unarmedpile, flag_t **unarmedflag); enum DAMTYPE getdamtype(object_t *wep); -int getextradam(object_t *wep, int *dam, enum DAMTYPE *damtype); +int getextradam(object_t *wep, int *dam, enum DAMTYPE *damtype, int *ndam); char *getkillverb(lifeform_t *victim, enum DAMTYPE damtype, int dam, int maxhp); void getdamrange(flagpile_t *fp, int *min, int *max); void getdamrangeunarmed(flag_t *f, int *min, int *max); @@ -15,4 +18,5 @@ int getdamroll(object_t *o, lifeform_t *victim); int getdamrollfromflag(flag_t *f); float getstrdammod(lifeform_t *lf); obpile_t *getunarmedweapon(lifeform_t *lf, flag_t **uflag); +int rolltohit(lifeform_t *lf, lifeform_t *victim, int *critical); void wepeffects(object_t *wep, cell_t *where); diff --git a/defs.h b/defs.h index bd8d20e..ed0c04e 100644 --- a/defs.h +++ b/defs.h @@ -25,6 +25,16 @@ enum ATTRIB { }; #define MAXATTS 3 +enum CHECKTYPE { + SC_STR, + SC_DEX, + SC_IQ, + ////////// + SC_DODGE, + SC_SLIP, + SC_MORALE, +}; + enum BURDENED { BR_NONE = 0, BR_BURDENED = 1, @@ -68,6 +78,7 @@ enum LFCONDITION { #define IFKNOWN (-9772) // used by f_xxconfer. only confer a flag if item is known. #define IFACTIVE (-9771) // used by f_prodeuceslight. only does so if object is activated +#define NOCONDITION (0) #define IFMONSTER (-9769) // used in v2 of f_ifpct job flags #define IFPLAYER (-9768) // used in v2 of f_ifpct job flags @@ -102,7 +113,7 @@ enum LFCONDITION { #define MAXRANDOMOBCANDIDATES 100 #define MAXRANDOMLFCANDIDATES 100 -#define MAXCANDIDATES 50 +#define MAXCANDIDATES 200 //#define MAX_MAPW 80 //#define MAX_MAPH 50 @@ -128,7 +139,7 @@ enum LFCONDITION { #define DEF_SPARSENESS 20 //#define DEF_SPARSENESS 0 //#define DEF_LOOPPCT 70 -#define DEF_LOOPPCT 85 +#define DEF_LOOPPCT 95 //#define DEF_LOOPPCT 0 #define MINROOMS 5 #define MAXROOMS 10 @@ -240,21 +251,25 @@ enum CELLTYPE { CT_LOOPCORRIDOR, }; + enum SPELLSCHOOL { - SS_DIVINE = 2, - SS_ABILITY = 0, - SS_ALLOMANCY = 1, - SS_DEATH = 3, - SS_ELEMENTAL = 4, - SS_DIVINATION = 5, - SS_GRAVITY = 6, - SS_LIFE = 7, - SS_MODIFICATION = 8, - SS_MENTAL = 9, - SS_SUMMONING = 10, - SS_TRANSLOCATION = 11, - SS_WILD = 12, - SS_LAST = 13, + SS_NONE, + SS_DIVINE, + SS_ABILITY, + SS_ALLOMANCY, + SS_AIR, + SS_DEATH, + SS_DIVINATION, + SS_FIRE, + SS_ICE, + SS_GRAVITY, + SS_LIFE, + SS_MODIFICATION, + SS_MENTAL, + SS_SUMMONING, + SS_TRANSLOCATION, + SS_WILD, + SS_LAST, }; enum STRBRACKET { @@ -318,15 +333,17 @@ enum DAMTYPE { DT_MAGIC = 17, DT_TOUCH = 18, DT_POISONGAS = 19, - DT_NONE = 20, // for direclty dealt damage, not really any type + DT_UNARMED = 20, + DT_NONE = 21, // for direclty dealt damage, not really any type }; -#define MAXDAMTYPE 21 +#define MAXDAMTYPE 22 // Object Classes enum OBCLASS { OC_MONEY, OC_WEAPON, OC_ARMOUR, + OC_MISSILE, OC_RING, OC_SCROLL, OC_POTION, @@ -374,21 +391,33 @@ enum RACE { // monsters R_BUGBEAR, R_EYEBAT, - R_GIANT, + R_GIANTHILL, + R_GIANTFIRE, + R_GIANTFIREFC, + R_GIANTFIRETITAN, R_GNOLL, + R_GNOLLHM, + R_GNOLLMR, R_GOBLIN, - R_GOBLINGUARD, - R_GOBLINCHAMP, + R_GOBLINWAR, + R_GOBLINSHOOTER, + R_GOBLINHEXER, R_HOBGOBLIN, + R_HOBGOBLINWAR, + R_KOBOLD, R_LIZARDMAN, R_LURKINGHORROR, R_OGRE, + R_OGRESAVAGE, + R_OGREWARHULK, + R_OOZEGREY, R_ORC, + R_ORCWARRIOR, R_ORK, R_POLTERGEIST, R_SHADOWCAT, - R_SLIME, R_SPRITEFIRE, + R_TROGLODYTE, R_TROLL, R_XAT, // small animals @@ -397,6 +426,7 @@ enum RACE { R_RAT, R_WOLF, // insects + R_BUTTERFLY, R_GLOWBUG, R_GIANTFLY, R_GIANTBLOWFLY, @@ -452,6 +482,7 @@ enum OBTYPE { OT_NONE, // dungeon features OT_BOULDER, + OT_STATUE, OT_WOODENDOOR, OT_WOODENTABLE, OT_WOODENBARREL, @@ -469,6 +500,7 @@ enum OBTYPE { OT_BERRY, OT_NUT, OT_BANANA, + OT_BANANASKIN, // not really food OT_APPLE, OT_MUSHROOM, OT_BREADSTALE, @@ -501,6 +533,7 @@ enum OBTYPE { OT_POT_ELEMENTENDURE, OT_POT_ELEMENTIMMUNE, OT_POT_ETHEREALNESS, + OT_POT_EXPERIENCE, OT_POT_GASEOUSFORM, OT_POT_HEALING, OT_POT_HEALINGMIN, @@ -521,6 +554,7 @@ enum OBTYPE { OT_SCR_DETECTLIFE, OT_SCR_DETECTMAGIC, OT_SCR_FLAMEPILLAR, + OT_SCR_FLAMEBURST, OT_SCR_IDENTIFY, OT_SCR_KNOCK, OT_SCR_LIGHT, @@ -535,18 +569,28 @@ enum OBTYPE { // SPELLBOOKS // allomancy can't be learned from books // -- death + OT_SB_ANIMATEDEAD, + OT_SB_PAIN, OT_SB_INFINITEDEATH, OT_SB_WEAKEN, + OT_SB_BLINDNESS, // -- divination OT_SB_DETECTAURA, OT_SB_DETECTLIFE, OT_SB_IDENTIFY, OT_SB_MAPPING, - // -- elemental + // -- elemental - air + OT_SB_CLOUDKILL, + // -- elemental - fire + OT_SB_SPARK, OT_SB_FIREDART, - OT_SB_CONECOLD, OT_SB_FIREBALL, OT_SB_FLAMEPILLAR, + OT_SB_FLAMEBURST, + OT_SB_BURNINGWAVE, + // -- elemental - ice + OT_SB_CONECOLD, + OT_SB_FREEZEOB, // -- gravity OT_SB_GRAVBOOST, OT_SB_HASTE, @@ -559,12 +603,13 @@ enum OBTYPE { OT_SB_MINDSCAN, OT_SB_TELEKINESIS, // -- modification - OT_SB_FREEZEOB, OT_SB_GASEOUSFORM, OT_SB_KNOCK, OT_SB_INSCRIBE, OT_SB_LIGHT, + OT_SB_DARKNESS, OT_SB_PASSWALL, + OT_SB_PETRIFY, OT_SB_POLYMORPH, OT_SB_POLYMORPHRND, // -- summoning @@ -586,19 +631,29 @@ enum OBTYPE { OT_S_MAGSHIELD, OT_S_METALHEAL, // -- death + OT_S_ANIMATEDEAD, + OT_S_PAIN, OT_S_INFINITEDEATH, OT_S_WEAKEN, + OT_S_BLINDNESS, // -- divination OT_S_DETECTAURA, OT_S_DETECTLIFE, OT_S_DETECTMAGIC, OT_S_IDENTIFY, OT_S_MAPPING, - // -- elemental + // -- elemental - air + OT_S_CLOUDKILL, + // -- elemental - fire + OT_S_SPARK, OT_S_FIREDART, - OT_S_CONECOLD, OT_S_FIREBALL, OT_S_FLAMEPILLAR, + OT_S_FLAMEBURST, + OT_S_BURNINGWAVE, + // -- elemental - ice + OT_S_CONECOLD, + OT_S_FREEZEOB, // -- gravity OT_S_GRAVBOOST, OT_S_HASTE, @@ -609,15 +664,17 @@ enum OBTYPE { OT_S_TURNUNDEAD, // -- mental OT_S_MINDSCAN, + OT_S_SLEEP, OT_S_TELEKINESIS, // -- modification OT_S_ENCHANT, - OT_S_FREEZEOB, OT_S_GASEOUSFORM, OT_S_INSCRIBE, OT_S_KNOCK, OT_S_LIGHT, + OT_S_DARKNESS, OT_S_PASSWALL, + OT_S_PETRIFY, OT_S_POLYMORPH, OT_S_POLYMORPHRND, // -- summoning @@ -638,10 +695,12 @@ enum OBTYPE { OT_S_WISH, OT_S_GIFT, // abilities + OT_A_GRAB, OT_A_JUMP, OT_A_SPRINT, OT_A_DEBUG, OT_A_EMPLOY, + OT_A_HEAVYBLOW, // wands OT_WAND_COLD, OT_WAND_DETONATION, @@ -653,6 +712,7 @@ enum OBTYPE { OT_WAND_POLYMORPH, OT_WAND_SLOW, OT_WAND_WEAKNESS, + OT_WAND_WONDER, // tech/tools OT_BLINDFOLD, OT_POCKETWATCH, @@ -682,11 +742,13 @@ enum OBTYPE { OT_CALTROP, OT_BROKENGLASS, OT_ICECHUNK, + OT_ICESHEET, OT_PUDDLEWATER, OT_PUDDLEWATERL, OT_SLIMEPOOL, OT_VOMITPOOL, OT_BLOODSTAIN, + OT_BLOODSPLASH, OT_BLOODPOOL, OT_SOGGYPAPER, OT_FLESHCHUNK, @@ -701,6 +763,11 @@ enum OBTYPE { OT_POISONPUFF, // armour - body OT_ARMOURLEATHER, + OT_ARMOURRING, + OT_ARMOURSCALE, + OT_ARMOURCHAIN, + OT_ARMOURSPLINT, + OT_ARMOURPLATE, OT_FLAKJACKET, OT_OVERALLS, OT_COTTONSHIRT, @@ -720,6 +787,7 @@ enum OBTYPE { OT_SHOESLEATHER, OT_BOOTSLEATHER, OT_BOOTSRUBBER, + OT_BOOTSSPIKED, // armour - hands OT_GLOVESCLOTH, OT_GLOVESLEATHER, @@ -736,6 +804,8 @@ enum OBTYPE { OT_SUNGLASSES, // armour - shields OT_BUCKLER, + OT_SHIELD, + OT_SHIELDLARGE, // rings OT_RING_INVULN, OT_RING_MPREGEN, @@ -752,6 +822,14 @@ enum OBTYPE { OT_ACIDATTACK, OT_TOUCHPARALYZE, OT_TOUCHPARALYZE2, + // missiles / ammo + OT_ARROW, + OT_BOLT, + OT_DART, + OT_NANODART, + OT_JAVELIN, + OT_BULLET, + OT_RUBBERBULLET, // stabbing weapons OT_DAGGER, OT_COMBATKNIFE, @@ -761,6 +839,7 @@ enum OBTYPE { OT_QUICKBLADE, // chopping weapons OT_AXE, + OT_HANDAXE, OT_BATTLEAXE, OT_GREATAXE, // slashing weapons @@ -770,6 +849,7 @@ enum OBTYPE { OT_SHORTSWORD, OT_SCIMITAR, OT_LONGSWORD, + OT_GREATSWORD, OT_ORNSWORD, // polearms OT_SPEAR, @@ -778,6 +858,8 @@ enum OBTYPE { OT_STICK, OT_SPANNER, OT_CLUB, + OT_FLAIL, + OT_FLAILHEAVY, OT_MACE, OT_MORNINGSTAR, OT_GREATCLUB, @@ -785,9 +867,9 @@ enum OBTYPE { // projectile weapons OT_REVOLVER, OT_SLING, - // ammo - OT_BULLET, - OT_RUBBERBULLET, + OT_BOW, + OT_LONGBOW, + OT_CROSSBOWHAND, // holy weapons OT_HANDOFGOD, @@ -822,14 +904,15 @@ enum NOISETYPE { }; enum LFSIZE { - SZ_MINI, // ie. fly - SZ_TINY, // ie. mouse - SZ_SMALL, // ie. cat - SZ_MEDIUM, // ie. wolf/dog - SZ_HUMAN, // ie. human-sized - SZ_LARGE, // ie. bear/horse - SZ_HUGE, // ie. elephant, dragon - SZ_ENORMOUS, // ie. ??? kraken? + SZ_MINI = 0, // ie. fly + SZ_TINY = 1, // ie. mouse + SZ_SMALL = 2, // ie. cat + SZ_MEDIUM = 3, // ie. wolf/dog + SZ_HUMAN = 4, // ie. human-sized + SZ_LARGE = 5, // ie. bear/horse + SZ_HUGE = 6, // ie. elephant, dragon, giant + SZ_ENORMOUS = 7, // ie. ??? kraken, titan + SZ_MAX = 100 }; @@ -854,7 +937,8 @@ enum FLAG { F_UNIQUE, // only one may appear F_GLYPH, // override the glyph with the first char of text F_NOPICKUP, // cannot pick this up - F_IMPASSABLE, // cannot walk past this + F_IMPASSABLE, // cannot walk past this if your size if v0 or smaller + F_CRUSHABLE, // if you are bigger than size v0, walking on this crushes it F_BLOCKSVIEW, // cannot see past this F_BLOCKSTHROW, // cannot throw past this F_DIETEXT, // text when the object dies @@ -918,15 +1002,22 @@ enum FLAG { F_STAIRDIR, // val0 = direcion F_OPPOSITESTAIRS, // val0 = opposite kind of stairs F_MAPLINK, // val0 = map to link to. optional v1/v2 = x/y + + // ob interaction flags + F_SHARP, // does damage when you step on it. v0/1 are min/max dam + F_SLIPPERY, // you might slip when stepping on it. v0 is amt + F_SLIPMOVE, // if someone slips on this, it will move to an adj cell F_FLAMMABLE, // object will catch alight if burnt // object mods/effects F_ONFIRE, // burning, also deals extra fire damage - F_HEADLESS, // for corpses + F_HEADLESS, // for corpses. can go on LFs too. // weapon flags F_OBATTACKDELAY, // how long weapon takes to attack F_DAMTYPE, // val0 = damage type F_DAM, // val0 = ndice, val1 = nsidesondie, val2 = mod + F_MISSILEDAM, // val0 = dam if it hits (without speed multiplier) F_ACCURACY, // 100 - val0 = penalty to tohit% (ie. higher is better) + F_ARMOURPIERCE, // goes through armour F_TWOHANDED, // weapon uses two hands to weild F_FIREARM, // this weapon is equipped in bp_secweapon, not _weapon. F_FIRESPEED, // how fast this weapon shoots projectimes @@ -934,7 +1025,7 @@ enum FLAG { F_RANGE, // range of projectile firing weapon F_FLAMESTRIKE, // causes fires where you hit F_BALANCE, // heals target if their maxhp < your maxhp - F_REVENGE, // causes damage based on your max hp + F_REVENGE, // causes damage based on your hp // tech flags F_RNDCHARGES, // ob starts with between val0 and val1 charges // this will cause F_CHARGES to be filled in @@ -944,7 +1035,6 @@ enum FLAG { F_REFILLWITH, // pour obj id val0 onto this to refill its charges // ob appearance flags F_SHINY, - F_SHARP, // does damage when you step on it. v0/1 are min/max dam // armour flags F_ARMOURRATING, // val0 * 2 = pct of damage reduced F_SHIELD, // this is a shield - use special bodyhitchance code @@ -967,8 +1057,13 @@ enum FLAG { F_MPCOST, // v0=mp cost of spell. if missing, mpcost if splev^2 //F_SPELLLETTER, // text[0] = letter to cast this spell F_AICASTATVICTIM, // hints for AI to cast spells + F_AICASTATADJVICTIM, // hints for AI to cast spells F_AICASTATSELF, // hints for AI to cast spells + F_AICASTNEXTTOVICTIM, // hints for AI to cast spells F_AICASTANYWHERE, // hints for AI to cast spells + F_AIBOOSTITEM, // ai will use this item to boost/buff itself + F_AIHEALITEM, // ai will use this item when low on hp + F_AIFLEEITEM, // ai will use this item when fleeing // lifeform flags F_DEBUG, // debugging enabled F_ATTRMOD, // modify attribute val0 by val1. ie. 0=A_STR,1=-3 @@ -990,6 +1085,7 @@ enum FLAG { F_STARTSTR, // val0 = start str bracket (ie. STR_STRONG) F_CORPSETYPE, // text field specifies what corpse obtype to leave F_NOCORPSE, // monster's body crumbles to dust after death + F_LFSUFFIX, // text = suffix. eg. "skeleton" F_VISRANGE, // how far you can see (in the light) F_VISRANGEMOD, // modifications to visrange F_GUNTARGET, // current projectile weapon target @@ -1005,6 +1101,8 @@ enum FLAG { F_WANTSBETTERWEP, // lf will look for better weapons, val1=covets F_WANTSBETTERARM, // lf will look for better armour, val1=covets F_FLEEONDAM, // lf will run away instead of counterattacking + F_FLEEONHPPCT, // lf will run away if its hp drop to v0% or lower + F_NOFLEE, // lf will not run away F_TARGET, // lf will attack lfid v0. lastknown x/y is v1/v2 F_TARGETCELL, // lf will go towards this place. val0=x,val1=y F_FLEEFROM, // lf will run away from this lf id @@ -1044,10 +1142,18 @@ enum FLAG { F_INDUCEFEAR, // causes fear when you attack it F_AUTOCREATEOB, // produces obtype 'text' wherever it walks, v0=radius // (only if ob of that type not already there) + F_PACKATTACK, // deal v0 extra damage of type v1 if there are + // v2 or more monsters matching f->text next + // to the victim + F_PHALANX, // gain v0 AR if v2 or more adj monsters matching f->text // INTRINSICS + F_ASLEEP, // is asleep F_BLIND, // cannot see anything F_CANCAST, // can cast the spell val0 (need MP) F_CANWILL, // can cast the spell val0 without using MP + // v1 is counter untiluse + // v2 is what you need to use it + // ie. when v1 == v2, ability is ready. F_DETECTAURAS, // autodetect bless/curse F_DETECTLIFE, // autodetect nearby lifeforms in orthogonal dist v0 F_DETECTMAGIC, // autodetect magic/special objects @@ -1058,12 +1164,19 @@ enum FLAG { F_FASTMOVE, // modifier for move speed F_FOODPOISONED, // has food poisoning F_FREEZINGTOUCH,// next thing touched turns to ice! + F_GRABBEDBY,// you've been grabbed by lf id v0 + F_GRABBING, // you are grabbing lf id v0 + F_HEAVYBLOW, // next attack is a heavy blow + F_QUICKBITE, // deals v0 d d1 + d2 damage when you hit a bleeding victim + // (bypasses armour) F_GRAVBOOSTED,// cannot walk or throw stuff + F_PAIN, // take damage if you walk F_PARALYZED,// cannot do anything F_FROZEN, // made of ice F_INVULNERABLE,// immune to most damage F_LEVITATING, // like flying but uncontrolled F_MAGSHIELD,// magnetic shield + F_NAUSEATED, // lf has a stench penalty of v0 (-v0*10 to hit). F_NONCORPOREAL,// can walk through walls F_OMNIPOTENT, // knows extra info F_PHOTOMEM, // you don't forget your surroundings @@ -1071,6 +1184,9 @@ enum FLAG { F_RESISTMAG, // immune to most magic effects F_MPREGEN, // regenerate MP at val0 per turn F_SEEINDARK, // nightvis range is val0 + F_SEEWITHOUTEYES, // doesn't need eyes to see + F_STABILITY, // doesn't slip over + F_STENCH, // creatures within v0 gain f_nauseated = v1 F_PRODUCESLIGHT, // produces light of val0 radius. // (but not for obs in pack) // if val2 is true, will only make light if ob @@ -1081,6 +1197,8 @@ enum FLAG { F_CANSEETHROUGHMAT, //val0=kind of material you can see through F_SPRINTING, // you are sprinting F_TIRED, // you are too tired to sprint + F_DODGES, // you dodge missed attacks + F_NOTIME, // this lf's actions don't take time // COMBAT F_HASATTACK, // objecttype id to use when attacking unarmed // if val0-3 are filled in, they override the object's @@ -1096,8 +1214,11 @@ enum FLAG { // for jobs F_IFPCT, // only add the NEXT job flag if rnd(1,100) <= v0. - // if v2=IFMONSTER, also only add the next one for non-players - // if v2=IFPLAYER, also only add the next one for players + F_ELSE, + F_IFPLAYER, + F_IFMONSTER, + F_ENDIFPLAYER, + F_ENDIFMONSTER, // F_NULL = -1 @@ -1126,8 +1247,16 @@ enum HUNGER { #define B_FALSE (0) #define B_TRUE (-1) -#define B_TEMP (-1) -#define B_PERM (-2) +//#define B_TEMP (-1) +//#define B_PERM (-2) +//#define B_NOT (-3) + +enum LIGHTLEV { + L_DARK = -1, + L_NOTLIT = 0, + L_TEMP = 1, + L_PERM = 2, +}; #define B_DIEONFAIL (-1) #define B_BLUNTONFAIL (-2) @@ -1200,8 +1329,58 @@ enum ERROR { E_NOMP = 27, E_AVOIDOB = 28, E_FROZEN = 29, + E_TOOBIG = 30, + E_NOTREADY = 31, + E_BLIND = 32, + E_GRABBEDBY = 33, + E_CANTMOVE = 34, }; + +enum COMMAND { + CMD_AIM, + CMD_CLOSE, + CMD_DOWN, + CMD_DROP, + CMD_DROPMULTI, + CMD_EAT, + CMD_FIRE, + CMD_FIRENEW, + CMD_FORCEATTACK, + CMD_HELP, + CMD_INFOARMOUR, + CMD_INFOKNOWLEDGE, + CMD_INFOPLAYER, + CMD_INV, + CMD_LOOKAROUND, + CMD_LOOKHERE, + CMD_MAGIC, + CMD_MSGHIST, + CMD_OPERATE, + CMD_PICKLOCK, + CMD_PICKUP, + CMD_POUR, + CMD_QUAFF, + CMD_QUIT, + CMD_READ, + CMD_REST, + CMD_RESTFULL, + CMD_SAVEQUIT, + CMD_TAKEOFF, + CMD_UP, + CMD_WEAR, + CMD_WEILD, +}; + +// command types +typedef struct command_s { + enum COMMAND id; + char ch; + char *desc; + struct command_s *next, *prev; +} command_t; + + typedef struct map_s { int id; int depth; @@ -1223,7 +1402,7 @@ typedef struct cell_s { int roomid; struct celltype_s *type; struct obpile_s *obpile; - int lit; + enum LIGHTLEV lit; char *writing; @@ -1252,6 +1431,7 @@ typedef struct celltype_s { typedef struct race_s { enum RACE id; + enum RACE baseid; struct material_s *material; char *name; char glyph; @@ -1409,10 +1589,12 @@ enum OBMOD { OM_FEEBLENESS, OM_FLIGHT, OM_GIANTSTRENGTH, + OM_IMPACT, OM_INTELLIGENCE, OM_KNOWLEDGE, OM_LEVITATION, OM_MAGRESIST, + OM_SHARPNESS, OM_PYROMANIA, OM_REVENGE, OM_SLOTH, diff --git a/doc/add_damtype.txt b/doc/add_damtype.txt index 9cd11af..ae768fe 100644 --- a/doc/add_damtype.txt +++ b/doc/add_damtype.txt @@ -8,3 +8,8 @@ in objcets.c: in attack.c update getattackverb if required update getkillverb if required + + update attackob() to say whether dealing this damtype to an object + will dull a weapon. + ie. hitting a door with DT_CHOP won't damage the weapon + ie. hitting a door with DT_SLASH _will_ damage the weapon diff --git a/doc/add_potions.txt b/doc/add_potions.txt new file mode 100644 index 0000000..ccf6065 --- /dev/null +++ b/doc/add_potions.txt @@ -0,0 +1,6 @@ +1. add it normally. + +2. if monsters should drink it, add a flag: + f_aiboostitem + f_aihealitem + f_aifleeitem diff --git a/doc/adding_spells.txt b/doc/adding_spells.txt index 08886d5..70368f3 100644 --- a/doc/adding_spells.txt +++ b/doc/adding_spells.txt @@ -9,6 +9,7 @@ objects.c: (optional) add a scroll to do the same effect, use F_LINKSPELL (optional) add a potion to do the same effect (optional) add a spellbook to learn it + assign AI hint flags so it knows how to cast it spell.c: implement the effects @@ -18,3 +19,7 @@ spell.c: target having antimagic - use hasmr(victim) blindness if the effect is vision-based +ai.c + update aigetspelltarget(); + update aigetattackspell(); + diff --git a/doc/dnd.txt b/doc/dnd.txt new file mode 100644 index 0000000..2818d44 --- /dev/null +++ b/doc/dnd.txt @@ -0,0 +1,3 @@ +Converting dndv4 monsters: + hp / 8 + ac / 2 (sometimes use evasion instead though) diff --git a/doc/object_ideas.txt b/doc/object_ideas.txt new file mode 100644 index 0000000..65fae4f --- /dev/null +++ b/doc/object_ideas.txt @@ -0,0 +1,9 @@ +hay +pebbles +torch +boulder / monolith / statue +shackles +chain +bone +skeleton +scrap of material diff --git a/doc/throwspeeds.txt b/doc/throwspeeds.txt new file mode 100644 index 0000000..c0922a6 --- /dev/null +++ b/doc/throwspeeds.txt @@ -0,0 +1,10 @@ +helpless/feeble = 0 +weak/vweak = 1 +avg/strong = 2 +mighty = 3 +titanic = 4 + +gun = 10 + +only apply damage to armour if speed >= 3 + (or armour piercing) diff --git a/doc/wandwondereffects b/doc/wandwondereffects new file mode 100644 index 0000000..86269c4 --- /dev/null +++ b/doc/wandwondereffects @@ -0,0 +1,24 @@ +#Slow the target down +#Summon a cloud of toxic gas +#Summon huge swarm of butterflies +#Turn target to stone +#Cause darkness +#Fireball +swap places ? +Make all inanimate objects in range vanish +Makes leaves grow from target +Shoots forth semi-precious gems (this is actually an attack, they shoot out really fast) +Cause a funky light show + +Turn target into a giant + + str? +Shrink wand user to halfling size + + acc? + +Makes user invisible +Summon a mouse, elephant, or rhino +Cause grass to grow +Lightning Bolt +Summon a great wind (ie. airblast spellO) +Cause heavy rainfall +Make the wand wielder believe that something else happened diff --git a/flag.c b/flag.c index a7195d9..4f48f4a 100644 --- a/flag.c +++ b/flag.c @@ -92,6 +92,7 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, if (gamestarted) { if (f->pile->owner) { if (announceflaggain(f->pile->owner, f)) { + interrupt(f->pile->owner); f->known = B_TRUE; if (f->obfrom) { // ooooooo it's getting -1 ?!?!?!? object_t *ob; @@ -238,14 +239,18 @@ flag_t *hasflagval_real(flagpile_t *fp, int id, int val1, int val2, int val3, ch return NULL; } -void killflagsofid(flagpile_t *fp, enum FLAG fid) { +// returns true if we did something +int killflagsofid(flagpile_t *fp, enum FLAG fid) { flag_t *f,*nextf; + int donesomething = B_FALSE; for (f = fp->first ; f ; f = nextf) { nextf = f->next; if (f->id == fid) { killflag(f); + donesomething = B_TRUE; } } + return donesomething; } void killflag(flag_t *f) { @@ -273,7 +278,9 @@ void killflag(flag_t *f) { // notify if (gamestarted) { if (f->pile->owner) { - announceflagloss(f->pile->owner, f); + if (announceflagloss(f->pile->owner, f)) { + interrupt(f->pile->owner); + } } else if (f->pile->ob) { announceobflagloss(f->pile->ob, f); } diff --git a/flag.h b/flag.h index f700dc2..2f94dea 100644 --- a/flag.h +++ b/flag.h @@ -14,7 +14,7 @@ flag_t *hasflag_real(flagpile_t *fp, int id, int wantknown); flag_t *hasflagval(flagpile_t *fp, int id, int val1, int val2, int val3, char *text); flag_t *hasflagvalknown(flagpile_t *fp, int id, int val1, int val2, int val3, char *text); flag_t *hasflagval_real(flagpile_t *fp, int id, int val1, int val2, int val3, char *text, int wantknown); -void killflagsofid(flagpile_t *fp, enum FLAG fid); +int killflagsofid(flagpile_t *fp, enum FLAG fid); void killflag(flag_t *f); void killflagpile(flagpile_t *fp); void makeflagknown(flagpile_t *fp); diff --git a/io.c b/io.c index f77f56a..7e92213 100644 --- a/io.c +++ b/io.c @@ -45,6 +45,7 @@ extern FILE *logfile; extern enum OBCLASS sortorder[]; extern knowledge_t *knowledge; extern objecttype_t *objecttype; +extern command_t *firstcommand; extern int gamestarted; extern long curtime; @@ -245,6 +246,37 @@ void animradial(cell_t *src, int radius, char ch) { } +void animradialorth(cell_t *src, int radius, char ch) { + int i; + int x,y; + cell_t *c; + + for (i = 0; i <= radius; i++) { + int drawn = B_FALSE; + + // update screen + updateviewfor(src); + drawlevelfor(player); + + for (y = src->y - radius ; y <= src->y + radius ; y++) { + for (x = src->x - radius ; x <= src->x + radius ; x++) { + c = getcellat(src->map, x, y); + if (c && haslos(player, c) && (getcelldist(src, c) <= i)) { + // draw char & cursor at its current pos... + mvwprintw(gamewin, c->y - viewy, c->x - viewx, "%c", ch); + drawn = B_TRUE; + } + } + } + + wrefresh(gamewin); + if (drawn) { + usleep(ANIMDELAY); + } + } + +} + char askchar(char *prompt, char *validchars, char *def, int showchars) { char buf[BUFLEN]; char *p; @@ -358,6 +390,7 @@ cell_t *askcoords(char *prompt, int targettype) { strcpy(buf, ""); if (haslos(player, c)) { if (c->lf) { + flag_t *f; object_t *wep; char extrainfo[BUFLEN]; strcpy(extrainfo, ""); @@ -368,7 +401,10 @@ cell_t *askcoords(char *prompt, int targettype) { sprintf(extrainfo, "level %d, ",c->lf->level); } */ - if (ispeaceful(c->lf)) { + if (isfriendly(c->lf)) { + if (strlen(extrainfo)) strcat(extrainfo, ", "); + strcat(extrainfo, "ally"); + } else if (ispeaceful(c->lf)) { if (strlen(extrainfo)) strcat(extrainfo, ", "); strcat(extrainfo, "peaceful"); } @@ -376,6 +412,10 @@ cell_t *askcoords(char *prompt, int targettype) { if (strlen(extrainfo)) strcat(extrainfo, ", "); strcat(extrainfo, "fleeing"); } + if (lfhasflag(c->lf, F_ASLEEP)) { + if (strlen(extrainfo)) strcat(extrainfo, ", "); + strcat(extrainfo, "asleep"); + } // hp if (isgenius(player)) { char buf2[BUFLEN]; @@ -402,6 +442,34 @@ cell_t *askcoords(char *prompt, int targettype) { if (strlen(extrainfo)) strcat(extrainfo, ", "); strcat(extrainfo, buf2); } + + f = lfhasflag(c->lf, F_GRABBING); + if (f) { + lifeform_t *lf2; + lf2 = findlf(NULL, f->val[0]); + if (lf2) { + char lfname2[BUFLEN]; + char buf2[BUFLEN]; + getlfname(lf2, lfname2); + sprintf(buf2, "holding %s",lfname2); + if (strlen(extrainfo)) strcat(extrainfo, ", "); + strcat(extrainfo, buf2); + } + } + + f = lfhasflag(c->lf, F_GRABBEDBY); + if (f) { + lifeform_t *lf2; + lf2 = findlf(NULL, f->val[0]); + if (lf2) { + char lfname2[BUFLEN]; + char buf2[BUFLEN]; + getlfname(lf2, lfname2); + sprintf(buf2, "held by %s",lfname2); + if (strlen(extrainfo)) strcat(extrainfo, ", "); + strcat(extrainfo, buf2); + } + } if (strlen(extrainfo)) { char buf2[BUFLEN]; @@ -568,6 +636,10 @@ int announceflaggain(lifeform_t *lf, flag_t *f) { } donesomething = B_TRUE; break; + case F_ASLEEP: + msg("%s fall%s asleep.",lfname, isplayer(lf) ? "" : "s"); + donesomething = B_TRUE; + break; case F_BLIND: if (isplayer(lf)) { msg("%s cannot see!",lfname); @@ -639,6 +711,12 @@ int announceflaggain(lifeform_t *lf, flag_t *f) { donesomething = B_TRUE; } break; + case F_DODGES: + if (isplayer(lf)) { // don't know if monsters get it + msg("You can now dodge attacks."); + donesomething = B_TRUE; + } + break; case F_INVULNERABLE: if (isplayer(lf)) { // don't know if monsters get it msg("You feel invulnerable!"); @@ -680,6 +758,15 @@ int announceflaggain(lifeform_t *lf, flag_t *f) { donesomething = B_TRUE; free(buf2); break; + case F_GRABBEDBY: + lf2 = findlf(NULL, f->val[0]); + if (lf2) { + getlfname(lf2, buf); + msg("%s %s %s!",buf, isplayer(lf2) ? "grab" : "grabs", lfname); + donesomething = B_TRUE; + } + break; + // don't announce grabbing. case F_GRAVBOOSTED: msg("%s %s stuck to the floor!",lfname, isplayer(lf) ? "are" : "is"); donesomething = B_TRUE; @@ -692,10 +779,18 @@ int announceflaggain(lifeform_t *lf, flag_t *f) { msg("%s %s surrounded by a magnetic shield!",lfname, isplayer(lf) ? "are" : "is"); donesomething = B_TRUE; break; + case F_NAUSEATED: + msg("%s %s nauseated by a disgusting stench!",lfname, isplayer(lf) ? "are" : "is"); + donesomething = B_TRUE; + break; case F_NONCORPOREAL: msg("%s%s body becomes transparent!",lfname, getpossessive(lfname)); donesomething = B_TRUE; break; + case F_PAIN: + msg("%s%s skin erupts in stings and burns!",lfname, getpossessive(lfname)); + donesomething = B_TRUE; + break; case F_PARALYZED: if (isplayer(lf)) { msg("You cannot move!"); @@ -745,10 +840,12 @@ int announceflaggain(lifeform_t *lf, flag_t *f) { donesomething = B_TRUE; break; case F_TIRED: - if (isplayer(lf)) { // don't know if monsters get it + if (isplayer(lf)) { msg("You are exhausted."); - donesomething = B_TRUE; + } else { + msg("%s looks exhausted.",lfname); } + donesomething = B_TRUE; break; case F_VISRANGEMOD: if (isplayer(lf)) { // don't know if monsters get it @@ -790,19 +887,21 @@ int announceflaggain(lifeform_t *lf, flag_t *f) { return donesomething; } -void announceflagloss(lifeform_t *lf, flag_t *f) { +int announceflagloss(lifeform_t *lf, flag_t *f) { char lfname[BUFLEN]; + lifeform_t *lf2; + int donesomething = B_FALSE; if (lf->race->id == R_DANCINGWEAPON) { - return; + return B_FALSE; } - if (isdead(player)) return; + if (isdead(player)) return B_FALSE; getlfname(lf, lfname); // player can't see? if (!haslos(player, lf->cell)) { - return; + return B_FALSE; } switch (f->id) { case F_ATTRMOD: @@ -817,6 +916,7 @@ void announceflagloss(lifeform_t *lf, flag_t *f) { msg("%s %s %s!",lfname, isplayer(lf) ? "feel" : "seems", (f->val[1] > 0) ? "less agile" : "more gile"); break; } + donesomething = B_TRUE; break; case F_ATTRSET: if (f->val[1] != getattr(lf, f->val[0])) { @@ -833,10 +933,16 @@ void announceflagloss(lifeform_t *lf, flag_t *f) { msg("%s %s %s!",lfname, isplayer(lf) ? "feel" : "seems", (f->val[1] > myatt) ? "non-agile" : "agile"); break; } + donesomething = B_TRUE; } break; + case F_ASLEEP: + msg("%s wake%s up.",lfname, isplayer(lf) ? "" : "s"); + donesomething = B_TRUE; + break; case F_BLIND: msg("%s can see again.",lfname); + donesomething = B_TRUE; break; case F_CANCAST: if (isplayer(lf)) { // don't know if monsters get it @@ -844,36 +950,44 @@ void announceflagloss(lifeform_t *lf, flag_t *f) { ot = findot(f->val[0]); if (ot) { msg("You have forgotten how to cast '%s'.", ot->name); + donesomething = B_TRUE; } } break; case F_DTIMMUNE: if (isplayer(lf)) { // don't know if monsters lose it msg("You are no longer immune to %s.", getdamnamenoun(f->val[0])); + donesomething = B_TRUE; } break; case F_DTRESIST: if (isplayer(lf)) { // don't know if monsters lose it msg("You are no longer resistant to %s.", getdamnamenoun(f->val[0])); + donesomething = B_TRUE; } break; case F_DTVULN: if (isplayer(lf)) { // don't know if monsters lose it msg("You are no longer vulnerable to %s.", getdamnamenoun(f->val[0])); + donesomething = B_TRUE; } break; case F_FASTACT: msg("%s %s",lfname, isplayer(lf) ? "are no longer accelerated." : "is no longer accelerated."); + donesomething = B_TRUE; break; case F_FASTMOVE: msg("%s %s slower.",lfname, isplayer(lf) ? "feel yourself moving" : "is now moving"); + donesomething = B_TRUE; break; case F_FLEEFROM: msg("%s stop%s fleeing.", lfname, isplayer(lf) ? "" : "s"); + donesomething = B_TRUE; break; case F_FOODPOISONED: if (isplayer(lf)) { // don't know if monsters lose it msg("You feel less sick now."); + donesomething = B_TRUE; } break; case F_CANWILL: @@ -881,39 +995,52 @@ void announceflagloss(lifeform_t *lf, flag_t *f) { switch (f->val[0]) { case OT_A_JUMP: msg("You no longer feel so good at jumping."); + donesomething = B_TRUE; break; default: break; } } break; + case F_DODGES: + if (isplayer(lf)) { // don't know if monsters lose it + msg("You can no longer dodge attacks."); + donesomething = B_TRUE; + } + break; case F_INVULNERABLE: if (isplayer(lf)) { // don't know if monsters lose it msg("You no longer feel invulnerable."); + donesomething = B_TRUE; } break; case F_DETECTAURAS: if (isplayer(lf)) { // don't know if monsters lose it msg("You can no longer detect auras."); + donesomething = B_TRUE; } break; case F_DETECTLIFE: if (isplayer(lf)) { // don't know if monsters get it msg("You can no longer detect nearby lifeforms."); + donesomething = B_TRUE; } break; case F_DETECTMAGIC: if (isplayer(lf)) { // don't know if monsters get it msg("You can no longer detect magical enchantments."); + donesomething = B_TRUE; } break; case F_DETECTMETAL: if (isplayer(lf)) { // don't know if monsters get it msg("You can no longer detect nearby metal."); + donesomething = B_TRUE; } break; case F_FLYING: msg("%s %s flying.", lfname, isplayer(lf) ? "cease" : "stops"); + donesomething = B_TRUE; break; case F_FROZEN: if (isplayer(lf)) { @@ -921,42 +1048,71 @@ void announceflagloss(lifeform_t *lf, flag_t *f) { } else { msg("%s thaws out.", lfname); } + donesomething = B_TRUE; + break; + case F_GRABBEDBY: + lf2 = findlf(NULL, f->val[0]); + if (lf2 && !isdead(lf2)) { + char buf[BUFLEN]; + getlfname(lf2, buf); + msg("%s releases %s.",buf, lfname); + donesomething = B_TRUE; + } break; case F_GRAVBOOSTED: msg("%s %s no longer stuck to the floor.",lfname, isplayer(lf) ? "are" : "is"); + donesomething = B_TRUE; break; case F_LEVITATING: msg("%s %s down to the ground.", lfname, isplayer(lf) ? "float" : "floats"); + donesomething = B_TRUE; break; case F_MAGSHIELD: - if (isplayer(lf)) { // don't know if monsters get it + if (isplayer(lf)) { // don't know if monsters lose it msg("Your magnetic shield vanishes."); + donesomething = B_TRUE; + } + break; + case F_NAUSEATED: + if (isplayer(lf)) { // don't know if monsters lose it + msg("You no longer feel nauseated."); + donesomething = B_TRUE; } break; case F_NONCORPOREAL: msg("%s%s body solidifies.",lfname, getpossessive(lfname)); + donesomething = B_TRUE; + break; + case F_PAIN: + msg("%s skin returns to normal.",lfname, getpossessive(lfname)); + donesomething = B_TRUE; break; case F_PARALYZED: if (isplayer(lf)) { // don't konw if it expires for monsters msg("You can move again."); + donesomething = B_TRUE; } break; case F_PHOTOMEM: if (isplayer(lf)) { // don't know if monsters lose it msg("Your feel like you might forget your surroundings."); + donesomething = B_TRUE; } break; case F_PRODUCESLIGHT: msg("%s stop%s glowing!", lfname, isplayer(lf) ? "" : "s"); + donesomething = B_TRUE; break; case F_REGENERATES: if (isplayer(lf)) { // don't know if monsters lose it msg("Your healing rate is no longer enhanced."); + donesomething = B_TRUE; } break; case F_RESISTMAG: if (isplayer(lf)) { // don't know if monsters lose it msg("You are no longer immune to magic."); + donesomething = B_TRUE; } break; /* @@ -969,21 +1125,30 @@ void announceflagloss(lifeform_t *lf, flag_t *f) { case F_SEEINDARK: if (isplayer(lf)) { // don't know if monsters lose it msg("You can no longer see in the dark."); + donesomething = B_TRUE; } break; case F_SLOWACT: msg("%s %s",lfname, isplayer(lf) ? "no longer feel sluggish." : "no longer looks sluggish."); + donesomething = B_TRUE; break; case F_SLOWMOVE: msg("%s %s faster.",lfname, isplayer(lf) ? "feel yourself moving" : "is now moving"); + donesomething = B_TRUE; break; case F_SPRINTING: - msg("%s %s sprinting.",lfname, isplayer(lf) ? "stop" : "stops"); + if (isplayer(lf)) { // don't know if monsters lose it (but you'll see them get exhausted) + msg("You stop sprinting."); + donesomething = B_TRUE; + } break; case F_TIRED: if (isplayer(lf)) { // don't know if monsters get it msg("You are no longer exhausted."); + } else { + msg("%s looks less exhausted.",lfname); } + donesomething = B_TRUE; break; case F_VISRANGEMOD: if (isplayer(lf)) { // don't know if monsters get it @@ -1010,19 +1175,23 @@ void announceflagloss(lifeform_t *lf, flag_t *f) { msg("Your vision is slightly reduced."); } } + donesomething = B_TRUE; } break; case F_XRAYVIS: if (isplayer(lf)) { // don't know if monsters lose it msg("The walls around you are no longer transparent."); + donesomething = B_TRUE; } break; default: // no message break; } + return donesomething; } + int announceobflaggain(object_t *o, flag_t *f) { int donesomething = B_FALSE; char obname[BUFLEN]; @@ -1036,7 +1205,7 @@ int announceobflaggain(object_t *o, flag_t *f) { if (!haslos(player, loc)) { return B_FALSE; } - real_getobname(o, obname, o->amt, B_FALSE, B_TRUE, B_TRUE); + real_getobname(o, obname, o->amt, B_TRUE, B_FALSE, B_TRUE, B_TRUE); if (o->pile->owner) { if (isplayer(o->pile->owner)) { @@ -1054,7 +1223,9 @@ int announceobflaggain(object_t *o, flag_t *f) { switch (f->id) { case F_ONFIRE: donesomething = B_TRUE; - if (o->birthtime != curtime) msg("%s catches on fire.",prefix); + // don't want "the flaming sword catches on fire" + real_getobname(o, obname, o->amt, B_FALSE, B_FALSE, B_TRUE, B_TRUE); + if (o->birthtime != curtime) msg("%s catch%s on fire.",prefix, (o->amt == 1) ? "es" : ""); break; case F_PRODUCESLIGHT: donesomething = B_TRUE; @@ -1078,7 +1249,7 @@ void announceobflagloss(object_t *o, flag_t *f) { if (!haslos(player, loc)) { return; } - real_getobname(o, obname, o->amt, B_FALSE, B_TRUE, B_TRUE); + real_getobname(o, obname, o->amt, B_TRUE, B_FALSE, B_TRUE, B_TRUE); if (o->pile->owner) { if (isplayer(o->pile->owner)) { @@ -1146,7 +1317,7 @@ object_t *doaskobject(obpile_t *op, char *prompt, int *count, int opts, enum FLA int finished; char nextlet = 'a'; int useobletters; - flag_t *f; + //flag_t *f; object_t *ammo; enum OBCLASS wantoc[MAXCANDIDATES]; va_list classes; @@ -1301,65 +1472,12 @@ object_t *doaskobject(obpile_t *op, char *prompt, int *count, int opts, enum FLA sprintf(buf2, " %c - %s", useobletters ? mylist[i]->letter : myletters[i], buf); - // charges - f = hasflag(mylist[i]->flags, F_CHARGES); - if (f && f->known) { - if (!hasflag(mylist[i]->flags, F_DONTSHOWCHARGES)) { - char chargestr[BUFLEN]; - if (f->val[0] > 0) { - sprintf(chargestr, " (%d charges left)",f->val[0]); - } else { - sprintf(chargestr, " (empty)"); - } - strcat(buf2, chargestr); - } - } + getobextrainfo(mylist[i], buf); - // activated - f = hasflag(mylist[i]->flags, F_ACTIVATED); - if (f) { - strcat(buf2, " [activated]"); - } - // condition - /* - f = hasflag(mylist[i]->flags, F_OBHP); - if (f) { - char condname[BUFLEN]; - getobconditionname(mylist[i], condname); - if (strlen(condname) > 0) { - strcat(buf2, " ["); - strcat(buf2, condname); - strcat(buf2, "]"); - } - } - */ - - - f = hasflag(mylist[i]->flags,F_EQUIPPED); - if (f) { - if (f->val[0] == BP_WEAPON) { - if (hasflag(mylist[i]->flags, F_TWOHANDED)) { - strcat(buf2, " (two-handed weapon)"); - } else { - strcat(buf2, " (weapon)"); - } - } else { - strcat(buf2, " ("); - strcat(buf2, getbodypartequipname(f->val[0])); - strcat(buf2, " "); - strcat(buf2, getbodypartname(f->val[0])); - strcat(buf2, ")"); - } - } - - // ammo? - if (ammo && (ammo == mylist[i])) { - strcat(buf2, " (current ammo)"); - } - - mvwprintw(mainwin, y, 0, buf2); + mvwprintw(mainwin, y, 0, "%s%s", buf2, buf); y++; } + if (mylist[i] == NULL) { nextpage = -1; } else { @@ -1830,7 +1948,6 @@ void clearmsg(void) { // use forced clear msg when we have // drawn over the whole screen, eg. -// getlfstats or describeob. void real_clearmsg(int force) { // remember message history if (force || strcmp(msgbuf, "")) { @@ -2045,6 +2162,13 @@ void describeob(object_t *o) { y++; } + f = hasflag(o->flags, F_ARMOURPIERCE); + if (f && f->known) { + mvwprintw(mainwin, y, 0, "Armour will not reduce %s damage.",(o->amt == 1) ? "its" : "their"); + y++; + } + + f = hasflag(o->flags, F_PICKLOCKS); if (f) { @@ -2147,6 +2271,9 @@ void describeob(object_t *o) { case F_GRAVBOOSTED: mvwprintw(mainwin, y, 0, "%s increases gravity around you.", buf); y++; break; + case F_DODGES: + mvwprintw(mainwin, y, 0, "%s allows you to dodge attacks.", buf); y++; + break; case F_INVULNERABLE: mvwprintw(mainwin, y, 0, "%s protects you from all physical harm.", buf); y++; break; @@ -2175,15 +2302,27 @@ void describeob(object_t *o) { case F_MAGSHIELD: mvwprintw(mainwin, y, 0, "%s surrounds you with a magnetic shield.", buf); y++; break; + case F_NAUSEATED: + mvwprintw(mainwin, y, 0, "%s causes you to feel nauseated.", buf); y++; + break; case F_NONCORPOREAL: mvwprintw(mainwin, y, 0, "%s makes you non-corporeal.", buf); y++; break; + case F_PAIN: + mvwprintw(mainwin, y, 0, "%s causes you intense pain.", buf); y++; + break; case F_PARALYZED: mvwprintw(mainwin, y, 0, "%s paralyzes you.", buf); y++; break; case F_PHOTOMEM: mvwprintw(mainwin, y, 0, "%s prevents you from forgetting your surroundings.", buf); y++; break; + case F_STABILITY: + mvwprintw(mainwin, y, 0, "%s prevents you from slipping over.", buf); y++; + break; + case F_STENCH: + mvwprintw(mainwin, y, 0, "%s makes you smell bad.", buf); y++; + break; case F_PRODUCESLIGHT: mvwprintw(mainwin, y, 0, "%s produces light.", buf); y++; break; @@ -2226,11 +2365,26 @@ void describeob(object_t *o) { } // show special properties where known + f = hasflag(o->flags, F_BALANCE); + if (f && f->known) { + mvwprintw(mainwin, y, 0, "It heals weaker enemies, and does extra damage to stronger ones."); + y++; + } f = hasflag(o->flags, F_FLAMESTRIKE); if (f && f->known) { mvwprintw(mainwin, y, 0, "It ignites fires wherever it hits."); y++; } + f = hasflag(o->flags, F_HEAVYBLOW); + if (f && f->known) { + mvwprintw(mainwin, y, 0, "Its powerful blows knock enemies backwards."); + y++; + } + f = hasflag(o->flags, F_REVENGE); + if (f && f->known) { + mvwprintw(mainwin, y, 0, "It does more damage as your HP are lowered."); + y++; + } y++; if (hasflag(o->flags, F_NOBLESS)) { @@ -2293,8 +2447,10 @@ void describespell(objecttype_t *ot) { } i = getmpcost(ot->id); - mvwprintw(mainwin, y, 0, "It costs %d MP to cast.",i); - y++; + if (i > 0) { + mvwprintw(mainwin, y, 0, "It costs %d MP to cast.",i); + y++; + } wrefresh(mainwin); @@ -2661,10 +2817,11 @@ void domagic(enum OBTYPE spellid, int cellx, int celly) { char buf[BUFLEN]; char buf2[BUFLEN]; char costbuf[BUFLEN]; - enum OBTYPE poss[MAXPILEOBS]; - int mpcost[MAXPILEOBS]; - int validspell[MAXPILEOBS]; - int nposs; + enum OBTYPE poss[MAXCANDIDATES]; + int mpcost[MAXCANDIDATES]; + char mpdesc[MAXCANDIDATES][BUFLEN]; + int validspell[MAXCANDIDATES]; + int nposs = 0; int i,n; enum SPELLSCHOOL lastschool; objecttype_t *ot; @@ -2673,7 +2830,7 @@ void domagic(enum OBTYPE spellid, int cellx, int celly) { // init the prompt if required. if (spellid == OT_NONE) { nposs = 0; - for (i = SS_ABILITY; i < SS_LAST; i++) { + for (i = SS_NONE+1; i < SS_LAST; i++) { // get list of spells/abilities we can cast at will for (ot = objecttype ; ot ; ot = ot->next) { if ((ot->obclass->id == OC_SPELL) || (ot->obclass->id == OC_ABILITY)) { @@ -2682,7 +2839,19 @@ void domagic(enum OBTYPE spellid, int cellx, int celly) { if (hasflagval(ot->flags, F_SPELLSCHOOL, i, NA, NA, NULL)) { poss[nposs] = ot->id; mpcost[nposs] = -1; - validspell[nposs] = B_TRUE; + if (f->val[2] == NA) { + sprintf(mpdesc[nposs], "(ready)"); + validspell[nposs] = B_TRUE; + } else { + if (f->val[1] == f->val[2]) { + sprintf(mpdesc[nposs], "(ready)"); + validspell[nposs] = B_TRUE; + } else { + sprintf(mpdesc[nposs], "(%d/%d)",f->val[1],f->val[2]); + validspell[nposs] = B_FALSE; + } + } + nposs++; } } @@ -2711,6 +2880,7 @@ void domagic(enum OBTYPE spellid, int cellx, int celly) { // add to list poss[nposs] = ot->id; mpcost[nposs] = cost; + sprintf(mpdesc[nposs], "(%d MP)", mpcost[nposs]); if (player->mp >= cost) { validspell[nposs] = B_TRUE; } else { @@ -2739,7 +2909,6 @@ void domagic(enum OBTYPE spellid, int cellx, int celly) { lastschool = SS_LAST; for (i = 0; i < nposs; i++) { - char append[BUFLEN]; ot = findot(poss[i]); assert(ot); @@ -2760,12 +2929,7 @@ void domagic(enum OBTYPE spellid, int cellx, int celly) { strcpy(costbuf, "(NOT CASTABLE) "); } - if (mpcost[i] == -1) { - sprintf(append, "(at will)"); - } else { - sprintf(append, "(%d MP)", mpcost[i]); - } - strcat(costbuf, append); + strcat(costbuf, mpdesc[i]); sprintf(buf, "%-30s%s", buf2, costbuf); // we don't want spell letters to change // every time you get a new spell, so the @@ -2793,7 +2957,7 @@ void domagic(enum OBTYPE spellid, int cellx, int celly) { } } else { msg("You don't have any spells or abilities!"); - finished = B_TRUE; + return; } } // end if spellid == NONE @@ -2829,7 +2993,7 @@ void domagic(enum OBTYPE spellid, int cellx, int celly) { if (ot->obclass->id == OC_SPELL) { castspell(player, spellid, targlf, NULL, targcell); } else { - useability(player, spellid); + useability(player, spellid, targlf, targcell); } finished = B_TRUE; } else { // describe it @@ -2994,6 +3158,35 @@ void dofire(void) { } } +void dohelp(void) { + int h; + int y; + command_t *c; + char *ftext= "%c %s"; + + h = getmaxy(mainwin); + + cls(); + centre(mainwin, 0, "COMMAND REFERENCE"); + y = 2; + + + for (c = firstcommand ; c ; c = c->next) { + mvwprintw(mainwin, y, 0, ftext, c->ch, c->desc); y++; + if (y >= (h-2)) { + centre(mainwin, h-1, "[Press any key]"); + getch(); + cls(); + y = 2; + } + } + centre(mainwin, h-1, "[Press any key]"); + getch(); + + drawscreen(); + real_clearmsg(B_TRUE); +} + void doinventory(obpile_t *op) { object_t *o; char buf[BUFLEN]; @@ -3127,6 +3320,7 @@ void donextguntarget(void) { if (i == startpos) { // no new targets found - keep current one. setguntarget(player, targ); + done = B_TRUE; } } } @@ -3335,6 +3529,24 @@ void drawscannedcell(cell_t *cell, int x, int y) { } */ +void downline(int *y, int h, char *heading, char *subheading) { + char headbuf[BUFLEN]; + sprintf(headbuf, "%s (continued)", heading); + (*y)++; + if (*y >= (h-2)) { + centre(mainwin, h-1, MORESTRING); + getch(); + cls(); *y = 0; + centre(mainwin, *y, headbuf); + *y += 2; + wmove(mainwin, *y, 0); + if (subheading) { + doheading(mainwin, y, 0, subheading); + } + } +} + + // draw a cell which we remember, but can't see void drawunviscell(cell_t *cell, int x, int y) { char glyph; @@ -3368,11 +3580,7 @@ void drawcellwithcontents(cell_t *cell, int x, int y) { if (cell->lf) { // lifeform here? char ch; // draw the lf's race glyph - if (isplayer(cell->lf) && !ispolymorphed(cell->lf)) { - ch = '@'; - } else { - ch = cell->lf->race->glyph; - } + ch = getlfglyph(cell->lf); mvwprintw(gamewin, y, x, "%c", ch); } else if (countobs(cell->obpile) > 0) { object_t *o; @@ -3435,6 +3643,17 @@ void drawlevelfor(lifeform_t *lf) { } } +void doheading(WINDOW *win, int *y, int x, char *what) { + int len; + char *buf; + len = strlen(what) + 1; + buf = malloc(len * sizeof(char)); + memset(buf, '-', (size_t)len); + mvwprintw(win, *y, x, what); (*y)++; + mvwprintw(win, *y, x, buf); (*y)++; + free(buf); +} + void initgfx(void) { int msgwinh = 2; int statwinh = 2; @@ -3987,6 +4206,9 @@ void handleinput(void) { case 'i': // inventory doinventory(player->pack); break; + case '?': // help + dohelp(); + break; case '@': // display player stats showlfstats(player, B_FALSE); break; @@ -4010,7 +4232,9 @@ void handleinput(void) { break; case 'm': // 'm'agic/abilities (magic) if (wantrepeat) { - domagic(repeatflag.val[2], repeatflag.val[0], repeatflag.val[1]); + //domagic(repeatflag.val[2], repeatflag.val[0], repeatflag.val[1]); + // don't repeat the target cell! + domagic(repeatflag.val[2], NA, NA); } else { domagic(OT_NONE, NA, NA); } @@ -4201,7 +4425,7 @@ void warn(char *format, ... ) { msg_real("%s", buf); } -void msglower(char *format, ... ) { +void msgnocap(char *format, ... ) { char buf[BUFLEN]; va_list args; @@ -4296,7 +4520,7 @@ void drawstatus(void) { // show player action speed getspeedname(getactspeed(player), buf2); if (strcmp(buf2, "normal")) { - strcat(buf, " "); + strcat(buf, " Act:"); capitaliseall(buf2); strcat(buf, buf2); } @@ -4324,6 +4548,11 @@ void drawstatus(void) { break; } + // show certain flags + if (lfhasflag(player, F_FOODPOISONED)) { + strcat(buf, " Sick"); + } + mvwprintw(statwin, 0, 0, buf); @@ -4565,6 +4794,7 @@ void showlfstats(lifeform_t *lf, int showall) { enum BODYPART missingbp[MAXBODYPARTS]; int nmissingbp; + h = getmaxy(mainwin); cls(); if (isplayer(lf)) { @@ -4683,7 +4913,7 @@ void showlfstats(lifeform_t *lf, int showall) { int dex; // just show name dex = getattr(lf, A_DEX); - getstrname(dex, buf); + getdexname(dex, buf); if (dex != lf->baseatt[A_DEX]) strcat(buf, "*"); mvwprintw(mainwin, y, 0, ftext, "DEX"); wprintw(mainwin, "%s", buf); y++; @@ -4702,7 +4932,7 @@ void showlfstats(lifeform_t *lf, int showall) { int iq; // just show name iq = getattr(lf, A_IQ); - getstrname(iq, buf); + getiqname(iq, buf); if (iq != lf->baseatt[A_IQ]) strcat(buf, "*"); mvwprintw(mainwin, y, 0, ftext, "IQ"); wprintw(mainwin, "%s", buf); y++; @@ -5043,19 +5273,90 @@ void showlfstats(lifeform_t *lf, int showall) { } } + // obvious physical effects + // (NON-obvious intrinsics etc go on next page) + f = lfhasknownflag(lf, F_ASLEEP); + if (f) { + mvwprintw(mainwin, y, 0, "%s %s sleeping.", you(lf), isplayer(lf) ? "are" : "is"); + y++; + } + + f = lfhasknownflag(lf, F_FLYING); + if (f && (f->known)) { + mvwprintw(mainwin, y, 0, "%s %s flying.", you(lf), isplayer(lf) ? "are" : "is"); + y++; + } + f = lfhasflag(lf, F_FROZEN); + if (f && (f->known)) { + mvwprintw(mainwin, y, 0, "%s %s been turned to ice, and %s slowly melting.", you(lf), isplayer(lf) ? "have" : "has", + isplayer(lf) ? "are" : "is"); + y++; + } + f = lfhasknownflag(lf, F_GRABBEDBY); + if (f && (f->known)) { + lifeform_t *lf2; + char grabbername[BUFLEN]; + lf2 = findlf(NULL, f->val[0]); + if (lf2) { + getlfname(lf2, grabbername); + } else { + strcpy(grabbername, "something"); + } + sprintf(buf,"%s %s being held by %s.",you(lf), isplayer(lf) ? "are" : "is", grabbername); + mvwprintw(mainwin, y, 0, buf); + y++; + } + f = lfhasknownflag(lf, F_GRABBING); + if (f && (f->known)) { + lifeform_t *lf2; + char grabeename[BUFLEN]; + lf2 = findlf(NULL, f->val[0]); + if (lf2) { + getlfname(lf2, grabeename); + } else { + strcpy(grabeename, "something"); + } + sprintf(buf,"%s %s holding on to %s.",you(lf), isplayer(lf) ? "are" : "is", grabeename); + mvwprintw(mainwin, y, 0, buf); + y++; + } + f = lfhasknownflag(lf, F_LEVITATING); + if (f && (f->known)) { + mvwprintw(mainwin, y, 0, "%s %s levitating.", you(lf), isplayer(lf) ? "are" : "is"); + y++; + } + f = lfhasflag(lf, F_NONCORPOREAL); + if (f && (f->known)) { + mvwprintw(mainwin, y, 0, "%s %s noncorporeal and can walk through walls.", you(lf), isplayer(lf) ? "are" : "is"); + y++; + } + f = lfhasflag(lf, F_PRODUCESLIGHT); + if (f && (f->known)) { + mvwprintw(mainwin, y, 0, "%s produce%s light.", you(lf), isplayer(lf) ? "" : "s"); + y++; + } + f = lfhasknownflag(lf, F_SPRINTING); + if (f) { + mvwprintw(mainwin, y, 0, "%s %s sprinting.", you(lf), isplayer(lf) ? "are" : "is"); + y++; + } + + // wait for key - - h = getmaxy(mainwin); centre(mainwin, h-1, "[Press any key]"); getch(); if (showall) { + int anyfound = B_FALSE; + char subheading[BUFLEN]; + int lev; + + sprintf(subheading, " %-4s%-25s%-22s%s","Lv","Spell", "School", "Cost"); + // now show intrinsics on next page cls(); - centre(mainwin, 0, "ABILITIES / EFFECTS"); + centre(mainwin, 0, "ABILITIES"); y = 2; - - // TODO : change this to be like monster - show all CANWILL & CANCAST abilities // show abilities (but not spells - they are displayed using a different // command) @@ -5063,57 +5364,69 @@ void showlfstats(lifeform_t *lf, int showall) { if (ot->obclass->id == OC_ABILITY) { f = lfhasknownflagval(lf, F_CANWILL, ot->id, NA, NA, NULL); if (f && (f->known)) { - mvwprintw(mainwin, y, 0, ot->desc); - y++; + char expirebuf[BUFLEN]; + if (f->val[2] == NA) { + sprintf(expirebuf, " (at will)"); + } else { + sprintf(expirebuf, " (every %d turn%s)",f->val[2], + (f->val[2] == 1) ? "" : "s"); + } + sprintf(buf, "%-12s%s%s", ot->name, ot->desc, expirebuf); + mvwprintw(mainwin, y, 0, buf); + downline(&y, h, "ABILITIES", NULL); } } } - wmove(mainwin, y, 0); - - if (!isplayer(lf)) { - int first = B_TRUE; - int anyfound = B_FALSE; - // show spells monster can cast using mp + centre(mainwin, h-1, "[Press any key]"); + getch(); + cls(); y = 0; + //wmove(mainwin, y, 0); + centre(mainwin, y, "SPELLS"); y += 2; + doheading(mainwin, &y, 0, subheading); + //if (!isplayer(lf)) { + // show spells monster can cast using mp + for (lev = 0; lev <= 9; lev++) { for (ot = objecttype ; ot ; ot = ot->next) { if (ot->obclass->id == OC_SPELL) { - f = lfhasknownflagval(lf, F_CANCAST, ot->id, NA, NA, NULL); - if (f && (f->known)) { - if (first) { - wprintw(mainwin, "%s can use mana to cast the following spells:\n",you(lf)); - first = B_FALSE; + int thislev; + thislev = getspelllevel(ot->id); + if (thislev == lev) { + f = lfhasknownflagval(lf, F_CANWILL, ot->id, NA, NA, NULL); + if (!f) { + f = lfhasknownflagval(lf, F_CANCAST, ot->id, NA, NA, NULL); + } + if (f && (f->known)) { + char mpbuf[BUFLEN]; + int mpcost; + mpcost = getmpcost(ot->id); + if (mpcost) { + sprintf(mpbuf, "%d MP", mpcost); + } else { + sprintf(mpbuf, "At will"); + } + sprintf(buf, " %-4d%-25s%-22s%s",thislev, ot->name, getschoolname(getspellschool(ot->id)), mpbuf); + mvwprintw(mainwin, y, 0, "%s\n", buf); + anyfound = B_TRUE; + downline(&y, h, "SPELLS", subheading); } - sprintf(buf, " %s (%d MP)",ot->name, getmpcost(ot->id)); - wprintw(mainwin, "%s\n", buf); - anyfound = B_TRUE; } } } - if (anyfound) wprintw(mainwin, "\n"); - // show spells at will... - first = B_TRUE; - anyfound = B_FALSE; - for (ot = objecttype ; ot ; ot = ot->next) { - if (ot->obclass->id == OC_SPELL) { - f = lfhasknownflagval(lf, F_CANWILL, ot->id, NA, NA, NULL); - if (f && (f->known)) { - if (first) { - wprintw(mainwin, "%s can cast the following spells at will:\n",you(lf)); - first = B_FALSE; - } - sprintf(buf, " %s (%s)\n",ot->name, ot->desc); - wprintw(mainwin, "%s", buf); - y++; - anyfound = B_TRUE; - } - } - } - if (anyfound) wprintw(mainwin, "\n"); } + if (!anyfound) { + mvwprintw(mainwin, y, 0, "You cannot cast any spells."); + } + //} + centre(mainwin, h-1, "[Press any key]"); + getch(); + cls(); y = 0; - getyx(mainwin, y, x); x = 0; // override + // down a line. + centre(mainwin, y, "EFFECTS"); + y += 2; // show intrinsics f = lfhasknownflag(lf, F_ATTRSET); @@ -5166,11 +5479,6 @@ void showlfstats(lifeform_t *lf, int showall) { mvwprintw(mainwin, y, 0, "%s receive enhanced knowledge about the world.", you(lf)); y++; } - f = lfhasknownflag(lf, F_FLYING); - if (f && (f->known)) { - mvwprintw(mainwin, y, 0, "%s %s flying.", you(lf), isplayer(lf) ? "are" : "is"); - y++; - } f = lfhasknownflag(lf, F_FOODPOISONED); if (f && (f->known)) { sprintf(buf, "%s have food poisoning.", you(lf)); @@ -5182,6 +5490,37 @@ void showlfstats(lifeform_t *lf, int showall) { mvwprintw(mainwin, y, 0, buf); y++; } + f = lfhasflag(lf, F_NAUSEATED); + if (f && (f->known)) { + mvwprintw(mainwin, y, 0, "%s %s nauseated.", you(lf), isplayer(lf) ? "are" : "is"); + y++; + } + f = lfhasknownflag(lf, F_PACKATTACK); + if (f && (f->known)) { + sprintf(buf,"%s deal%s extra damage when in a %s pack.", you(lf), isplayer(lf) ? "" : "s", + f->text); + mvwprintw(mainwin, y, 0, buf); + y++; + } + f = lfhasknownflag(lf, F_PHALANX); + if (f && (f->known)) { + sprintf(buf,"%s gain%s %d extra armour rating when in a %s pack.", you(lf), isplayer(lf) ? "" : "s", + f->val[0], f->text); + mvwprintw(mainwin, y, 0, buf); + y++; + } + f = lfhasknownflag(lf, F_HEAVYBLOW); + if (f && (f->known)) { + sprintf(buf,"%s attacks knock enemies back.", getpossessive(you(lf))); + mvwprintw(mainwin, y, 0, buf); + y++; + } + f = lfhasknownflag(lf, F_QUICKBITE); + if (f && (f->known)) { + sprintf(buf,"%s can bite wounded enemies for extra damage.", you(lf)); + mvwprintw(mainwin, y, 0, buf); + y++; + } f = lfhasknownflag(lf, F_FREEZINGTOUCH); if (f && (f->known)) { strcpy(buf,"The next object you touch will turn to solid ice."); @@ -5193,37 +5532,39 @@ void showlfstats(lifeform_t *lf, int showall) { mvwprintw(mainwin, y, 0, buf); y++; } - f = lfhasflag(lf, F_FROZEN); - if (f && (f->known)) { - mvwprintw(mainwin, y, 0, "%s %s been turned to ice, and %s slowly melting.", you(lf), isplayer(lf) ? "have" : "has", - isplayer(lf) ? "are" : "is"); - y++; - } f = lfhasflag(lf, F_GRAVBOOSTED); if (f && (f->known)) { mvwprintw(mainwin, y, 0, "Gravity is increased around %s.", you_l(lf)); y++; } + f = lfhasknownflag(lf, F_DODGES); + if (f && (f->known)) { + mvwprintw(mainwin, y, 0, "%s can dodge attacks.", you(lf)); + y++; + } f = lfhasknownflag(lf, F_INVULNERABLE); if (f && (f->known)) { mvwprintw(mainwin, y, 0, "%s are protected from all physical harm.", you(lf)); y++; } - f = lfhasknownflag(lf, F_LEVITATING); - if (f && (f->known)) { - mvwprintw(mainwin, y, 0, "%s %s levitating.", you(lf), isplayer(lf) ? "are" : "is"); - y++; - } f = lfhasflag(lf, F_MAGSHIELD); if (f && (f->known)) { mvwprintw(mainwin, y, 0, "%s %s surrounded by a magnetic shield.", you(lf), isplayer(lf) ? "are" : "is"); y++; } - f = lfhasflag(lf, F_NONCORPOREAL); + + f = lfhasflag(lf, F_PAIN); if (f && (f->known)) { - mvwprintw(mainwin, y, 0, "%s %s noncorporeal and can walk through walls.", you(lf), isplayer(lf) ? "are" : "is"); + mvwprintw(mainwin, y, 0, "%s %s in extreme pain, and movement will cause %s damage.", you(lf), isplayer(lf) ? "are" : "is", isplayer(lf) ? "you" : "it"); y++; } + + + + + + + f = lfhasflag(lf, F_PARALYZED); if (f && (f->known)) { mvwprintw(mainwin, y, 0, "%s %s paralyzed.", you(lf), isplayer(lf) ? "are" : "is"); @@ -5234,11 +5575,6 @@ void showlfstats(lifeform_t *lf, int showall) { mvwprintw(mainwin, y, 0, "%s do not forget your surroundings.", you(lf)); y++; } - f = lfhasflag(lf, F_PRODUCESLIGHT); - if (f && (f->known)) { - mvwprintw(mainwin, y, 0, "%s produce%s light.", you(lf), isplayer(lf) ? "" : "s"); - y++; - } f = lfhasknownflag(lf, F_REGENERATES); if (f) { char regenspeed[BUFLEN]; @@ -5259,11 +5595,6 @@ void showlfstats(lifeform_t *lf, int showall) { mvwprintw(mainwin, y, 0, "Magic does not affect %s.", you(lf)); y++; } - f = lfhasknownflag(lf, F_SPRINTING); - if (f) { - mvwprintw(mainwin, y, 0, "%s %s sprinting.", you(lf), isplayer(lf) ? "are" : "is"); - y++; - } f = lfhasknownflag(lf, F_TIRED); if (f) { mvwprintw(mainwin, y, 0, "%s %s tired.", you(lf), isplayer(lf) ? "are" : "is"); @@ -5271,22 +5602,60 @@ void showlfstats(lifeform_t *lf, int showall) { } - f = lfhasknownflag(lf, F_SEEINDARK); - if (f) { - mvwprintw(mainwin, y, 0, "%s can see in the dark.", you(lf)); + f = lfhasflag(lf, F_STABILITY); + if (f && (f->known)) { + mvwprintw(mainwin, y, 0, "%s will not fall on slippery ground.", you(lf)); y++; } - f = lfhasknownflag(lf, F_XRAYVIS); - if (f && !lfhasflag(lf, F_BLIND)) { - mvwprintw(mainwin, y, 0, "%s can see through walls.", you(lf)); + f = lfhasflag(lf, F_STENCH); + if (f && (f->known)) { + mvwprintw(mainwin, y, 0, "%s smell%s terrible.", you(lf), isplayer(lf) ? "" : "s"); y++; } - + if (!isblind(lf)) { + f = lfhasknownflag(lf, F_SEEINDARK); + if (f) { + mvwprintw(mainwin, y, 0, "%s can see in the dark.", you(lf)); + y++; + } + + f = lfhasknownflag(lf, F_XRAYVIS); + if (f) { + mvwprintw(mainwin, y, 0, "%s can see through walls.", you(lf)); + y++; + } + } // wait for key - h = getmaxy(mainwin); + centre(mainwin, h-1, "[Press any key]"); + getch(); + } + + if (!isplayer(lf) && showall) { + object_t *o; + cls(); + centre(mainwin, 0, "INVENTORY"); + y = 2; + mvwprintw(mainwin, y, 0, "It is carrying:"); + y += 2; + for (o = lf->pack->first ; o ; o = o->next) { + getobname(o, buf,o->amt); + getobextrainfo(o, buf2); + + mvwprintw(mainwin, y, 0, "%s%s", buf,buf2); + y++; + if (y >= (h-3) && (o->next)) { + // wait for key + centre(mainwin, h-1, "-- More --"); + getch(); + cls(); + centre(mainwin, 0, "INVENTORY"); + y = 2; + } + } + // wait for key centre(mainwin, h-1, "[Press any key]"); getch(); } @@ -5313,7 +5682,11 @@ void tombstone(lifeform_t *lf) { p = strtok_r(lf->lastdam,"^", &dummy); if (p) { - centre(mainwin, y, "Killed by %s.",p); y++; + if (!strcmp(p, "you")) { + centre(mainwin, y, "Committed suicide.",p); y++; + } else { + centre(mainwin, y, "Killed by %s.",p); y++; + } p = strtok_r(NULL, "^", &dummy); while (p) { centre(mainwin, y, "(%s)",p); y++; @@ -5342,3 +5715,5 @@ void tombstone(lifeform_t *lf) { } + + diff --git a/io.h b/io.h index 92da156..535e7ea 100644 --- a/io.h +++ b/io.h @@ -6,9 +6,10 @@ void addmsghist(char *text); void addpromptq(prompt_t *p, char *q); void anim(cell_t *src, cell_t *dst, char ch); void animradial(cell_t *src, int radius, char ch); +void animradialorth(cell_t *src, int radius, char ch); //void announceob(enum OBTYPE oid); int announceflaggain(lifeform_t *lf, flag_t *f); -void announceflagloss(lifeform_t *lf, flag_t *f); +int announceflagloss(lifeform_t *lf, flag_t *f); int announceobflaggain(object_t *o, flag_t *f); void announceobflagloss(object_t *o, flag_t *f); object_t *askobject(obpile_t *op, char *title, int *count, int opts); @@ -36,6 +37,7 @@ void doenter(lifeform_t *lf); void doexplain(void); void dofinaloblist(obpile_t *op); void dofire(void); +void dohelp(void); void doinventory(obpile_t *op); void doknowledgelist(void); void dolook(cell_t *where); @@ -57,6 +59,7 @@ void dothrow(obpile_t *op); void dovendingmachine(lifeform_t *lf, object_t *vm); int dowear(obpile_t *op); int doweild(obpile_t *op); +void downline(int *y, int h, char *heading, char *subheading); void drawunviscell(cell_t *cell, int x, int y); void drawcellwithcontents(cell_t *cell, int x, int y); void drawcursor(void); @@ -69,13 +72,14 @@ char getchoice(prompt_t *prompt); char getchoicestr(prompt_t *prompt); int getkey(void); void handleinput(void); +void doheading(WINDOW *win, int *y, int x, char *what); void initgfx(void); void initprompt(prompt_t *p, char *q1); int keycodetokey(int keycode); void more(void); void warn(char *format, ... ); void msg(char *format, ... ); -void msglower(char *format, ... ); +void msgnocap(char *format, ... ); void msg_real(char *format, ... ); void nothinghappens(void); void dblog(char *format, ... ); diff --git a/lf.c b/lf.c index 5850f53..28ed67f 100644 --- a/lf.c +++ b/lf.c @@ -22,6 +22,7 @@ extern job_t *firstjob, *lastjob; extern objecttype_t *objecttype; extern lifeform_t *player; +extern int needredraw; extern prompt_t prompt; @@ -30,6 +31,7 @@ extern long nextlfid; extern WINDOW *msgwin; extern WINDOW *statwin; extern int statdirty; +extern int needredraw; extern int gamestarted; @@ -163,6 +165,8 @@ lifeform_t *real_addlf(cell_t *cell, enum RACE rid, int level, int controller) { race_t *addrace(enum RACE id, char *name, float weight, char glyph, enum MATERIAL mat) { race_t *a; + assert(!findrace(id)); + // add to the end of the list if (firstrace == NULL) { firstrace = malloc(sizeof(race_t)); @@ -178,8 +182,10 @@ race_t *addrace(enum RACE id, char *name, float weight, char glyph, enum MATERIA lastrace = a; a->next = NULL; + // props a->id = id; + a->baseid = id; // default a->material = findmaterial(mat); assert(a->material); @@ -232,6 +238,87 @@ void adjustdamlf(lifeform_t *lf, int *amt, enum DAMTYPE damtype) { if (*amt < 0) *amt = 0; } +lifeform_t *makezombie(object_t *o) { + flag_t *f; + race_t *r; + lifeform_t *lf; + cell_t *where; + char obname[BUFLEN]; + + if (o->type->id != OT_CORPSE) return NULL; + + f = hasflag(o->flags, F_CORPSEOF); + if (!f) return NULL; + + r = findrace(f->val[0]); + if (!r) return NULL; + + where = getoblocation(o); + getobname(o, obname, 1); + + lf = addlf(where, r->id, 1); + + addflag(lf->flags, F_LFSUFFIX, B_TRUE, NA, NA, "zombie"); + addflag(lf->flags, F_GLYPH, NA, NA, NA, "Z"); + addflag(lf->flags, F_UNDEAD, B_TRUE, NA, NA, NULL); + addflag(lf->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL); + 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); + addflag(lf->flags, F_DTVULN, DT_HOLY, NA, NA, NULL); + + if (hasflag(o->flags, F_HEADLESS)) { + // remove the head + addflag(lf->flags, F_NOBODYPART, BP_HEAD, NA, NA, NULL); + // remove the eyes (this will make the creature blind) + addflag(lf->flags, F_NOBODYPART, BP_EYES, NA, NA, NULL); + // need HEADLESS too to show that this monster normally + // _does_ have a head. this will cause getlfname + // to add "headless " to the description. + addflag(lf->flags, F_HEADLESS, B_TRUE, NA, NA, NULL); + } + + killflagsofid(lf->flags, F_WANTSBETTERWEP); + killflagsofid(lf->flags, F_WANTSBETTERARM); + killflagsofid(lf->flags, F_WANTSOBFLAG); + killflagsofid(lf->flags, F_WANTS); + killflagsofid(lf->flags, F_NOISETEXT); + killflagsofid(lf->flags, F_SEEINDARK); + + killflagsofid(lf->flags, F_MOVESPEED); + addflag(lf->flags, F_MOVESPEED, SP_SLOW, NA, NA, NULL); + killflagsofid(lf->flags, F_ACTIONSPEED); + addflag(lf->flags, F_ACTIONSPEED, SP_SLOW, NA, NA, NULL); + lf->baseatt[A_IQ] = rolliq(IQ_MINDLESS); + lf->att[A_IQ] = lf->baseatt[A_IQ]; + + // no magic + lf->maxmp = 0; + lf->mp = 0; + + // no objects + while (lf->pack->first) { + killob(lf->pack->first); + } + + // no abilities + killflagsofid(lf->flags, F_CANCAST); + killflagsofid(lf->flags, F_CANWILL); + + // remove the object + removeob(o,o->amt); + + // redraw & announce + if (haslos(player, where)) { + needredraw = B_TRUE; + drawscreen(); + msg("%s rises from the dead!", obname); + } + + return lf; +} + + void autotarget(lifeform_t *lf) { object_t *gun; lifeform_t *targ,*newtarg; @@ -279,11 +366,19 @@ void autotarget(lifeform_t *lf) { cell_t *c; c = lf->los[i]; if (c->lf && (c->lf != lf) && isingunrange(lf, c)) { - int thisdist; - thisdist = getcelldist(lf->cell, c); - if (thisdist < closest) { - newtarg = c->lf; - closest = thisdist; + int valid = B_TRUE; + if (isplayer(lf)) { + if (isfriendly(c->lf) || ispeaceful(c->lf)) { + valid = B_FALSE; + } + } + if (valid) { + int thisdist; + thisdist = getcelldist(lf->cell, c); + if (thisdist < closest) { + newtarg = c->lf; + closest = thisdist; + } } } } @@ -324,14 +419,14 @@ void autoweild(lifeform_t *lf) { // start using ammo if required - if (isplayer(lf)) { - if (getfirearm(lf)) { - for (o = lf->pack->first ; o ; o = o->next) { - testammo(lf, o); - if (getammo(lf)) break; - } + //if (isplayer(lf)) { + if (getfirearm(lf)) { + for (o = lf->pack->first ; o ; o = o->next) { + testammo(lf, o); + if (getammo(lf)) break; } } + //} // make sure it doesn't take any time lf->timespent = pretimespent; @@ -362,7 +457,7 @@ void bleed(lifeform_t *lf) { strcpy(obname, ""); } } else { - strcpy(obname, "blood stain"); + strcpy(obname, "splash of blood"); } if (strlen(obname) > 0) { @@ -416,7 +511,7 @@ int calcxp(lifeform_t *lf) { // -- modify with accuracy acc = getlfaccuracy(lf); - offense = avgdam * (acc/100); + offense = pctof(acc,avgdam); if (db) dblog("calcxp: ATTACKVAL IS %0.1f",offense); @@ -470,16 +565,23 @@ int calcxprace(enum RACE rid) { int cancast(lifeform_t *lf, enum OBTYPE oid, int *mpcost) { int castable = B_FALSE; + flag_t *f; // TODO: check for mute? reason = E_OK; - if (lfhasflagval(lf, F_CANWILL, oid, NA, NA, NULL)) { + f = lfhasflagval(lf, F_CANWILL, oid, NA, NA, NULL); + if (f) { // no mp cost. if (mpcost) *mpcost = 0; - return B_TRUE; - } - if (lfhasflagval(lf, F_CANCAST, oid, NA, NA, NULL)) { + // ability ready? + if (f->val[1] == f->val[2]) { + castable = B_TRUE; + } else { + reason = E_NOTREADY; + return B_FALSE; + } + } else if (lfhasflagval(lf, F_CANCAST, oid, NA, NA, NULL)) { int cost; // how much mp does it take to cast this? cost = getmpcost(oid); @@ -512,8 +614,9 @@ int canhear(lifeform_t *lf, cell_t *c) { return B_FALSE; } +// int cannotmove(lifeform_t *lf) { - if (lfhasflag(lf, F_PARALYZED) || lfhasflag(lf, F_FROZEN)) { + if (lfhasflag(lf, F_PARALYZED) || lfhasflag(lf, F_FROZEN) || lfhasflag(lf, F_ASLEEP)) { return B_TRUE; } return B_FALSE; @@ -522,7 +625,6 @@ int cannotmove(lifeform_t *lf) { int canpickup(lifeform_t *lf, object_t *o, int amt) { reason = E_OK; - if (amt == ALL) { amt = o->amt; } @@ -531,6 +633,10 @@ int canpickup(lifeform_t *lf, object_t *o, int amt) { reason = E_NOPICKUP; return B_FALSE; } + if (isimpassableob(o, lf)) { + reason = E_TOOBIG; + return B_FALSE; + } if (lfhasflag(lf, F_NOPACK)) { reason = E_NOPACK; return B_FALSE; @@ -541,7 +647,8 @@ int canpickup(lifeform_t *lf, object_t *o, int amt) { } // too heavy to lift? - if (getobunitweight(o) > getmaxliftweight(lf)) { + //max = getlfweight(lf, B_NOOBS) * 2; // twice your body weight + if (getobunitweight(o) + getobpileweight(lf->pack) > (getmaxcarryweight(lf)*2)) { reason = E_TOOHEAVY; return B_FALSE; } @@ -745,7 +852,7 @@ int cantakeoff(lifeform_t *lf, object_t *o) { int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *targob, cell_t *targcell) { int rv; int cost; - flag_t *f; + flag_t *f,*willflag; // check whether we _can_ cast it. // do we have this spell/ability? // enough mp? etc @@ -764,6 +871,8 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar return B_TRUE; } + willflag = lfhasflagval(lf, F_CANWILL, sid, NA, NA, NULL); + // take time taketime(lf, getspellspeed(lf)); @@ -796,6 +905,13 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar if (f) { killflag(f); } + + // willing this spell? reset counter! + if (willflag) { + if (willflag->val[2] != NA) { + willflag->val[1] = -1; + } + } return rv; } @@ -858,7 +974,7 @@ void die(lifeform_t *lf) { if (hasflag(lf->flags, F_KILLEDBYPLAYER)) { int xpval; xpval = calcxp(lf); - assert(xpval > 0); + //assert(xpval > 0); gainxp(player, xpval); } } @@ -892,7 +1008,7 @@ void die(lifeform_t *lf) { fragments(lf->cell, "chunk of ice", 2); } else { if (lfhasflag(lf, F_NOCORPSE)) { - if (haslos(player, lf->cell)) { + if (lfhasflag(lf, F_UNDEAD) && haslos(player, lf->cell)) { getlfname(lf, buf); msg("%s crumbles to dust.", buf); } @@ -1029,7 +1145,7 @@ void dumpxp(void) { } int eat(lifeform_t *lf, object_t *o) { - char buf[BUFLEN]; + char lfname[BUFLEN]; char obname[BUFLEN]; flag_t *f; int nutrition; @@ -1045,6 +1161,7 @@ int eat(lifeform_t *lf, object_t *o) { } getobname(o, obname, 1); + getlfname(lf, lfname); nutrition = getnutrition(o); @@ -1056,6 +1173,7 @@ int eat(lifeform_t *lf, object_t *o) { return B_TRUE; } + // only do this check for the player - basically it should // handle the case where we have poluymorphed into something // which doesn't eat. @@ -1078,9 +1196,7 @@ int eat(lifeform_t *lf, object_t *o) { msg("You eat %s.%s", obname, (f->val[1] >= 20) ? " Yum!" : ""); } else if (haslos(player, lf->cell)) { - getlfname(lf, buf); - capitalise(buf); - msg("%s eats %s.", buf, obname); + msg("%s eats %s.", lfname, obname); } if (isrotting(o)) { @@ -1100,10 +1216,31 @@ int eat(lifeform_t *lf, object_t *o) { addtempflag(lf->flags, F_PRODUCESLIGHT, B_TRUE, NA, NA, NULL, 30); } + // special case for bananas + if (o->type->id == OT_BANANA) { + object_t *skin; + skin = addob(lf->pack, "banana skin"); + if (skin) { + if (isplayer(lf)) { + char skinname[BUFLEN]; + getobname(skin, skinname, 1); + msgnocap("%c - %s", skin->letter, skinname); + } + } else { + skin = addob(lf->cell->obpile, "banana skin"); + if (skin && haslos(player, lf->cell)) { + char skinname[BUFLEN]; + getobname(skin, skinname, 1); + msg("%s drop%s %s on the ground.",lfname, isplayer(lf) ? "" : "s", + skinname); + } + } + } // remove object removeob(o, 1); + // how long will it take? // ie. picking up off ground if (o->pile->owner != lf) { @@ -1131,6 +1268,8 @@ int eat(lifeform_t *lf, object_t *o) { mod = 0.25; break; case SZ_ENORMOUS: mod = 0.125; break; + default: + mod = 1; break; } amt += ((double)getactspeed(lf) * mod); @@ -1163,9 +1302,11 @@ object_t *eyesshaded(lifeform_t *lf) { void fightback(lifeform_t *lf, lifeform_t *attacker) { // respond to damage if (attacker && !isdead(lf)) { - if (lf->controller != C_PLAYER) { - if (hasflag(lf->flags, F_FLEEONDAM)) { - // they will flee + // wake up + killflagsofid(lf->flags, F_ASLEEP); + // monsters might flee, fight back, etc + if (!isplayer(lf)) { + if (willflee(lf)) { scare(lf, attacker, PERMENANT); } else { // they will now fight back! @@ -1282,6 +1423,14 @@ int flee(lifeform_t *lf) { if (fleefrom) { // TODO: if we are AI, try to use specific spells like teleport self + + // if AI, use helpful fleeing items + if (!isplayer(lf)) { + if (!useitemwithflag(lf, F_AIFLEEITEM)) { + return B_FALSE; + } + } + // move away from them if (!moveawayfrom(lf, fleefrom->cell)) { // announce @@ -1360,7 +1509,7 @@ void gainlevel(lifeform_t *lf) { } lf->level++; - if (lf->controller == C_PLAYER) { + if (isplayer(lf)) { msg("Welcome to level %d!",lf->level); more(); } else if (haslos(player, lf->cell)) { @@ -1380,6 +1529,24 @@ void gainlevel(lifeform_t *lf) { lf->mp = mpratio * (float)lf->maxmp; } + // stat gain + if ((lf->level % 3) == 0) { + enum ATTRIB att; + if (isplayer(lf)) { + char ch; + ch = askchar("Increase your Strength, Dexterity or Intelligence?", "sdi",NULL, B_TRUE); + switch (ch) { + case 's': att = A_STR; break; + case 'd': att = A_DEX; break; + case 'i': att = A_IQ; break; + } + } else { + // pick randomly + att = rnd(0,MAXATTS-1); + } + modattr(lf, att, 1); + } + // TODO: hand out effects based on job } @@ -1482,11 +1649,38 @@ int getarmourrating(lifeform_t *lf) { ar += f->val[0]; } + f = hasflag(lf->flags, F_PHALANX); + if (f) { + int dir; + cell_t *c; + int nmatched = 0; + // count adjacent allies of name xx + for (dir = DC_N; dir <= DC_NW; dir++) { + c = getcellindir(lf->cell, dir); + if (c && c->lf) { + if (strcasestr(c->lf->race->name, f->text)) { + nmatched++; + } + } + } + if (nmatched >= f->val[2]) { + ar += f->val[0]; + } + } + for (o = lf->pack->first ; o ; o = o->next) { if (hasflag(o->flags, F_EQUIPPED)) { f = hasflag(o->flags, F_ARMOURRATING); if (f) { - ar += f->val[0]; + int thisar; + float pct; + + pct = getobhppct(o); + thisar = pctof(pct, f->val[0]); + + ar += thisar; + + ar += getobbonus(o); } } } @@ -1540,7 +1734,7 @@ int getevasion(lifeform_t *lf) { int ev = 0; // no evasion if you can't move! - if (cannotmove(lf)) { + if (isimmobile(lf)) { return 0; } @@ -1568,9 +1762,15 @@ int getevasion(lifeform_t *lf) { ev += (getstatmod(lf, A_DEX) / 2); if (ev < 0) ev = 0; + // you are easier to hit if you're glowing + if (hasflag(lf->flags, F_PRODUCESLIGHT)) { + ev -= 5; + if (ev < 0) ev = 0; + } + // modify for blindness if (isblind(lf)) { - ev -= 10; + ev -= 15; } if (ev < 0) ev = 0; @@ -1791,6 +1991,12 @@ int gethearingrange(lifeform_t *lf) { return range; } +int gethppct(lifeform_t *lf) { + float pct; + pct = (int)(((float)lf->hp / (float)lf->maxhp) * 100); + return pct; +} + enum HUNGER gethungerlevel(int hunger) { int thresh = HUNGERCONST; if (hunger < -thresh) { @@ -1895,6 +2101,11 @@ int getlfaccuracy(lifeform_t *lf) { acc -= 50; } + // modify for nausea + if (lfhasflag(lf, F_NAUSEATED)) { + acc -= 20; + } + if (acc < 0) acc = 0; return acc; } @@ -1974,6 +2185,20 @@ char *getseenlfconditionname(lifeform_t *lf, lifeform_t *viewer) { return getlfconditionname(cond); } +char getlfglyph(lifeform_t *lf) { + flag_t *f; + if (isplayer(lf) && !ispolymorphed(lf)) { + return '@'; + } + + f = lfhasflag(lf, F_GLYPH); + if (f) { + return f->text[0]; + } + + return lf->race->glyph; +} + enum MATERIAL getlfmaterial(lifeform_t *lf) { if (lf->race->id == R_DANCINGWEAPON) { object_t *wep; @@ -2016,6 +2241,7 @@ float getmaxcarryweight(lifeform_t *lf) { return max; } +/* float getmaxliftweight(lifeform_t *lf) { float max; float mod; @@ -2045,6 +2271,7 @@ float getmaxliftweight(lifeform_t *lf) { return max; } +*/ float getmaxpushweight(lifeform_t *lf) { float max; @@ -2143,12 +2370,16 @@ char *getlfname(lifeform_t *lf, char *buf) { char descstring[BUFLEN]; char jobstring[BUFLEN]; job_t *j; + flag_t *f; // construct description string strcpy(descstring, ""); if (lfhasflag(lf, F_FROZEN)) { strcat(descstring, "frozen "); } + if (lfhasflag(lf, F_HEADLESS)) { + strcat(descstring, "headless "); + } // construct job string strcpy(jobstring, ""); @@ -2169,13 +2400,21 @@ char *getlfname(lifeform_t *lf, char *buf) { wep = getweapon(lf); if (wep) { char obname[BUFLEN]; - real_getobname(wep, obname, 1, B_FALSE, B_FALSE, B_FALSE); + real_getobname(wep, obname, 1, B_TRUE, B_FALSE, B_FALSE, B_FALSE); sprintf(buf, "the %s%s",descstring,noprefix(obname)); } else { sprintf(buf, "the %s%s%s",descstring,lf->race->name,jobstring); } } else { - sprintf(buf, "the %s%s%s",descstring,lf->race->name,jobstring); + char zombiestring[BUFLEN]; + f = hasflag(lf->flags, F_LFSUFFIX); + + strcpy(zombiestring, ""); + if (f) { + sprintf(zombiestring, " %s", f->text); + } + + sprintf(buf, "the %s%s%s%s",descstring,lf->race->name,jobstring,zombiestring); } } } @@ -2186,9 +2425,11 @@ char *getlfnamea(lifeform_t *lf, char *buf) { if (lf == player) { sprintf(buf, "you"); } else { + char buf2[BUFLEN]; + getlfname(lf, buf2); sprintf(buf, "%s %s", isvowel(lf->race->name[0]) ? "an" : "a", - lf->race->name); + noprefix(buf2)); } return buf; } @@ -2617,7 +2858,8 @@ long getxpforlev(int level) { needxp += (20 * (pow(i,2.8))); } */ - needxp = (20 * (pow(level,2.8) - 1)); + //needxp = (20 * (pow(level,2.8) - 1)); + needxp = (10 * (pow(level,2.8) - 1)); return needxp; } @@ -2625,9 +2867,14 @@ void givejob(lifeform_t *lf, enum JOB jobid) { job_t *j; flag_t *f; int i; + int condition = NOCONDITION; int rollhp = B_FALSE, rollmp = B_FALSE; int rollatt[MAXATTS]; int ignorenext; + int ignoredprev; + int db = B_TRUE; + + if (db) dblog("givejob() starting.\n"); for (i = 0; i < MAXATTS; i++) { rollatt[i] = B_FALSE; @@ -2654,27 +2901,68 @@ void givejob(lifeform_t *lf, enum JOB jobid) { } } - // give start obs from it - givestartobs(lf, j->flags); - - - // now inherit all flags except startob ones + // inherit all flags except startob ones ignorenext = B_FALSE; + ignoredprev = B_FALSE; for (f = j->flags->first ; f ; f = f->next) { + if (condition == IFPLAYER) { + if (f->id == F_ENDIFPLAYER) { + if (db) dblog("ending ifplayer condition"); + condition = NOCONDITION; + } else if (!isplayer(lf)) { + if (db) dblog("setting ignorenext cause of ifplayer"); + ignorenext = B_TRUE; // ie. ignore this one. + } + } else if (condition == IFMONSTER) { + if (f->id == F_ENDIFMONSTER) { + if (db) dblog("ending ifmonster condition"); + condition = NOCONDITION; + } else if (isplayer(lf)) { + if (db) dblog("setting ignorenext cause of ifmonster"); + ignorenext = B_TRUE; // ie. ignore this one. + } + } + if (ignorenext) { + if (db) dblog("ignoring this flag: %d",f->id); ignorenext = B_FALSE; + ignoredprev = B_TRUE; } else { if (f->id == F_IFPCT) { + if (db) dblog("ifpct flag..."); if (rnd(0,100) > f->val[0]) { + if (db) dblog(" failed."); ignorenext = B_TRUE; + } else { + if (db) dblog(" passed."); } + /* if ((f->val[2] == IFMONSTER) && isplayer(lf)) { ignorenext = B_TRUE; } else if ((f->val[2] == IFPLAYER) && !isplayer(lf)) { ignorenext = B_TRUE; } + */ + } else if (f->id == F_IFPLAYER) { + if (db) dblog("starting ifplayer condition"); + condition = IFPLAYER; + } else if (f->id == F_IFMONSTER) { + if (db) dblog("starting ifmonster condition"); + condition = IFMONSTER; + } else if (f->id == F_ELSE) { + if (db) dblog("else flag..."); + if (ignoredprev) { + if (db) dblog("... MATCHED."); + } else { + if (db) dblog("... ignoring next."); + ignorenext = B_TRUE; + } + // } else { + if (db) dblog("processing normal flag: %d",f->id); + /* switch (f->id) { + case F_STARTOB: case F_STARTOBDT: case F_STARTOBCLASS: @@ -2686,10 +2974,22 @@ void givejob(lifeform_t *lf, enum JOB jobid) { if (f->id == F_STARTIQ) rollatt[A_IQ] = B_TRUE; break; } + */ + addflag_real(lf->flags, f->id, f->val[0], f->val[1], f->val[2], f->text, FROMJOB,B_TRUE, -1); + if (f->id == F_STARTSTR) rollatt[A_STR] = B_TRUE; + if (f->id == F_STARTDEX) rollatt[A_DEX] = B_TRUE; + if (f->id == F_STARTIQ) rollatt[A_IQ] = B_TRUE; } + ignoredprev = B_FALSE; } } + + // now give start obs from it + givestartobs(lf, lf->flags); + + + // override hp/mp from race if (rollhp) { lf->maxhp = 0; @@ -2834,6 +3134,7 @@ void givestartobs(lifeform_t *lf, flagpile_t *fp) { } if (f->id == F_STARTOB) { + assert(strlen(f->text) > 0); if (rnd(1,100) <= f->val[0]) { o = addob(lf->pack, f->text); } @@ -2857,6 +3158,11 @@ void givestartobs(lifeform_t *lf, flagpile_t *fp) { } } } + + // now remove startob flags so we don't get them again! + killflagsofid(fp, F_STARTOB); + killflagsofid(fp, F_STARTOBDT); + killflagsofid(fp, F_STARTOBCLASS); } job_t *hasjob(lifeform_t *lf, enum JOB job) { @@ -3093,14 +3399,7 @@ int lockpick(lifeform_t *lf, object_t *target, object_t *device) { } removeob(device, 1); } else if (faileffect == B_BLUNTONFAIL) { - char devname[BUFLEN]; - getobname(device,devname, 1); - if (isplayer(lf)) { - msg("Your %s seems duller!",noprefix(devname)); - } else if (haslos(player, lf->cell)) { - msg("%s%s %s seems duller!",lfname, getpossessive(lfname), noprefix(devname)); - } - modbonus(device, -1); + makeduller(device, 1); } else { if (isplayer(lf) || haslos(player, lf->cell)) { msg("%s fail%s to unlock %s.",lfname, isplayer(lf) ? "" : "s", obname); @@ -3238,8 +3537,7 @@ int haslof(lifeform_t *viewer, cell_t *dest) { object_t *blockob; /* - // we _DO_ need to move out of last one for line of fire. - // don't need to move out of the last one + // we _DO_ need to move out of last cell for line of fire. if ((x == x2) && (y == y2)) { break; } @@ -3261,6 +3559,17 @@ int haslof(lifeform_t *viewer, cell_t *dest) { reason = E_NOLOF; return B_FALSE; } + // lifeforms block lof unless they're in our destination + if (cell->lf) { + // if not in first cell... + if ((x != x1) || (y != y1)) { + // if not in last cell... + if ((x != x2) || (y != y2)) { + reason = E_NOLOF; + return B_FALSE; + } + } + } // certain objects block lof blockob = hasobwithflag(cell->obpile, F_BLOCKSTHROW); if (blockob) { @@ -3538,7 +3847,7 @@ void initjobs(void) { addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "10 blessed scrolls of create monster"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "ring of invulnerability"); // gods may use all abilities and cast any spell at will - for (i = SS_ABILITY; i < SS_LAST; i++) { + for (i = SS_NONE+1; i < SS_LAST; i++) { if (i == SS_ABILITY) { mayusespellschool(lastjob->flags, i, F_CANWILL); } else { @@ -3555,7 +3864,7 @@ void initjobs(void) { addflag(lastjob->flags, F_STARTSTR, ST_AVERAGE, NA, NA, NULL); addflag(lastjob->flags, F_STARTDEX, ST_AVERAGE, NA, NA, NULL); addflag(lastjob->flags, F_STARTIQ, IQ_AVERAGE, NA, NA, NULL); - addflag(lastjob->flags, F_CANWILL, OT_A_SPRINT, NA, NA, NULL); + addflag(lastjob->flags, F_CANWILL, OT_A_SPRINT, 3, 3, NULL); addjob(J_ALLOMANCER, "Allomancer"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "1 gold coins"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "club"); @@ -3578,7 +3887,7 @@ void initjobs(void) { addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "rubber boots"); addflag(lastjob->flags, F_EVASION, 30, NA, NA, NULL); addflag(lastjob->flags, F_OBESE, B_TRUE, NA, NA, NULL); - addflag(lastjob->flags, F_CANWILL, OT_A_JUMP, NA, NA, NULL); + addflag(lastjob->flags, F_CANWILL, OT_A_JUMP, 3, 3, NULL); addjob(J_PRINCE, "Prince"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "blessed ornamental sword"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "100 gold coins"); @@ -3607,10 +3916,18 @@ void initjobs(void) { addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "knife"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "robe"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "2 potions of magic"); - addflag(lastjob->flags, F_IFPCT, 100, NA, IFPLAYER, NULL); // players start with a fixed spellbook - addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "spellbook of flame dart"); - addflag(lastjob->flags, F_IFPCT, 50, NA, IFMONSTER, NULL); // monsters sometimes start with a random book - addflag(lastjob->flags, F_STARTOBCLASS, 100, OC_BOOK, NA, NULL); + + addflag(lastjob->flags, F_IFPLAYER, NA, NA, NA, NULL); + addflag(lastjob->flags, F_IFPCT, 50, NA, NA, NULL); + addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "spellbook of flame dart"); + addflag(lastjob->flags, F_ELSE, NA, NA, NA, NULL); + addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "spellbook of cone of cold"); + addflag(lastjob->flags, F_ENDIFPLAYER, NA, NA, NA, NULL); + + addflag(lastjob->flags, F_IFMONSTER, NA, NA, NA, NULL); + addflag(lastjob->flags, F_IFPCT, 50, NA, NA, NULL); // monsters sometimes start with a random book + addflag(lastjob->flags, F_STARTOBCLASS, 100, OC_BOOK, NA, NULL); + addflag(lastjob->flags, F_ENDIFMONSTER, NA, NA, NA, NULL); addflag(lastjob->flags, F_HITDICE, 1, 1, NA, NULL); // low hp addflag(lastjob->flags, F_MPDICE, 2, 1, NA, NULL); addflag(lastjob->flags, F_STARTSTR, ST_WEAK, NA, NA, NULL); @@ -3622,33 +3939,35 @@ void initjobs(void) { // can detect magic objects addflag(lastjob->flags, F_DETECTMAGIC, B_TRUE, NA, NA, NULL); // for monster wizards only: - addflag(lastjob->flags, F_IFPCT, 50, NA, IFMONSTER, NULL); - addflag(lastjob->flags, F_CANCAST, OT_S_FIREDART, NA, NA, NULL); - addflag(lastjob->flags, F_IFPCT, 50, NA, IFMONSTER, NULL); - addflag(lastjob->flags, F_CANCAST, OT_S_CONECOLD, NA, NA, NULL); - addflag(lastjob->flags, F_IFPCT, 33, NA, IFMONSTER, NULL); - addflag(lastjob->flags, F_CANCAST, OT_S_HEALINGMIN, NA, NA, NULL); - addflag(lastjob->flags, F_IFPCT, 33, NA, IFMONSTER, NULL); - addflag(lastjob->flags, F_CANCAST, OT_S_BLINK, NA, NA, NULL); - addflag(lastjob->flags, F_IFPCT, 33, NA, IFMONSTER, NULL); - addflag(lastjob->flags, F_CANCAST, OT_S_TELEKINESIS, NA, NA, NULL); - addflag(lastjob->flags, F_IFPCT, 20, NA, IFMONSTER, NULL); - addflag(lastjob->flags, F_CANCAST, OT_S_HASTE, NA, NA, NULL); - addflag(lastjob->flags, F_IFPCT, 20, NA, IFMONSTER, NULL); - addflag(lastjob->flags, F_CANCAST, OT_S_HEALING, NA, NA, NULL); + addflag(lastjob->flags, F_IFMONSTER, NA, NA, NA, NULL); + addflag(lastjob->flags, F_IFPCT, 50, NA, NA, NULL); + addflag(lastjob->flags, F_CANCAST, OT_S_FIREDART, NA, NA, NULL); + addflag(lastjob->flags, F_IFPCT, 50, NA, NA, NULL); + addflag(lastjob->flags, F_CANCAST, OT_S_CONECOLD, NA, NA, NULL); + addflag(lastjob->flags, F_IFPCT, 33, NA, NA, NULL); + addflag(lastjob->flags, F_CANCAST, OT_S_HEALINGMIN, NA, NA, NULL); + addflag(lastjob->flags, F_IFPCT, 33, NA, NA, NULL); + addflag(lastjob->flags, F_CANCAST, OT_S_BLINK, NA, NA, NULL); + addflag(lastjob->flags, F_IFPCT, 33, NA, NA, NULL); + addflag(lastjob->flags, F_CANCAST, OT_S_TELEKINESIS, NA, NA, NULL); + addflag(lastjob->flags, F_IFPCT, 20, NA, NA, NULL); + addflag(lastjob->flags, F_CANCAST, OT_S_HASTE, NA, NA, NULL); + addflag(lastjob->flags, F_IFPCT, 20, NA, NA, NULL); + addflag(lastjob->flags, F_CANCAST, OT_S_HEALING, NA, NA, NULL); + addflag(lastjob->flags, F_ENDIFMONSTER, NA, NA, NA, NULL); } void initrace(void) { // races / monsters addrace(R_HUMAN, "human", 75, '@', MT_FLESH); - addflag(lastrace->flags, F_RARITY, H_DUNGEON, 25, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, 60, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); - addflag(lastrace->flags, F_HITDICE, 1, 4, NA, NULL); + addflag(lastrace->flags, F_HITDICE, 3, 4, NA, NULL); addflag(lastrace->flags, F_EVASION, 0, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_HASATTACK, NA, NA, NA, "fists"); - addflag(lastrace->flags, F_STARTOB, 80, 1, 50, "gold coin"); + addflag(lastrace->flags, F_STARTOB, 80, NA, NA, "1-50 gold coins"); addflag(lastrace->flags, F_STARTOBCLASS, 65, OC_WEAPON, NA, NULL); addflag(lastrace->flags, F_STARTOBCLASS, 65, OC_ARMOUR, NA, NULL); addflag(lastrace->flags, F_STARTOBCLASS, 65, OC_ARMOUR, NA, NULL); @@ -3666,19 +3985,19 @@ void initrace(void) { addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 65, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL); - addflag(lastrace->flags, F_HITDICE, 3, 3, NA, NULL); + addflag(lastrace->flags, F_HITDICE, 17, NA, NA, NULL); addflag(lastrace->flags, F_EVASION, 0, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_HASATTACK, 1, 10, NA, "claws"); addflag(lastrace->flags, F_STARTSTR, ST_STRONG, NA, NA, NULL); - addflag(lastrace->flags, F_STARTOBCLASS, 100, OC_WEAPON, NA, NULL); + addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "heavy flail"); addflag(lastrace->flags, F_STARTOBCLASS, 50, OC_ARMOUR, NA, NULL); addflag(lastrace->flags, F_STARTOBCLASS, 50, OC_ARMOUR, NA, NULL); addflag(lastrace->flags, F_WANTSBETTERWEP, B_TRUE, NA, NA, NULL); - addflag(lastrace->flags, F_WANTSOBFLAG, F_MISSILE, NA, NA, NULL); addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, NA, NA, "roars^a roars"); - addflag(lastrace->flags, F_SEEINDARK, UNLIMITED, NA, NA, NULL); + addflag(lastrace->flags, F_SEEINDARK, 3, NA, NA, NULL); + addflag(lastrace->flags, F_CANWILL, OT_A_HEAVYBLOW, 2, 2, NULL); addrace(R_EYEBAT, "eyebat", 5, 'e', MT_FLESH); addflag(lastrace->flags, F_STARTIQ, IQ_SMART, NA, NA, NULL); @@ -3705,48 +4024,191 @@ void initrace(void) { addflag(lastrace->flags, F_NOPACK, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SEEINDARK, UNLIMITED, NA, NA, NULL); - addrace(R_GIANT, "giant", 160, 'H', MT_FLESH); - addflag(lastrace->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); + addrace(R_GIANTHILL, "hill giant", 160, 'H', MT_FLESH); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, 55, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_HUGE, NA, NA, NULL); - addflag(lastrace->flags, F_HITDICE, 4, 4, NA, NULL); + addflag(lastrace->flags, F_HITDICE, 19, NA, NA, NULL); + addflag(lastrace->flags, F_ARMOURRATING, 12, NA, NA, NULL); addflag(lastrace->flags, F_EVASION, -20, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_SLOW, NA, NA, NULL); addflag(lastrace->flags, F_HASATTACK, 2, 5, NA, "fists"); - addflag(lastrace->flags, F_STARTOB, 90, 25, 100, "gold coin"); - addflag(lastrace->flags, F_STARTOBCLASS, 65, OC_WEAPON, NA, NULL); - addflag(lastrace->flags, F_STARTOBCLASS, 65, OC_ARMOUR, NA, NULL); + addflag(lastrace->flags, F_STARTOB, 90, NA, NA, "25-100 gold coins"); + addflag(lastrace->flags, F_STARTOB, 70, NA, NA, "1-2 boulders"); + addflag(lastrace->flags, F_IFPCT, 70, NA, NA, NULL); + addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "great club"); + addflag(lastrace->flags, F_ELSE, NA, NA, NA, NULL); + addflag(lastrace->flags, F_STARTOB, 70, NA, NA, "club"); addflag(lastrace->flags, F_STARTOBCLASS, 65, OC_ARMOUR, NA, NULL); addflag(lastrace->flags, F_STARTOBCLASS, 65, OC_ARMOUR, NA, NULL); addflag(lastrace->flags, F_STARTOBCLASS, 30, OC_POTION, NA, NULL); addflag(lastrace->flags, F_STARTOBCLASS, 30, OC_POTION, NA, NULL); - addflag(lastrace->flags, F_STARTOBCLASS, 30, OC_SCROLL, NA, NULL); - addflag(lastrace->flags, F_STARTOBCLASS, 30, OC_SCROLL, NA, NULL); addflag(lastrace->flags, F_STARTSTR, ST_MIGHTY, NA, NA, NULL); - addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, NA, NA, "shouts^a shout"); + addflag(lastrace->flags, F_STARTIQ, IQ_DOPEY, NA, NA, NULL); + addflag(lastrace->flags, F_STARTDEX, DX_CLUMSY, NA, NA, NULL); + addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, NA, NA, "bellows^a bellow"); + addflag(lastrace->flags, F_CANWILL, OT_A_HEAVYBLOW, NA, NA, NULL); + addflag(lastrace->flags, F_FLEEONHPPCT, 50, NA, NA, NULL); + + addrace(R_GIANTFIRE, "fire giant", 160, 'H', MT_FLESH); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); + addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_SIZE, SZ_HUGE, NA, NA, NULL); + addflag(lastrace->flags, F_HITDICE, 21, NA, NA, NULL); + addflag(lastrace->flags, F_ARMOURRATING, 13, NA, NA, NULL); + addflag(lastrace->flags, F_EVASION, -20, NA, NA, NULL); + addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); + addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, NULL); + addflag(lastrace->flags, F_HASATTACK, 2, 5, NA, "fists"); + addflag(lastrace->flags, F_STARTOB, 90, NA, NA, "25-100 gold coins"); + addflag(lastrace->flags, F_IFPCT, 70, NA, NA, NULL); + addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "flaming greatsword"); + addflag(lastrace->flags, F_ELSE, NA, NA, NA, NULL); + addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "flaming longsword"); + addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "javelin"); + addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "javelin"); + addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "javelin"); + addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "javelin"); + addflag(lastrace->flags, F_STARTOB, 80, NA, NA, "plate mail"); + addflag(lastrace->flags, F_STARTOBCLASS, 70, OC_ARMOUR, NA, NULL); + addflag(lastrace->flags, F_STARTOBCLASS, 30, OC_POTION, NA, NULL); + addflag(lastrace->flags, F_STARTOBCLASS, 30, OC_POTION, NA, NULL); + addflag(lastrace->flags, F_STARTSTR, ST_MIGHTY, NA, NA, NULL); + addflag(lastrace->flags, F_STARTIQ, IQ_AVERAGE, NA, NA, NULL); + addflag(lastrace->flags, F_STARTDEX, DX_AVERAGE, NA, NA, NULL); + addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, NA, NA, "bellows^a bellow"); + addflag(lastrace->flags, F_FLEEONHPPCT, 50, NA, NA, NULL); + + addrace(R_GIANTFIREFC, "fire giant forgecaller", 160, 'H', MT_FLESH); + lastrace->baseid = R_GIANTFIRE; + addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "fire giant corpse"); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); + addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_SIZE, SZ_HUGE, NA, NA, NULL); + addflag(lastrace->flags, F_HITDICE, 17, NA, NA, NULL); + addflag(lastrace->flags, F_ARMOURRATING, 12, NA, NA, NULL); + addflag(lastrace->flags, F_EVASION, -20, NA, NA, NULL); + addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); + addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, NULL); + addflag(lastrace->flags, F_HASATTACK, 2, 5, NA, "fists"); + addflag(lastrace->flags, F_STARTOB, 90, NA, NA, "25-100 gold coins"); + addflag(lastrace->flags, F_IFPCT, 70, NA, NA, NULL); + addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "flaming morningstar"); + addflag(lastrace->flags, F_ELSE, NA, NA, NA, NULL); + addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "flaming mace"); + addflag(lastrace->flags, F_STARTOB, 80, NA, NA, "plate mail"); + addflag(lastrace->flags, F_STARTOBCLASS, 70, OC_ARMOUR, NA, NULL); + addflag(lastrace->flags, F_STARTOBCLASS, 30, OC_POTION, NA, NULL); + addflag(lastrace->flags, F_STARTOBCLASS, 30, OC_POTION, NA, NULL); + addflag(lastrace->flags, F_STARTSTR, ST_MIGHTY, NA, NA, NULL); + addflag(lastrace->flags, F_STARTIQ, IQ_AVERAGE, NA, NA, NULL); + addflag(lastrace->flags, F_STARTDEX, DX_DEXTROUS, NA, NA, NULL); + addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, NA, NA, "bellows^a bellow"); + addflag(lastrace->flags, F_FLEEONHPPCT, 50, NA, NA, NULL); + addflag(lastrace->flags, F_MPDICE, 0, 9, NA, NULL); + addflag(lastrace->flags, F_MPREGEN, 1, NA, NA, NULL); + addflag(lastrace->flags, F_DTRESIST, DT_FIRE, NA, NA, NULL); + addflag(lastrace->flags, F_CANCAST, OT_S_FIREDART, NA, NA, NULL); + addflag(lastrace->flags, F_CANCAST, OT_S_FLAMEPILLAR, NA, NA, NULL); + addflag(lastrace->flags, F_CANWILL, OT_S_FLAMEBURST, 4, 4, NULL); + + addrace(R_GIANTFIRETITAN, "fire titan", 160, 'H', MT_FLESH); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, 40, NA, NULL); + addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_SIZE, SZ_ENORMOUS, NA, NA, NULL); + addflag(lastrace->flags, F_HITDICE, 49, NA, NA, NULL); + addflag(lastrace->flags, F_ARMOURRATING, 20, NA, NA, NULL); + addflag(lastrace->flags, F_EVASION, -30, NA, NA, NULL); + addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); + addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, NULL); + addflag(lastrace->flags, F_HASATTACK, 2, 5, 8, "fists"); + addflag(lastrace->flags, F_STARTOB, 90, NA, NA, "100-300 gold coins"); + addflag(lastrace->flags, F_IFPCT, 65, NA, NA, NULL); + addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "flaming greatsword of pyromania"); + addflag(lastrace->flags, F_ELSE, NA, NA, NA, NULL); + addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "flaming greatsword"); + addflag(lastrace->flags, F_STARTOBCLASS, 30, OC_POTION, NA, NULL); + addflag(lastrace->flags, F_STARTOBCLASS, 30, OC_POTION, NA, NULL); + addflag(lastrace->flags, F_STARTSTR, ST_MIGHTY, NA, NA, NULL); + addflag(lastrace->flags, F_STARTIQ, IQ_AVERAGE, NA, NA, NULL); + addflag(lastrace->flags, F_STARTDEX, DX_SWIFT, NA, NA, NULL); + addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, NA, NA, "bellows^a bellow"); + addflag(lastrace->flags, F_FLEEONHPPCT, 50, NA, NA, NULL); + addflag(lastrace->flags, F_HEAVYBLOW, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_CANWILL, OT_S_BURNINGWAVE, 3, 3, NULL); + + // TODO: storm giant + // TODO: storm titan addrace(R_GNOLL, "gnoll", 130, 'h', MT_FLESH); + addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "gnoll corpse"); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NUMAPPEAR, 2, 3, NA, ""); addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); - addflag(lastrace->flags, F_HITDICE, 3, NA, NA, NULL); - addflag(lastrace->flags, F_EVASION, 0, NA, NA, NULL); + addflag(lastrace->flags, F_HITDICE, 8, NA, NA, NULL); + addflag(lastrace->flags, F_ARMOURRATING, 9, NA, NA, NULL); + addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); - addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); - addflag(lastrace->flags, F_STARTIQ, IQ_SMART, NA, NA, NULL); + addflag(lastrace->flags, F_ACTIONSPEED, SP_FAST, NA, NA, ""); + addflag(lastrace->flags, F_STARTIQ, IQ_AVERAGE, NA, NA, NULL); + addflag(lastrace->flags, F_STARTDEX, DX_DEXTROUS, NA, NA, NULL); addflag(lastrace->flags, F_STARTSTR, ST_STRONG, NA, NA, NULL); - addflag(lastrace->flags, F_HASATTACK, 2, 4, 0, "claws"); - addflag(lastrace->flags, F_STARTOB, 50, OT_SPEAR, NA, NULL); - addflag(lastrace->flags, F_STARTOBCLASS, 30, OC_POTION, NA, NULL); - addflag(lastrace->flags, F_STARTOBCLASS, 30, OC_POTION, NA, NULL); - addflag(lastrace->flags, F_STARTOBCLASS, 50, OC_ARMOUR, NA, NULL); - addflag(lastrace->flags, F_STARTOBCLASS, 50, OC_ARMOUR, NA, NULL); - addflag(lastrace->flags, F_STARTOB, 50, 1, 40, "gold coin"); - addflag(lastrace->flags, F_STARTOBCLASS, 50, OC_POTION, NA, NULL); + addflag(lastrace->flags, F_HASATTACK, 1, 6, 4, "claws"); + addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "leather armour"); + addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "1-40 gold coins"); addflag(lastrace->flags, F_WANTSBETTERWEP, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, NA, NA, "shouts^a shout"); addflag(lastrace->flags, F_SEEINDARK, 2, NA, NA, NULL); + addflag(lastrace->flags, F_PACKATTACK, 5, NA, 2, "gnoll"); + + addrace(R_GNOLLHM, "gnoll huntmaster", 130, 'h', MT_FLESH); + lastrace->baseid = R_GNOLL; + addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "gnoll corpse"); + addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); + addflag(lastrace->flags, F_HITDICE, 6, NA, NA, NULL); + addflag(lastrace->flags, F_ARMOURRATING, 9, NA, NA, NULL); + addflag(lastrace->flags, F_EVASION, 0, NA, NA, NULL); + addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); + addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); + addflag(lastrace->flags, F_STARTIQ, IQ_DOPEY, NA, NA, NULL); + addflag(lastrace->flags, F_STARTDEX, DX_DEXTROUS, NA, NA, NULL); + addflag(lastrace->flags, F_STARTSTR, ST_STRONG, NA, NA, NULL); + addflag(lastrace->flags, F_HASATTACK, 1, 6, 4, "claws"); + addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "leather armour"); + addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "longbow"); + addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "10-20 arrows"); + addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "hand axe"); + addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "1-40 gold coins"); + addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, NA, NA, "shouts^a shout"); + addflag(lastrace->flags, F_SEEINDARK, 2, NA, NA, NULL); + addflag(lastrace->flags, F_PACKATTACK, 5, NA, 2, "gnoll"); + + addrace(R_GNOLLMR, "gnoll marauder", 130, 'h', MT_FLESH); + lastrace->baseid = R_GNOLL; + addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "gnoll corpse"); + addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); + addflag(lastrace->flags, F_HITDICE, 10, NA, NA, NULL); + addflag(lastrace->flags, F_ARMOURRATING, 9, NA, NA, NULL); + addflag(lastrace->flags, F_EVASION, 0, NA, NA, NULL); + addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); + addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); + addflag(lastrace->flags, F_STARTIQ, IQ_DOPEY, NA, NA, NULL); + addflag(lastrace->flags, F_STARTDEX, DX_DEXTROUS, NA, NA, NULL); + addflag(lastrace->flags, F_STARTSTR, ST_STRONG, NA, NA, NULL); + addflag(lastrace->flags, F_HASATTACK, 1, 4, 2, "claws"); + addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "leather armour"); + addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "spear"); + addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "buckler"); + addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, NA, NA, "shouts^a shout"); + addflag(lastrace->flags, F_SEEINDARK, 2, NA, NA, NULL); + addflag(lastrace->flags, F_QUICKBITE, 1, 6, 2, NULL); + addflag(lastrace->flags, F_PACKATTACK, 5, NA, 2, "gnoll"); addrace(R_GOBLIN, "goblin", 20, 'g', MT_FLESH); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -3758,98 +4220,206 @@ void initrace(void) { addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_HASATTACK, 1, 4, NA, "claws"); addflag(lastrace->flags, F_STARTIQ, IQ_DOPEY, NA, NA, NULL); - addflag(lastrace->flags, F_STARTOBDT, 50, DT_PIERCE, NA, NULL); + addflag(lastrace->flags, F_STARTSTR, ST_AVERAGE, NA, NA, NULL); + addflag(lastrace->flags, F_STARTDEX, DX_DEXTROUS, NA, NA, NULL); + addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "short sword"); addflag(lastrace->flags, F_STARTOBCLASS, 40, OC_POTION, NA, NULL); addflag(lastrace->flags, F_WANTSBETTERWEP, B_TRUE, B_COVETS, NA, NULL); - addflag(lastrace->flags, F_WANTS, OT_GOLD, NA, NA, NULL); - addflag(lastrace->flags, F_WANTSOBFLAG, F_MISSILE, NA, NA, NULL); - addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, NA, NA, "shouts^a shout"); - addflag(lastrace->flags, F_SEEINDARK, 3, NA, NA, NULL); - addflag(lastrace->flags, F_STARTJOB, 25, J_WIZARD, NA, NULL); - addrace(R_GOBLINGUARD, "goblin guard", 30, 'g', MT_FLESH); - addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "goblin corpse"); - addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); - addflag(lastrace->flags, F_RARITY, H_DUNGEON, 60, NA, NULL); - addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL); - addflag(lastrace->flags, F_HITDICE, 2, 3, NA, NULL); - addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL); - addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); - addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); - addflag(lastrace->flags, F_HASATTACK, 1, 4, 0, "claws"); - addflag(lastrace->flags, F_STARTIQ, IQ_AVERAGE, NA, NA, NULL); - addflag(lastrace->flags, F_STARTOBCLASS, 100, OC_ARMOUR, NA, NULL); - addflag(lastrace->flags, F_STARTOBCLASS, 50, OC_ARMOUR, NA, NULL); - addflag(lastrace->flags, F_STARTOBDT, 100, DT_PIERCE, NA, NULL); - addflag(lastrace->flags, F_STARTOBCLASS, 70, OC_POTION, NA, NULL); - addflag(lastrace->flags, F_STARTOBCLASS, 40, OC_POTION, NA, NULL); - addflag(lastrace->flags, F_WANTSBETTERWEP, B_TRUE, B_COVETS, NA, NULL); - addflag(lastrace->flags, F_WANTS, OT_GOLD, NA, NA, NULL); - addflag(lastrace->flags, F_WANTSOBFLAG, F_MISSILE, NA, NA, NULL); - addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, NA, NA, "shouts^a shout"); - addflag(lastrace->flags, F_SEEINDARK, 3, NA, NA, NULL); - addrace(R_GOBLINCHAMP, "goblin champion", 40, 'g', MT_FLESH); - addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "goblin corpse"); - addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); - addflag(lastrace->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); - addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL); - addflag(lastrace->flags, F_HITDICE, 3, 3, NA, NULL); - addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL); - addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); - addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); - addflag(lastrace->flags, F_HASATTACK, 1, 4, 0, "claws"); - addflag(lastrace->flags, F_STARTIQ, IQ_AVERAGE, NA, NA, NULL); - addflag(lastrace->flags, F_STARTOBCLASS, 100, OC_ARMOUR, NA, NULL); - addflag(lastrace->flags, F_STARTOBCLASS, 100, OC_ARMOUR, NA, NULL); - addflag(lastrace->flags, F_STARTOBCLASS, 50, OC_ARMOUR, NA, NULL); - addflag(lastrace->flags, F_STARTOBCLASS, 50, OC_ARMOUR, NA, NULL); - addflag(lastrace->flags, F_STARTOBDT, 100, DT_PIERCE, NA, NULL); - addflag(lastrace->flags, F_STARTOBDT, 80, DT_PIERCE, NA, NULL); - addflag(lastrace->flags, F_STARTOBCLASS, 60, OC_POTION, NA, NULL); - addflag(lastrace->flags, F_STARTOBCLASS, 30, OC_POTION, NA, NULL); - addflag(lastrace->flags, F_WANTSBETTERWEP, B_TRUE, B_COVETS, NA, NULL); - addflag(lastrace->flags, F_WANTS, OT_GOLD, NA, NA, NULL); - addflag(lastrace->flags, F_WANTSOBFLAG, F_MISSILE, NA, NA, NULL); + addflag(lastrace->flags, F_WANTS, OT_GOLD, B_COVETS, NA, NULL); addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, NA, NA, "shouts^a shout"); addflag(lastrace->flags, F_SEEINDARK, 3, NA, NA, NULL); + //addflag(lastrace->flags, F_STARTJOB, 25, J_WIZARD, NA, NULL); + addflag(lastrace->flags, F_DODGES, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_PACKATTACK, 2, DT_CLAW, 3, "goblin"); + addrace(R_GOBLINWAR, "goblin warrior", 30, 'g', MT_FLESH); + lastrace->baseid = R_GOBLIN; + addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "goblin corpse"); + addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); + addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL); + addflag(lastrace->flags, F_HITDICE, 3, 5, NA, NULL); + addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL); + addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); + addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); + addflag(lastrace->flags, F_HASATTACK, 1, 4, NA, "claws"); + addflag(lastrace->flags, F_STARTIQ, IQ_DOPEY, NA, NA, NULL); + addflag(lastrace->flags, F_STARTSTR, ST_AVERAGE, NA, NA, NULL); + addflag(lastrace->flags, F_STARTDEX, DX_DEXTROUS, NA, NA, NULL); + addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "spear"); + addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "1-5 javelins"); + addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "leather armour"); + addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, NA, NA, "shouts^a shout"); + addflag(lastrace->flags, F_SEEINDARK, 3, NA, NA, NULL); + addflag(lastrace->flags, F_DODGES, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_PACKATTACK, 2, DT_CLAW, 3, "goblin"); + + addrace(R_GOBLINSHOOTER, "goblin sharpshooter", 20, 'g', MT_FLESH); + lastrace->baseid = R_GOBLIN; + addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "goblin corpse"); + addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); + addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL); + addflag(lastrace->flags, F_HITDICE, 3, 7, NA, NULL); + addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL); + addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); + addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); + addflag(lastrace->flags, F_HASATTACK, 1, 4, NA, "claws"); + addflag(lastrace->flags, F_STARTIQ, IQ_DOPEY, NA, NA, NULL); + addflag(lastrace->flags, F_STARTSTR, ST_AVERAGE, NA, NA, NULL); + addflag(lastrace->flags, F_STARTDEX, DX_DEXTROUS, NA, NA, NULL); + addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "short sword"); + addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "hand crossbow"); + addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "1-15 bolts"); + addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "leather armour"); + addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, NA, NA, "shouts^a shout"); + addflag(lastrace->flags, F_SEEINDARK, 5, NA, NA, NULL); + addflag(lastrace->flags, F_DODGES, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_PACKATTACK, 2, DT_CLAW, 3, "goblin"); + // TODO: can hide in shadows (need cansee function first) + + + addrace(R_GOBLINHEXER, "goblin hexer", 20, 'g', MT_FLESH); + lastrace->baseid = R_GOBLIN; + addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "goblin corpse"); + addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); + addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL); + addflag(lastrace->flags, F_HITDICE, 5, 6, NA, NULL); + addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL); + addflag(lastrace->flags, F_MOVESPEED, SP_SLOW, NA, NA, NULL); + addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); + addflag(lastrace->flags, F_HASATTACK, 1, 4, NA, "claws"); + addflag(lastrace->flags, F_STARTIQ, IQ_AVERAGE, NA, NA, NULL); + addflag(lastrace->flags, F_STARTSTR, ST_AVERAGE, NA, NA, NULL); + addflag(lastrace->flags, F_STARTDEX, DX_DEXTROUS, NA, NA, NULL); + addflag(lastrace->flags, F_STARTOB, 80, NA, NA, "club"); + addflag(lastrace->flags, F_STARTOB, 80, NA, NA, "leather armour"); + addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, NA, NA, "shouts^a shout"); + addflag(lastrace->flags, F_SEEINDARK, 5, NA, NA, NULL); + addflag(lastrace->flags, F_DODGES, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_PACKATTACK, 2, DT_CLAW, 3, "goblin"); + addflag(lastrace->flags, F_MPDICE, 0, 10, NA, NULL); + addflag(lastrace->flags, F_MPREGEN, 3, NA, NA, NULL); + addflag(lastrace->flags, F_CANCAST, OT_S_BLINDNESS, NA, NA, NULL); + addflag(lastrace->flags, F_CANCAST, OT_S_PAIN, NA, NA, NULL); + addrace(R_HOBGOBLIN, "hobgoblin", 90, 'g', MT_FLESH); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); - addflag(lastrace->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); + addflag(lastrace->flags, F_NUMAPPEAR, 1, 2, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); addflag(lastrace->flags, F_HITDICE, 2, 3, NA, NULL); + addflag(lastrace->flags, F_ARMOURRATING, 8, NA, NA, NULL); addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); - addflag(lastrace->flags, F_HASATTACK, 1, 8, NA, "claws"); + addflag(lastrace->flags, F_HASATTACK, 1, 6, NA, "claws"); addflag(lastrace->flags, F_STARTIQ, IQ_SMART, NA, NA, NULL); - addflag(lastrace->flags, F_STARTSTR, ST_STRONG, NA, NA, NULL); + addflag(lastrace->flags, F_STARTSTR, ST_MIGHTY, NA, NA, NULL); addflag(lastrace->flags, F_STARTDEX, DX_DEXTROUS, NA, NA, NULL); - addflag(lastrace->flags, F_STARTOBDT, 50, DT_SLASH, NA, NULL); + addflag(lastrace->flags, F_STARTOB, 80, NA, NA, "longsword"); + addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "buckler"); addflag(lastrace->flags, F_STARTOBCLASS, 100, OC_ARMOUR, NA, NULL); addflag(lastrace->flags, F_STARTOBCLASS, 50, OC_ARMOUR, NA, NULL); - addflag(lastrace->flags, F_STARTOBCLASS, 40, OC_POTION, NA, NULL); - addflag(lastrace->flags, F_STARTOBCLASS, 40, OC_POTION, NA, NULL); + addflag(lastrace->flags, F_STARTOBCLASS, 30, OC_POTION, NA, NULL); addflag(lastrace->flags, F_WANTSBETTERWEP, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_WANTS, OT_GOLD, NA, NA, NULL); - addflag(lastrace->flags, F_WANTSOBFLAG, F_MISSILE, NA, NA, NULL); - addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, NA, NA, NULL); addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, NA, NA, "shouts^a shout"); addflag(lastrace->flags, F_SEEINDARK, 10, NA, NA, NULL); + addflag(lastrace->flags, F_PHALANX, 5, NA, 1, "hobgoblin"); + addrace(R_HOBGOBLINWAR, "hobgoblin warrior", 90, 'g', MT_FLESH); + lastrace->baseid = R_HOBGOBLIN; + addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); + addflag(lastrace->flags, F_NUMAPPEAR, 1, 2, NA, NULL); + addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); + addflag(lastrace->flags, F_HITDICE, 2, 3, NA, NULL); + addflag(lastrace->flags, F_ARMOURRATING, 10, NA, NA, NULL); + addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL); + addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); + addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); + addflag(lastrace->flags, F_HASATTACK, 1, 6, NA, "claws"); + addflag(lastrace->flags, F_STARTIQ, IQ_SMART, NA, NA, NULL); + addflag(lastrace->flags, F_STARTSTR, ST_MIGHTY, NA, NA, NULL); + addflag(lastrace->flags, F_STARTDEX, DX_DEXTROUS, NA, NA, NULL); + addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "flail"); + addflag(lastrace->flags, F_STARTOB, 90, NA, NA, "large shield"); + addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "scale armour"); + addflag(lastrace->flags, F_STARTOBCLASS, 50, OC_ARMOUR, NA, NULL); + addflag(lastrace->flags, F_STARTOBCLASS, 30, OC_POTION, NA, NULL); + addflag(lastrace->flags, F_WANTSBETTERWEP, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_WANTS, OT_GOLD, NA, NA, NULL); + addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, NA, NA, "shouts^a shout"); + addflag(lastrace->flags, F_SEEINDARK, 10, NA, NA, NULL); + addflag(lastrace->flags, F_PHALANX, 8, NA, 1, "hobgoblin"); + addflag(lastrace->flags, F_NOFLEE, B_TRUE, NA, NA, NULL); + + // TODO: hobgoblin archer + // TODO: hobgoblin warcaster + + addrace(R_KOBOLD, "kobold", 18, 'k', MT_FLESH); + addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); + addflag(lastrace->flags, F_NUMAPPEAR, 1, 3, NA, ""); + addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL); + addflag(lastrace->flags, F_HITDICE, 1, NA, NA, NULL); + addflag(lastrace->flags, F_EVASION, 15, NA, NA, NULL); + addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); + addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); + addflag(lastrace->flags, F_HASATTACK, 0, 1, 4, "claws"); + addflag(lastrace->flags, F_STARTSTR, ST_WEAK, NA, NA, NULL); + addflag(lastrace->flags, F_STARTIQ, IQ_DOPEY, NA, NA, NULL); + addflag(lastrace->flags, F_STARTDEX, DX_NIMBLE, NA, NA, NULL); + addflag(lastrace->flags, F_STARTOBDT, 20, DT_PIERCE, NA, NULL); + addflag(lastrace->flags, F_STARTOBCLASS, 40, OC_POTION, NA, NULL); + addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "1-5 darts"); + addflag(lastrace->flags, F_STARTOB, 33, NA, NA, "1-3 javelins"); + addflag(lastrace->flags, F_STARTOB, 33, NA, NA, "leather armour"); + addflag(lastrace->flags, F_STARTOB, 33, NA, NA, "buckler"); + addflag(lastrace->flags, F_WANTSBETTERWEP, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, NA, NA, "shouts^a shout"); + addflag(lastrace->flags, F_SEEINDARK, 2, NA, NA, NULL); + + addrace(R_TROGLODYTE, "troglodyte", 20, 'z', MT_FLESH); + addflag(lastrace->flags, F_COLDBLOOD, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); + addflag(lastrace->flags, F_HITDICE, 1, NA, NA, NULL); + addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL); + addflag(lastrace->flags, F_ARMOURRATING, 10, NA, NA, NULL); + addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); + addflag(lastrace->flags, F_ACTIONSPEED, SP_FAST, NA, NA, ""); + addflag(lastrace->flags, F_STARTSTR, ST_MIGHTY, NA, NA, NULL); + addflag(lastrace->flags, F_STARTIQ, IQ_DIMWITTED, NA, NA, NULL); + addflag(lastrace->flags, F_STARTDEX, DX_AVERAGE, NA, NA, NULL); + addflag(lastrace->flags, F_HASATTACK, 1, 2, 0, "fists"); + addflag(lastrace->flags, F_HASATTACK, 1, 2, 0, "tail"); + addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "club"); + addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "buckler"); + addflag(lastrace->flags, F_DTVULN, DT_COLD, B_TRUE, NA, NULL); + addflag(lastrace->flags, F_DTRESIST, DT_FIRE, B_TRUE, NA, NULL); + addflag(lastrace->flags, F_SEEINDARK, 3, NA, NA, NULL); + addflag(lastrace->flags, F_STENCH, 2, 2, NA, NULL); addrace(R_LIZARDMAN, "lizardman", 100, 'z', MT_FLESH); addflag(lastrace->flags, F_COLDBLOOD, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); - addflag(lastrace->flags, F_HITDICE, 2, 4, NA, NULL); + addflag(lastrace->flags, F_HITDICE, 6, NA, NA, NULL); addflag(lastrace->flags, F_EVASION, 15, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_FAST, NA, NA, ""); - addflag(lastrace->flags, F_STARTIQ, IQ_SMART, NA, NA, NULL); + addflag(lastrace->flags, F_STARTSTR, ST_MIGHTY, NA, NA, NULL); + addflag(lastrace->flags, F_STARTIQ, IQ_DOPEY, NA, NA, NULL); + addflag(lastrace->flags, F_STARTDEX, DX_DEXTROUS, NA, NA, NULL); addflag(lastrace->flags, F_HASATTACK, 1, 5, 1, "claws"); addflag(lastrace->flags, F_HASATTACK, 1, 4, 0, "tail"); + addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "spear"); addflag(lastrace->flags, F_DTVULN, DT_COLD, B_TRUE, NA, NULL); addflag(lastrace->flags, F_DTRESIST, DT_FIRE, B_TRUE, NA, NULL); addflag(lastrace->flags, F_SEEINDARK, 3, NA, NA, NULL); @@ -3863,7 +4433,6 @@ void initrace(void) { addflag(lastrace->flags, F_EVASION, 0, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_SLOW, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); - addflag(lastrace->flags, F_INDUCEFEAR, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTIQ, IQ_MINDLESS, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_WEAPON, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_SECWEAPON, NA, NA, NULL); @@ -3876,20 +4445,76 @@ void initrace(void) { addflag(lastrace->flags, F_NOBODYPART, BP_LEGS, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_FEET, NA, NA, NULL); addflag(lastrace->flags, F_SEEINDARK, UNLIMITED, NA, NA, NULL); + addflag(lastrace->flags, F_INDUCEFEAR, B_TRUE, NA, NA, NULL); addrace(R_OGRE, "ogre", 160, 'O', MT_FLESH); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL); - addflag(lastrace->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); - addflag(lastrace->flags, F_HITDICE, 4, 0, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, 65, NA, NULL); + addflag(lastrace->flags, F_HITDICE, 7, 0, NA, NULL); addflag(lastrace->flags, F_EVASION, -5, NA, NA, NULL); + addflag(lastrace->flags, F_ARMOURRATING, 11, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_HASATTACK, 2, 4, 0, "fists"); - addflag(lastrace->flags, F_STARTIQ, IQ_DOPEY, NA, NA, NULL); + addflag(lastrace->flags, F_STARTIQ, IQ_STUPID, NA, NA, NULL); + addflag(lastrace->flags, F_STARTDEX, DX_AVERAGE, NA, NA, NULL); addflag(lastrace->flags, F_STARTSTR, ST_MIGHTY, NA, NA, NULL); - addflag(lastrace->flags, F_STARTOBDT, 90, DT_BASH, NA, NULL); - addflag(lastrace->flags, F_SEEINDARK, 2, NA, NA, NULL); + addflag(lastrace->flags, F_WANTSBETTERWEP, B_TRUE, B_COVETS, NA, NULL); + addflag(lastrace->flags, F_WANTS, OT_GOLD, B_COVETS, NA, NULL); + addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, B_COVETS, NA, NULL); + addflag(lastrace->flags, F_IFPCT, 80, NA, NA, NULL); + addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "great club"); + addflag(lastrace->flags, F_ELSE, NA, NA, NA, NULL); + addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "morningstar"); + addflag(lastrace->flags, F_STARTOB, 70, NA, NA, "leather armour"); + + addrace(R_OGRESAVAGE, "ogre savage", 160, 'O', MT_FLESH); + lastrace->baseid = R_OGRE; + addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, 55, NA, NULL); + addflag(lastrace->flags, F_HITDICE, 13, 8, NA, NULL); + addflag(lastrace->flags, F_EVASION, 0, NA, NA, NULL); + addflag(lastrace->flags, F_ARMOURRATING, 11, NA, NA, NULL); + addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); + addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); + addflag(lastrace->flags, F_HASATTACK, 3, 4, 0, "claws"); + addflag(lastrace->flags, F_STARTIQ, IQ_STUPID, NA, NA, NULL); + addflag(lastrace->flags, F_STARTDEX, DX_AVERAGE, NA, NA, NULL); + addflag(lastrace->flags, F_STARTSTR, ST_MIGHTY, NA, NA, NULL); + addflag(lastrace->flags, F_WANTSBETTERWEP, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_WANTS, OT_GOLD, NA, NA, NULL); + addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, NA, NA, NULL); + addflag(lastrace->flags, F_IFPCT, 80, NA, NA, NULL); + addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "blessed great club"); + addflag(lastrace->flags, F_ELSE, NA, NA, NA, NULL); + addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "great club"); + addflag(lastrace->flags, F_STARTOB, 80, NA, NA, "leather armour"); + + addrace(R_OGREWARHULK, "ogre warhulk", 160, 'O', MT_FLESH); + lastrace->baseid = R_OGRE; + addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, 60, NA, NULL); + addflag(lastrace->flags, F_HITDICE, 35, 0, NA, NULL); + addflag(lastrace->flags, F_EVASION, 0, NA, NA, NULL); + addflag(lastrace->flags, F_ARMOURRATING, 11, NA, NA, NULL); + addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); + addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); + addflag(lastrace->flags, F_HASATTACK, 2, 4, NA, "fists"); + addflag(lastrace->flags, F_STARTIQ, IQ_STUPID, NA, NA, NULL); + addflag(lastrace->flags, F_STARTDEX, DX_AVERAGE, NA, NA, NULL); + addflag(lastrace->flags, F_STARTSTR, ST_MIGHTY, NA, NA, NULL); + addflag(lastrace->flags, F_WANTSBETTERWEP, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_WANTS, OT_GOLD, NA, NA, NULL); + addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, NA, NA, NULL); + addflag(lastrace->flags, F_IFPCT, 80, NA, NA, NULL); + addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "heavy flail"); + addflag(lastrace->flags, F_ELSE, NA, NA, NA, NULL); + addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "great club"); + addflag(lastrace->flags, F_STARTOB, 70, NA, NA, "leather armour"); + addflag(lastrace->flags, F_HEAVYBLOW, B_TRUE, NA, NA, NULL); addrace(R_ORC, "orc", 90, 'o', MT_FLESH); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -3897,43 +4522,74 @@ void initrace(void) { addflag(lastrace->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); addflag(lastrace->flags, F_HITDICE, 1, 3, NA, NULL); addflag(lastrace->flags, F_EVASION, 5, NA, NA, NULL); + addflag(lastrace->flags, F_ARMOURRATING, 5, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_STARTIQ, IQ_DOPEY, NA, NA, NULL); addflag(lastrace->flags, F_HASATTACK, 1, 4, 0, "claws"); - addflag(lastrace->flags, F_STARTOBDT, 50, DT_SLASH, NA, NULL); - addflag(lastrace->flags, F_STARTOBDT, 30, DT_BASH, NA, NULL); + addflag(lastrace->flags, F_IFPCT, 70, NA, NA, NULL); + addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "club"); + addflag(lastrace->flags, F_ELSE, NA, NA, NA, NULL); + addflag(lastrace->flags, F_STARTOBDT, 50, DT_SLASH, NA, NULL); addflag(lastrace->flags, F_STARTOBCLASS, 30, OC_POTION, NA, NULL); - addflag(lastrace->flags, F_STARTOB, 50, 1, 1, "leather armour"); - addflag(lastrace->flags, F_STARTOB, 50, 1, 1, "leather boots"); - addflag(lastrace->flags, F_STARTOB, 50, 1, 1, "bone helmet"); - addflag(lastrace->flags, F_STARTOB, 50, 1, 1, "gauntlets"); - addflag(lastrace->flags, F_STARTOB, 50, 1, 40, "gold coin"); + addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "leather armour"); + addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "bone helmet"); + addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "1-50 gold coins"); addflag(lastrace->flags, F_STARTOBCLASS, 50, OC_POTION, NA, NULL); addflag(lastrace->flags, F_WANTS, OT_GOLD, NA, NA, NULL); addflag(lastrace->flags, F_WANTSBETTERWEP, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, NA, NA, "shouts^a shout"); addflag(lastrace->flags, F_SEEINDARK, 2, NA, NA, NULL); - addflag(lastrace->flags, F_STARTJOB, 20, J_WIZARD, NA, NULL); + //addflag(lastrace->flags, F_STARTJOB, 20, J_WIZARD, NA, NULL); + addflag(lastrace->flags, F_CANWILL, OT_A_SPRINT, 5, 5, NULL); + + addrace(R_ORCWARRIOR, "orc wariror", 90, 'o', MT_FLESH); + lastrace->baseid = R_ORC; + addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); + addflag(lastrace->flags, F_HITDICE, 2, 3, NA, NULL); + addflag(lastrace->flags, F_EVASION, 5, NA, NA, NULL); + addflag(lastrace->flags, F_ARMOURRATING, 10, NA, NA, NULL); + addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); + addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); + addflag(lastrace->flags, F_STARTIQ, IQ_DOPEY, NA, NA, NULL); + addflag(lastrace->flags, F_HASATTACK, 1, 4, 0, "claws"); + addflag(lastrace->flags, F_IFPCT, 70, NA, NA, NULL); + addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "battleaxe"); + addflag(lastrace->flags, F_ELSE, NA, NA, NA, NULL); + addflag(lastrace->flags, F_STARTOBDT, 50, DT_CHOP, NA, NULL); + addflag(lastrace->flags, F_STARTOBCLASS, 30, OC_POTION, NA, NULL); + addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "leather armour"); + addflag(lastrace->flags, F_STARTOB, 75, NA, NA, "buckler"); + addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "bone helmet"); + addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "1-50 gold coins"); + addflag(lastrace->flags, F_STARTOBCLASS, 50, OC_POTION, NA, NULL); + addflag(lastrace->flags, F_WANTS, OT_GOLD, NA, NA, NULL); + addflag(lastrace->flags, F_WANTSBETTERWEP, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, NA, NA, "shouts^a shout"); + addflag(lastrace->flags, F_SEEINDARK, 2, NA, NA, NULL); + //addflag(lastrace->flags, F_STARTJOB, 20, J_WIZARD, NA, NULL); + addflag(lastrace->flags, F_CANWILL, OT_A_SPRINT, NA, NA, NULL); addrace(R_ORK, "ork", 90, 'o', MT_FLESH); addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "orc corpse"); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); - addflag(lastrace->flags, F_HITDICE, 1, 3, NA, NULL); + addflag(lastrace->flags, F_HITDICE, 3, 3, NA, NULL); addflag(lastrace->flags, F_EVASION, 0, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_HASATTACK, 1, 4, 0, "claws"); addflag(lastrace->flags, F_STARTIQ, IQ_AVERAGE, NA, NA, NULL); - addflag(lastrace->flags, F_STARTOBDT, 50, DT_SLASH, NA, NULL); + addflag(lastrace->flags, F_STARTOBDT, 100, DT_SLASH, NA, NULL); addflag(lastrace->flags, F_STARTOBDT, 30, DT_BASH, NA, NULL); addflag(lastrace->flags, F_STARTOBCLASS, 30, OC_POTION, NA, NULL); - addflag(lastrace->flags, F_STARTOB, 50, 1, 1, "flak jacket"); - addflag(lastrace->flags, F_STARTOB, 50, 1, 1, "leather boots"); - addflag(lastrace->flags, F_STARTOB, 50, 1, 1, "football helmet"); - addflag(lastrace->flags, F_STARTOB, 50, 1, 25, "gold coin"); + addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "flak jacket"); + addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "leather boots"); + addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "football helmet"); + addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "1-25 gold coins"); addflag(lastrace->flags, F_STARTOBCLASS, 50, OC_POTION, NA, NULL); addflag(lastrace->flags, F_STARTOBCLASS, 50, OC_TECH, NA, NULL); addflag(lastrace->flags, F_WANTS, OT_GOLD, NA, NA, NULL); @@ -3970,7 +4626,7 @@ void initrace(void) { addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 65, NA, NULL); - addflag(lastrace->flags, F_HITDICE, 1, 3, NA, NULL); + addflag(lastrace->flags, F_HITDICE, 2, 3, NA, NULL); addflag(lastrace->flags, F_EVASION, 40, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_FAST, NA, NA, ""); @@ -3980,12 +4636,12 @@ void initrace(void) { addflag(lastrace->flags, F_CANSEETHROUGHMAT, MT_GAS, NA, NA, NULL); addflag(lastrace->flags, F_AUTOCREATEOB, 1, NA, NA, "cloud of smoke"); - addrace(R_SLIME, "slime", 10, 'j', MT_SLIME); + addrace(R_OOZEGREY, "grey ooze", 10, 'j', MT_SLIME); addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "pool of slime"); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); - addflag(lastrace->flags, F_HITDICE, 2, 0, NA, NULL); + addflag(lastrace->flags, F_HITDICE, 5, 0, NA, NULL); addflag(lastrace->flags, F_EVASION, 0, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_SLOW, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); @@ -3996,11 +4652,14 @@ void initrace(void) { addflag(lastrace->flags, F_NOBODYPART, BP_LEFTHAND, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_HANDS, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_HEAD, NA, NA, NULL); + addflag(lastrace->flags, F_NOBODYPART, BP_EYES, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_SHOULDERS, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_LEGS, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_FEET, NA, NA, NULL); - addflag(lastrace->flags, F_HASATTACK, 2, 3, 0, "acidattack"); + addflag(lastrace->flags, F_HASATTACK, 1, 6, 5, "acidattack"); addflag(lastrace->flags, F_SEEINDARK, UNLIMITED, NA, NA, NULL); + addflag(lastrace->flags, F_SEEWITHOUTEYES, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_DTIMMUNE, DT_ACID, B_TRUE, NA, NULL); addrace(R_SPRITEFIRE, "fire sprite", 5, 'n', MT_FIRE); addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "small fire"); @@ -4124,8 +4783,26 @@ void initrace(void) { addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, B_COVETS, NA, NULL); addflag(lastrace->flags, F_SEEINDARK, 5, NA, NA, NULL); + addflag(lastrace->flags, F_CANWILL, OT_A_SPRINT, 5, 5, NULL); // insects + addrace(R_BUTTERFLY, "butterfly", 0.01, 'i', MT_FLESH); + addflag(lastrace->flags, F_INSECT, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_STARTIQ, IQ_ANIMAL, NA, NA, NULL); + addflag(lastrace->flags, F_MOVESPEED, SP_VERYFAST, NA, NA, ""); + addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); + addflag(lastrace->flags, F_SIZE, SZ_TINY, NA, NA, NULL); + addflag(lastrace->flags, F_FLYING, B_TRUE, NA, NA, ""); + addflag(lastrace->flags, F_HITDICE, 0, 1, NA, NULL); + addflag(lastrace->flags, F_EVASION, 60, NA, NA, NULL); + addflag(lastrace->flags, F_NOBODYPART, BP_WEAPON, NA, NA, NULL); + addflag(lastrace->flags, F_NOBODYPART, BP_SECWEAPON, NA, NA, NULL); + addflag(lastrace->flags, F_NOBODYPART, BP_SHOULDERS, NA, NA, NULL); + addflag(lastrace->flags, F_NOBODYPART, BP_HANDS, NA, NA, NULL); + addflag(lastrace->flags, F_NOPACK, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_PRODUCESLIGHT, 2, NA, NA, NULL); + addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL); addrace(R_GIANTFLY, "giant fly", 1, 'i', MT_FLESH); addflag(lastrace->flags, F_INSECT, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTIQ, IQ_ANIMAL, NA, NA, NULL); @@ -4168,6 +4845,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, NA, NA, "buzzes angrily^an angry buzzing"); addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL); + addrace(R_GLOWBUG, "glowbug", 1, 'i', MT_FLESH); addflag(lastrace->flags, F_INSECT, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTIQ, IQ_ANIMAL, NA, NA, NULL); @@ -4198,12 +4876,14 @@ void initrace(void) { addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); - addflag(lastrace->flags, F_HITDICE, 2, 2, NA, NULL); + addflag(lastrace->flags, F_HITDICE, 5, 4, NA, NULL); + addflag(lastrace->flags, F_ARMOURRATING, 5, NA, NA, NULL); addflag(lastrace->flags, F_EVASION, -10, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_SLOW, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_SLOW, NA, NA, NULL); addflag(lastrace->flags, F_HASATTACK, 1, 4, NA, "claws"); addflag(lastrace->flags, F_HASATTACK, 1, 5, NA, "teeth"); + addflag(lastrace->flags, F_CANWILL, OT_A_GRAB, NA, NA, NULL); addflag(lastrace->flags, F_DTIMMUNE, DT_COLD, NA, NA, NULL); addflag(lastrace->flags, F_DTIMMUNE, DT_POISONGAS, NA, NA, NULL); addflag(lastrace->flags, F_DTIMMUNE, DT_DECAY, NA, NA, NULL); @@ -4326,7 +5006,7 @@ int isbleeding(lifeform_t *lf) { float hppct; hppct = ((float)lf->hp / (float) lf->maxhp) * 100; - if (hppct <= 15) return B_TRUE; + if (hppct <= 30) return B_TRUE; return B_FALSE; } @@ -4335,7 +5015,9 @@ int isblind(lifeform_t *lf) { return B_TRUE; } if (lfhasflagval(lf, F_NOBODYPART, BP_EYES, NA, NA, NULL)) { - return B_TRUE; + if (!lfhasflag(lf, F_SEEWITHOUTEYES)) { + return B_TRUE; + } } return B_FALSE; } @@ -4350,7 +5032,7 @@ enum BURDENED isburdened(lifeform_t *lf) { max = getmaxcarryweight(lf); cur = getobpileweight(lf->pack); ratio = cur / max; - if (ratio > 2) { + if (ratio >= 2) { return BR_OVERLOADED; } else if (ratio > 1.5) { return BR_STRAINED; @@ -4384,10 +5066,12 @@ void killlf(lifeform_t *lf) { // we are dead. // TODO: check on all maps? for (l = m->lf ; l ; l = l->next) { - f = hasflag(l->flags, F_TARGET); - if (f && (f->val[0] == lf->id)) { - killflag(f); - } + f = lfhasflagval(l, F_TARGET, lf->id, NA, NA, NULL); + if (f) killflag(f); + f = lfhasflagval(l, F_GRABBEDBY, lf->id, NA, NA, NULL); + if (f) killflag(f); + f = lfhasflagval(l, F_GRABBING, lf->id, NA, NA, NULL); + if (f) killflag(f); } // free mem @@ -4449,6 +5133,13 @@ int isfreebp(lifeform_t *lf, enum BODYPART bp) { return B_TRUE; } +int isfriendly(lifeform_t *lf) { + if (lfhasflag(lf, F_FRIENDLY)) { + return B_TRUE; + } + return B_FALSE; +} + int isgenius(lifeform_t *lf) { enum IQBRACKET iqb; iqb = getiqname(getattr(lf, A_IQ), NULL); @@ -4483,8 +5174,12 @@ int isingunrange(lifeform_t *lf, cell_t *where) { } +// cannot voluntarily move _at all_. int isimmobile(lifeform_t *lf) { - if (lfhasflag(lf, F_GRAVBOOSTED)) { + if (lfhasflag(lf, F_ASLEEP)) { + return B_TRUE; + } + if (lfhasflag(lf, F_FROZEN)) { return B_TRUE; } if (lfhasflag(lf, F_PARALYZED)) { @@ -4600,6 +5295,7 @@ int losehp(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *fromlf, ch int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *fromlf, char *damsrc, int reducedam) { char buf[BUFLEN]; + char buf2[BUFLEN]; if (isplayer(lf)) { statdirty = B_TRUE; @@ -4618,6 +5314,12 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml bleed(lf); } + if (hasflag(lf->flags, F_DEBUG)) { + char lfname[BUFLEN]; + getlfname(lf, lfname); + msg("[%s takes %d dam]",lfname, amt); + } + // take damage lf->hp -= amt; @@ -4645,6 +5347,12 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml } else { strcpy(buf, damsrc); } + + + // fill in damage amount + sprintf(buf2, "^%d damage",amt); + strcat(buf, buf2); + setlastdam(lf, buf); // fight back if required @@ -4668,6 +5376,30 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml return amt; } +void makefriendly(lifeform_t *lf) { + killflagsofid(lf->flags, F_HOSTILE); + if (!hasflag(lf->flags, F_FRIENDLY)) { + addflag(lf->flags, F_FRIENDLY, B_TRUE, NA, NA, NULL); + } +} + +void makenauseated(lifeform_t *lf, int amt, int howlong) { + flag_t *f; + + if (lfhasflag(lf, F_UNDEAD)) return; + if (isdead(lf)) return; + + f = lfhasflag(lf, F_NAUSEATED); + if (f) { + if ((f->lifetime >= 0) && (f->lifetime < howlong)) { + f->lifetime = howlong; + f->val[0] = MAXOF(f->val[0], amt); + } + } else { + addtempflag(lf->flags, F_NAUSEATED, amt, NA, NA, NULL, howlong); + } +} + void makenoise(lifeform_t *lf, enum NOISETYPE nid) { flag_t *f; char buf[BUFLEN]; @@ -4870,6 +5602,9 @@ int pickup(lifeform_t *lf, object_t *what, int howmany, int fromground) { case E_NOPICKUP: msg("You can't pick up %s!",obname); break; + case E_TOOBIG: + msg("%s %s too large for you to lift.",obname, (what->amt == 1) ? "is" : "are"); + break; case E_TOOHEAVY: msg("%s %s too heavy to lift!",obname, (what->amt == 1) ? "is" : "are"); break; @@ -4902,7 +5637,7 @@ int pickup(lifeform_t *lf, object_t *what, int howmany, int fromground) { o = moveob(what, lf->pack, howmany); if (o) { // if pickup was successful... if (isplayer(lf)) { - msglower("%c - %s.",o->letter, obname); + msgnocap("%c - %s.",o->letter, obname); } else if (haslos(player, lf->cell)) { char buf[BUFLEN]; getlfname(lf, buf); @@ -5239,22 +5974,6 @@ int rollstat(lifeform_t *lf, enum ATTRIB attr) { return B_FALSE; } -// positive mod makes it easier, negative makes it harder -int savingthrow(lifeform_t *lf, enum ATTRIB attr, int mod) { - int roll; - int attrib; - int levmod; - int db = B_FALSE; - attrib = getattr(lf, attr); - levmod = (lf->level / 3); - roll = rolldie(3, 6) - mod - levmod; // 3d6, modified for level - if (db) msg("sthrw vs %s: attr:%d, mod:%d, roll:%d, ",getattrname(attr), attrib, mod, roll); - if (roll <= attrib) { - return B_TRUE; - } - return B_FALSE; -} - // returns TRUE if something happened int scare(lifeform_t *lf, lifeform_t *scarer, int howlong) { if (!scarer) return B_FALSE; @@ -5268,7 +5987,7 @@ int scare(lifeform_t *lf, lifeform_t *scarer, int howlong) { return B_FALSE; } - if (!savingthrow(lf, A_IQ, -1)) { + if (!skillcheck(lf, SC_MORALE, 15, 0)) { flag_t *f; // already fleeing? f = hasflagval(lf->flags, F_FLEEFROM, scarer->id, NA, NA, NULL); @@ -5359,11 +6078,25 @@ void setguntarget(lifeform_t *lf, lifeform_t *targ) { char targname[BUFLEN]; getlfname(targ, targname); msg("Targetted: %s.",noprefix(targname)); // remove 'the ' + } else { + if (lfhasflag(lf, F_DEBUG)) { + char lfname[BUFLEN]; + char targname[BUFLEN]; + getlfname(lf, lfname); + getlfname(targ, targname); + dblog("%s targetted %s.",lfname,targname); + } } } else { if (isplayer(lf)) { // announce msg("Targetted: nothing."); + } else { + if (lfhasflag(lf, F_DEBUG)) { + char lfname[BUFLEN]; + getlfname(lf, lfname); + dblog("%s target set to nothing.",lfname); + } } } } @@ -5405,6 +6138,7 @@ void setrace(lifeform_t *lf, enum RACE rid) { } // first remove flags from existing race, or temporary ones + lf->born = B_FALSE; for (f = lf->flags->first ; f ; f = nextf) { nextf = f->next; if (f->lifetime == FROMRACE) { @@ -5420,7 +6154,6 @@ void setrace(lifeform_t *lf, enum RACE rid) { // inherit flags from race copyflags(lf->flags, lf->race->flags, FROMRACE); - // generate hp/maxhp from hit dice lf->maxhp = 0; for (i = 0; i < lf->level; i++) { @@ -5450,10 +6183,13 @@ void setrace(lifeform_t *lf, enum RACE rid) { lf->baseatt[A_DEX] = lf->att[A_DEX]; lf->baseatt[A_IQ] = lf->att[A_IQ]; + lf->born = B_TRUE; + // check whether: // new race can equip things (F_NOBODYPART xx) // new race can hold objects (F_NOPACK xx) // TODO: new race can use magic (F_NOSPELLS) + // new race can still hold all the items which you have if (gamestarted) { enum BODYPART bp; object_t *o,*nexto; @@ -5496,6 +6232,24 @@ void setrace(lifeform_t *lf, enum RACE rid) { } } } + + for (o = lf->pack->first ; o ; o = nexto) { + nexto = o->next; + + if (!canpickup(lf, o, o->amt)) { + char obname[BUFLEN]; + getobname(o, obname, o->amt); + // drop it! + if (isplayer(lf)) { + msg("Your %s drops to the ground!",noprefix(obname)); + } else if (haslos(player, lf->cell)) { + getlfname(lf, buf); + msg("%s%s %s drop to the ground!",buf, getpossessive(buf), + noprefix(obname)); + } + moveob(o, lf->cell->obpile, o->amt); + } + } } // end if gamestarted } @@ -5524,7 +6278,7 @@ int shoot(lifeform_t *lf) { return B_TRUE; } // get target - targ = getguntarget(player); + targ = getguntarget(lf); if (!targ) { reason = E_NOTARGET; return B_TRUE; @@ -5541,7 +6295,81 @@ int shoot(lifeform_t *lf) { taketime(lf, getattackspeed(lf)); - fireat(player, ammo, targ->cell, firespeed, gun); + fireat(lf, ammo, targ->cell, firespeed, gun); + return B_FALSE; +} + +// positive mod makes it easier, negative makes it harder +int skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod) { + int attrib; + int levmod; + int othermod = 0; + int db = B_FALSE; + int roll; + + switch (ct) { + case SC_STR: + attrib = getattr(lf, A_STR); + break; + case SC_DEX: + attrib = getattr(lf, A_DEX); + break; + case SC_IQ: + case SC_MORALE: + attrib = getattr(lf, A_IQ); + break; + case SC_DODGE: + case SC_SLIP: + attrib = getattr(lf, A_DEX); + break; + } + + // other modifiers + if (ct == SC_SLIP) { + if (getequippedob(lf->pack, BP_FEET)) { + othermod += 5; + } + if (lfhasflag(lf, F_STABILITY)) { + othermod += 10; + } + } + + levmod = (lf->level / 3); + + roll = rolldie(1, 20); + if (db) msg("skillcheck - need %d, got %d(rll)+%d(attr)+%d(lvm)+%d(othmod)+%d(mod)=%d.",diff, roll, attrib,levmod, othermod,mod); + roll += attrib; + roll += mod; + roll += levmod; + roll += othermod; + if (roll >= diff) { + return B_TRUE; + } + return B_FALSE; +} + +int slipon(lifeform_t *lf, object_t *o) { + char obname[BUFLEN]; + char lfname[BUFLEN]; + getlfname(lf,lfname); + getobname(o, obname, 1); + // slip! + if (isplayer(lf) || haslos(player, lf->cell)) { + msg("%s slip%s on %s.",lfname, isplayer(lf) ? "" : "s", obname); + } + taketime(lf, getactspeed(lf)); + // object moves? + if (hasflag(o->flags, F_SLIPMOVE)) { + cell_t *cur, *new; + cur = getoblocation(o); + new = getrandomadjcell(cur, WE_NOTSOLID); + if (new) { + if (haslos(player, cur) || haslos(player, new)) { + msg("%s slips across the floor.", obname); + } + moveob(o, new->obpile, 1); + } + } return B_FALSE; } @@ -5615,6 +6443,45 @@ void sortlf(map_t *map, lifeform_t *lf) { } } +int stone(lifeform_t *lf) { + char lfname[BUFLEN]; + char statname[BUFLEN]; + int failed = B_FALSE; + + // SAVING THROW ? + + getlfname(lf, lfname); + + // check for immune to stoning + switch (getlfmaterial(lf)) { + case MT_STONE: + case MT_GAS: + failed = B_TRUE; + break; + default: + break; + } + + if (failed) { + return B_TRUE; + } + + sprintf(statname, "statue of a %s", lf->race->name); + addob(lf->cell->obpile, statname); + + // kill lifeform + addflag(lf->flags, F_NODEATHANNOUNCE, B_TRUE, NA, NA, NULL); + addflag(lf->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL); + + if (haslos(player, lf->cell)) { + msg("%s %s to stone!", lfname, isplayer(lf) ? "turn" : "turns"); + } + setlastdam(lf, "petrification"); + die(lf); + return B_FALSE; +} + + void stopresting(lifeform_t *lf) { flag_t *f; // stop resting! @@ -5727,6 +6594,10 @@ void taketime(lifeform_t *lf, long howlong) { int db = B_FALSE; map_t *map; + if (lfhasflag(lf, F_NOTIME)) { + return; + } + if (isplayer(lf)) { statdirty = B_TRUE; } @@ -5825,9 +6696,11 @@ void timeeffectslf(lifeform_t *lf) { void turneffectslf(lifeform_t *lf) { int db = B_FALSE; map_t *map; + enum ERROR error; object_t *o; - flag_t *f; + flag_t *f, *nextf; char buf[BUFLEN]; + lifeform_t *l; int i; map = lf->cell->map; @@ -5843,12 +6716,14 @@ void turneffectslf(lifeform_t *lf) { } // stuck inside solid cells? - if (!cellwalkable(lf, lf->cell, NULL)) { - if (isplayer(lf)) { - msg("You reintegrate inside a solid object!"); + if (!cellwalkable(lf, lf->cell, &error)) { + if (error == E_WALLINWAY) { + if (isplayer(lf)) { + msg("You reintegrate inside a solid object!"); + } + losehp(lf, 9999, DT_DIRECT, NULL, "re-integration inside a solid object"); + //} } - losehp(lf, 9999, DT_DIRECT, NULL, "re-integration inside a solid object"); - //} } // regeneration @@ -5937,9 +6812,27 @@ void turneffectslf(lifeform_t *lf) { } } + + // gains/loses stench? + for (l = lf->cell->map->lf ; l ; l = l->next) { + if (!isdead(l) && (l != lf)) { + // TODO: race shoudl be "subspecies" + if (l->race->baseid != lf->race->baseid) { // can't smell your own race. + f = lfhasflag(l, F_STENCH); + if (f) { + int range,power; + range = f->val[0]; + power = f->val[1]; + if (getcelldist(l->cell, lf->cell) <= range) { + // you get nauseated + makenauseated(lf, power, 2); + } + } + } + } + } + // any potentiall damaging effects have to go after here... - - if (lfhasflag(lf, F_FROZEN)) { // melt... if (rnd(1,2)) { @@ -5965,18 +6858,61 @@ void turneffectslf(lifeform_t *lf) { getobname(o, buf, o->amt); dam = losehp(lf, dam, f->val[1], NULL, buf); if (dam > 0) { - if (isplayer(lf)) { - msg("%s %ss you!", buf, getattackverb(f->val[1], dam,lf->maxhp)); - } else if (haslos(player, lf->cell)) { - char lfname[BUFLEN]; - getlfname(lf, lfname); - msg("%s %ss %s!", buf, getattackverb(f->val[1], dam,lf->maxhp), lfname); + if (f->val[1] == DT_POISONGAS) { + if (isplayer(lf) || haslos(player, lf->cell)) { + char lfname[BUFLEN]; + getlfname(lf, lfname); + msg("%s choke%s on %s!", lfname, isplayer(lf) ? "" : "s", buf); + } + } else { + if (isplayer(lf)) { + msg("%s %ss you!", buf, getattackverb(f->val[1], dam,lf->maxhp)); + } else if (haslos(player, lf->cell)) { + char lfname[BUFLEN]; + getlfname(lf, lfname); + msg("%s %ss %s!", buf, getattackverb(f->val[1], dam,lf->maxhp), lfname); + } } } } } if (isdead(lf)) return; + for (f = lf->flags->first ; f ; f = nextf) { + nextf = f->next; + // remove impossible flags + if (f->id == F_GRABBEDBY) { + lifeform_t *lf2; + lf2 = findlf(NULL, f->val[0]); + if (!lf2) { + killflag(f); + continue; + } else if (getcelldist(lf2->cell, lf->cell) != 1) { + killflag(f); + continue; + } + } + if (f->id == F_GRABBING) { + lifeform_t *lf2; + lf2 = findlf(NULL, f->val[0]); + if (!lf2) { + killflag(f); + continue; + } else if (getcelldist(lf2->cell, lf->cell) != 1) { + killflag(f); + continue; + } + } + // recharge abilities + if (f->id == F_CANWILL) { + if (f->val[2] != NA) { + if (f->val[1] < f->val[2]) { + f->val[1]++; + } + } + } + } + } // returns B_TRUE if the action which involved touching this should fail @@ -6110,14 +7046,56 @@ int unweild(lifeform_t *lf, object_t *o) { return B_FALSE; } -int useability(lifeform_t *lf, enum OBTYPE aid) { +int useability(lifeform_t *lf, enum OBTYPE aid, lifeform_t *who, cell_t *where) { int rv; + if (!cancast(lf, aid, NULL)) { + if (isplayer(lf)) { + // announce + switch (reason) { + case E_NOTREADY: + msg("This ability is not recharged yet."); + break; + default: + msg("For some reason, you can't use this ability."); + break; + } + } + return B_TRUE; + } + // taketime() will happen during abiltiyeffects() // use the ability - rv = abilityeffects(lf, aid); + rv = abilityeffects(lf, aid, where, who); return rv; } +// returns B_FALSE if successful +int useitemwithflag(lifeform_t *lf, enum FLAG whichflag) { + object_t *o; + for (o = lf->pack->first ; o ; o = o->next) { + if (hasflag(o->flags, whichflag)) { + switch (o->type->obclass->id) { + case OC_POTION: + if (canquaff(lf, o)) { + quaff(lf, o); + return B_FALSE; + } + break; + case OC_SCROLL: + if (!readsomething(lf, o)) { + return B_FALSE; + } + break; + // TODO: if wand, use it on ourself + default: + break; + } + } + } + // failed to use an item + return B_TRUE; +} + int usestairs(lifeform_t *lf, object_t *o) { flag_t *f; map_t *curmap; @@ -6225,7 +7203,14 @@ int usestairs(lifeform_t *lf, object_t *o) { dblog("ERROR - can't find opposite end of stairs/portal!"); msg("ERROR - can't find opposite end of stairs/portal!"); } - drawscreen(); + + if (isplayer(lf)) { + statdirty = B_TRUE; + needredraw = B_TRUE; + calclight(player->cell->map); + precalclos(lf); + drawscreen(); + } return B_FALSE; } @@ -6233,12 +7218,21 @@ int usestairs(lifeform_t *lf, object_t *o) { int validateraces(void) { int goterror = B_FALSE; race_t *r; + flag_t *f; for (r = firstrace ; r ; r = r->next) { if (!hasflag(r->flags, F_SIZE)) { printf("ERROR in race '%s' - missing F_SIZE.", r->name); goterror = B_TRUE; } + for (f = r->flags->first ; f ; f = f->next) { + if (f->id == F_STARTOB) { + if (!f->text || (strlen(f->text) == 0)) { + printf("ERROR in race '%s' - F_STARTOB with zero length text.", r->name); + goterror = B_TRUE; + } + } + } } return goterror; } @@ -6254,66 +7248,71 @@ int rest(lifeform_t *lf, int onpurpose) { taketime(lf, getactspeed(lf)); - ff = lfhasflag(lf, F_RESTHEALAMT); - if (ff) { - hpheal = ff->val[0]; - } else { - hpheal = 1; - } - - ff = lfhasflag(lf, F_RESTHEALMPAMT); - if (ff) { - mpheal = ff->val[0]; - } else { - mpheal = 1; - } - - if (onpurpose) { - f = lfhasflag(lf, F_RESTCOUNT); - if (!f) { - f = addflag(lf->flags, F_RESTCOUNT, 0, NA, NA, NULL); - } - f->val[0]++; - f->lifetime = 2; - - ff = lfhasflag(lf, F_RESTHEALTIME); + if (!lfhasflag(lf, F_FOODPOISONED)) { + ff = lfhasflag(lf, F_RESTHEALAMT); if (ff) { - healtime = ff->val[0]; + hpheal = ff->val[0]; } else { - // 3 turns = heal 1 hp - healtime = 3; + hpheal = 1; } - if (f->val[0] >= healtime) { - //if (isplayer(lf)) msg("hp given."); - if (lf->hp < lf->maxhp) { - gainhp(lf, hpheal); - } + ff = lfhasflag(lf, F_RESTHEALMPAMT); + if (ff) { + mpheal = ff->val[0]; + } else { + mpheal = 1; + } - if (lf->mp < lf->maxmp) { - gainmp(lf, mpheal); + if (onpurpose) { + f = lfhasflag(lf, F_RESTCOUNT); + if (!f) { + f = addflag(lf->flags, F_RESTCOUNT, 0, NA, NA, NULL); } - /* - // heal mp too? - ff = lfhasflag(lf, F_RESTHEALMPAMT); + f->val[0]++; + f->lifetime = 2; + + ff = lfhasflag(lf, F_RESTHEALTIME); if (ff) { - if (lf->mp < lf->maxmp) { - gainmp(lf, ff->val[0]); + healtime = ff->val[0]; + } else { + // 3 turns = heal 1 hp + healtime = 3; + } + + if (f->val[0] >= healtime) { + //if (isplayer(lf)) msg("hp given."); + if (lf->hp < lf->maxhp) { + gainhp(lf, hpheal); } - } - */ - killflag(f); + if (lf->mp < lf->maxmp) { + gainmp(lf, mpheal); + } + /* + // heal mp too? + ff = lfhasflag(lf, F_RESTHEALMPAMT); + if (ff) { + if (lf->mp < lf->maxmp) { + gainmp(lf, ff->val[0]); + } + } + */ + killflag(f); + + } } - } - rf = lfhasflag(lf, F_RESTING); - if (rf) { - if ((lf->hp >= lf->maxhp) || !hpheal) { - if ((lf->mp >= lf->maxmp) || !mpheal) { - if (isplayer(lf)) msg("You finish resting."); - killflag(rf); + rf = lfhasflag(lf, F_RESTING); + if (rf) { + if ((lf->hp >= lf->maxhp) || !hpheal) { + if ((lf->mp >= lf->maxmp) || !mpheal) { + if (isplayer(lf)) { + msg("You finish resting."); + wantclearmsg = B_FALSE; + } + killflag(rf); + } } } } @@ -6755,6 +7754,44 @@ int weild(lifeform_t *lf, object_t *o) { // give flags giveobflags(lf, o, F_EQUIPCONFER); + // make certain flags known + if (isplayer(lf)) { + f = hasflag(o->flags, F_ARMOURPIERCE); + if (f) { + msg("Your %s seems unnaturally sharp!",noprefix(buf)); + f->known = B_TRUE; + } + } + + return B_FALSE; +} + +// will the lf flee after taking damage? +int willflee(lifeform_t *lf) { + enum IQBRACKET iqb; + flag_t *f; + + + if (hasflag(lf->flags, F_NOFLEE)) { + return B_FALSE; + } + + if (hasflag(lf->flags, F_FLEEONDAM)) { + return B_TRUE; + } + + iqb = getiqname(getattr(lf, A_IQ), NULL); + if ((iqb >= IQ_SMART) && isbleeding(lf)) { + return B_TRUE; + } + + f = hasflag(lf->flags, F_FLEEONHPPCT); + if (f) { + if (gethppct(lf) <= f->val[0]) { + return B_TRUE; + } + } + return B_FALSE; } diff --git a/lf.h b/lf.h index 989f95f..a17a49b 100644 --- a/lf.h +++ b/lf.h @@ -14,7 +14,6 @@ int calcxprace(enum RACE rid); int cancast(lifeform_t *lf, enum OBTYPE oid, int *mpcost); int caneat(lifeform_t *lf, object_t *o); int canhear(lifeform_t *lf, cell_t *c); -int cannotmove(lifeform_t *lf); int canpickup(lifeform_t *lf, object_t *o, int amt); int canpush(lifeform_t *lf, object_t *o, int dir); int canquaff(lifeform_t *lf, object_t *o); @@ -45,7 +44,6 @@ object_t *getarmour(lifeform_t *lf, enum BODYPART bp); int getarmourrating(lifeform_t *lf); int getattackspeed(lifeform_t *lf); int getattr(lifeform_t *lf, enum ATTRIB attr); -int getdexmod(lifeform_t *lf); int getevasion(lifeform_t *lf); object_t *getbestmissile(lifeform_t *lf); object_t *getbestweapon(lifeform_t *lf); @@ -59,6 +57,7 @@ lifeform_t *getguntarget(lifeform_t *lf); int getguntargetid(lifeform_t *lf); //int gethealtime(lifeform_t *lf); int gethearingrange(lifeform_t *lf); +int gethppct(lifeform_t *lf); enum HUNGER gethungerlevel(int hunger); char * gethungername(enum HUNGER hunger, char *buf); int gethungerval(lifeform_t *lf); @@ -68,6 +67,7 @@ enum LFCONDITION getlfcondition(lifeform_t *lf); int getnightvisrange(lifeform_t *lf); char *getlfconditionname(enum LFCONDITION cond); char *getseenlfconditionname(lifeform_t *lf, lifeform_t *viewer); +char getlfglyph(lifeform_t *lf); enum MATERIAL getlfmaterial(lifeform_t *lf); float getmaxcarryweight(lifeform_t *lf); float getmaxliftweight(lifeform_t *lf); @@ -119,6 +119,7 @@ enum BURDENED isburdened(lifeform_t *lf); int isdead(lifeform_t *lf); int isfleeing(lifeform_t *lf); int isfreebp(lifeform_t *lf, enum BODYPART bp); +int isfriendly(lifeform_t *lf); int isgenius(lifeform_t *lf); int isimmobile(lifeform_t *lf); flag_t *isimmuneto(flagpile_t *fp, enum DAMTYPE dt); @@ -133,7 +134,10 @@ void killlf(lifeform_t *lf); void killrace(race_t *race); int losehp(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *fromlf, char *damsrc); int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *fromlf, char *damsrc, int reducedam); +void makefriendly(lifeform_t *lf); +void makenauseated(lifeform_t *lf, int amt, int howlong); void makenoise(lifeform_t *lf, enum NOISETYPE nid); +lifeform_t *makezombie(object_t *o); void mayusespellschool(flagpile_t *fp, enum SPELLSCHOOL ss, enum FLAG how); int modattr(lifeform_t *lf, enum ATTRIB attr, int amt); void modhunger(lifeform_t *lf, int amt); @@ -148,7 +152,6 @@ int rolldex(enum DEXBRACKET bracket); int rolliq(enum IQBRACKET bracket); int rollstr(enum STRBRACKET bracket); int rollstat(lifeform_t *lf, enum ATTRIB attr); -int savingthrow(lifeform_t *lf, enum ATTRIB attr, int mod); int scare(lifeform_t *lf, lifeform_t *scarer, int howlong); int setammo(lifeform_t *lf, object_t *o); void setattr(lifeform_t *lf, enum ATTRIB attr, int val); @@ -156,7 +159,10 @@ void setguntarget(lifeform_t *lf, lifeform_t *targ); void setrace(lifeform_t *lf, enum RACE rid); void setlastdam(lifeform_t *lf, char *buf); int shoot(lifeform_t *lf); +int skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod); +int slipon(lifeform_t *lf, object_t *o); void sortlf(map_t *map, lifeform_t *lf); +int stone(lifeform_t *lf); void stopresting(lifeform_t *lf); void stoprunning(lifeform_t *lf); int testammo(lifeform_t *lf, object_t *o); @@ -167,9 +173,11 @@ void timeeffectslf(lifeform_t *lf); void turneffectslf(lifeform_t *lf); int touch(lifeform_t *lf, object_t *o); int unweild(lifeform_t *lf, object_t *o); -int useability(lifeform_t *lf, enum OBTYPE aid); +int useability(lifeform_t *lf, enum OBTYPE aid, lifeform_t *who, cell_t *where); +int useitemwithflag(lifeform_t *lf, enum FLAG whichflag); int usestairs(lifeform_t *lf, object_t *o); int validateraces(void); int wear(lifeform_t *lf, object_t *o); int weild(lifeform_t *lf, object_t *o); +int willflee(lifeform_t *lf); int youhear(cell_t *c, char *text); diff --git a/log.txt b/log.txt index 12c5bb6..3ce105c 100644 --- a/log.txt +++ b/log.txt @@ -2,23 +2,3024 @@ ====== NEW LOGFILE ==== -nclasses is 0 -nclasses is 0 -nclasses is 0 -initial dam[0] = 1 -adjusted for lf to dam[0] = 1 -reduced by armour to dam[0] = 1 -nclasses is 0 -nclasses is 0 -nclasses is 0 -nclasses is 0 -nclasses is 0 -nclasses is 1 -nclasses is 0 -initial dam[0] = 5 -adjusted for lf to dam[0] = 5 -reduced by armour to dam[0] = 4 -initial dam[0] = 5 -adjusted for lf to dam[0] = 5 -reduced by armour to dam[0] = 4 -nclasses is 0 +DB: called addobject() for wooden door, canstack = -1 +DB: Looking for object name 'wooden door' +checkobnames(): got exact match: 'wooden door' +DB: FOUND: ot->name = 'wooden door' +xxx +DB: setting canstack = false, objecttype 'wooden door' not stackable +DB: 'wooden door' -> adding 1 x wooden door +DB: Creating new object (wooden door). +DB: called addobject() for wooden door, canstack = -1 +DB: Looking for object name 'wooden door' +checkobnames(): got exact match: 'wooden door' +DB: FOUND: ot->name = 'wooden door' +xxx +DB: setting canstack = false, objecttype 'wooden door' not stackable +DB: 'wooden door' -> adding 1 x wooden door +DB: Creating new object (wooden door). +DB: called addobject() for wooden door, canstack = -1 +DB: Looking for object name 'wooden door' +checkobnames(): got exact match: 'wooden door' +DB: FOUND: ot->name = 'wooden door' +xxx +DB: setting canstack = false, objecttype 'wooden door' not stackable +DB: 'wooden door' -> adding 1 x wooden door +DB: Creating new object (wooden door). +DB: called addobject() for wooden door, canstack = -1 +DB: Looking for object name 'wooden door' +checkobnames(): got exact match: 'wooden door' +DB: FOUND: ot->name = 'wooden door' +xxx +DB: setting canstack = false, objecttype 'wooden door' not stackable +DB: 'wooden door' -> adding 1 x wooden door +DB: Creating new object (wooden door). +DB: called addobject() for wooden door, canstack = -1 +DB: Looking for object name 'wooden door' +checkobnames(): got exact match: 'wooden door' +DB: FOUND: ot->name = 'wooden door' +xxx +DB: setting canstack = false, objecttype 'wooden door' not stackable +DB: 'wooden door' -> adding 1 x wooden door +DB: Creating new object (wooden door). +DB: called addobject() for wooden door, canstack = -1 +DB: Looking for object name 'wooden door' +checkobnames(): got exact match: 'wooden door' +DB: FOUND: ot->name = 'wooden door' +xxx +DB: setting canstack = false, objecttype 'wooden door' not stackable +DB: 'wooden door' -> adding 1 x wooden door +DB: Creating new object (wooden door). +DB: called addobject() for wooden door, canstack = -1 +DB: Looking for object name 'wooden door' +checkobnames(): got exact match: 'wooden door' +DB: FOUND: ot->name = 'wooden door' +xxx +DB: setting canstack = false, objecttype 'wooden door' not stackable +DB: 'wooden door' -> adding 1 x wooden door +DB: Creating new object (wooden door). +DB: called addobject() for wooden door, canstack = -1 +DB: Looking for object name 'wooden door' +checkobnames(): got exact match: 'wooden door' +DB: FOUND: ot->name = 'wooden door' +xxx +DB: setting canstack = false, objecttype 'wooden door' not stackable +DB: 'wooden door' -> adding 1 x wooden door +DB: Creating new object (wooden door). +DB: called addobject() for staircase going up, canstack = -1 +DB: Looking for object name 'staircase going up' +checkobnames(): got exact match: 'staircase going up' +DB: FOUND: ot->name = 'staircase going up' +DB: setting canstack = false, objecttype 'staircase going up' not stackable +DB: 'staircase going up' -> adding 1 x staircase going up +DB: Creating new object (staircase going up). +DB: called addobject() for staircase going down, canstack = -1 +DB: Looking for object name 'staircase going down' +checkobnames(): got exact match: 'staircase going down' +DB: FOUND: ot->name = 'staircase going down' +DB: setting canstack = false, objecttype 'staircase going down' not stackable +DB: 'staircase going down' -> adding 1 x staircase going down +DB: Creating new object (staircase going down). +DB: called addobject() for 1 blessed +0 shield, canstack = -1 +DB: ob is blessed (blessed +0 shield) +DB: Looking for object name 'blessed +0 shield' +checkobnames(): got exact match: 'shield' +DB: FOUND: ot->name = 'shield' +DB: setting canstack = false, objecttype 'shield' not stackable +DB: '1 blessed +0 shield' -> adding 1 x shield +DB: Creating new object (shield). +DB: called addobject() for 1 +0 pair of overalls, canstack = -1 +DB: Looking for object name 'pair of overalls' +checkobnames(): got exact match: 'pair of overalls' +DB: FOUND: ot->name = 'pair of overalls' +DB: setting canstack = false, objecttype 'pair of overalls' not stackable +DB: '1 +0 pair of overalls' -> adding 1 x pair of overalls +DB: Creating new object (pair of overalls). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for buckler, canstack = -1 +DB: Looking for object name 'buckler' +checkobnames(): got exact match: 'buckler' +DB: FOUND: ot->name = 'buckler' +DB: setting canstack = false, objecttype 'buckler' not stackable +DB: 'buckler' -> adding 1 x buckler +DB: Creating new object (buckler). +DB: called addobject() for 1 +0 pair of sandals, canstack = -1 +DB: Looking for object name 'pair of sandals' +checkobnames(): got exact match: 'pair of sandals' +DB: FOUND: ot->name = 'pair of sandals' +DB: setting canstack = false, objecttype 'pair of sandals' not stackable +DB: '1 +0 pair of sandals' -> adding 1 x pair of sandals +DB: Creating new object (pair of sandals). +DB: called addobject() for 1 +0 gas mask, canstack = -1 +DB: Looking for object name 'gas mask' +checkobnames(): got exact match: 'gas mask' +DB: FOUND: ot->name = 'gas mask' +DB: setting canstack = false, objecttype 'gas mask' not stackable +DB: '1 +0 gas mask' -> adding 1 x gas mask +DB: Creating new object (gas mask). +DB: called addobject() for 1 potion of minor healing, canstack = -1 +DB: Looking for object name 'potion of minor healing' +checkobnames(): got exact match: 'potion of minor healing' +DB: FOUND: ot->name = 'potion of minor healing' +DB: '1 potion of minor healing' -> adding 1 x potion of minor healing +DB: Looking for stacks... +DB: No stacks found. +DB: Creating new object (potion of minor healing). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for club, canstack = -1 +DB: Looking for object name 'club' +checkobnames(): got exact match: 'club' +DB: FOUND: ot->name = 'club' +DB: setting canstack = false, objecttype 'club' not stackable +DB: 'club' -> adding 1 x club +DB: Creating new object (club). +DB: called addobject() for buckler, canstack = -1 +DB: Looking for object name 'buckler' +checkobnames(): got exact match: 'buckler' +DB: FOUND: ot->name = 'buckler' +DB: setting canstack = false, objecttype 'buckler' not stackable +DB: 'buckler' -> adding 1 x buckler +DB: Creating new object (buckler). +DB: called addobject() for fists, canstack = -1 +DB: Looking for object name 'fists' +checkobnames(): got exact match: 'fists' +DB: FOUND: ot->name = 'fists' +DB: setting canstack = false, objecttype 'fists' not stackable +DB: 'fists' -> adding 1 x fists +DB: Creating new object (fists). +DB: called addobject() for teeth, canstack = -1 +DB: Looking for object name 'teeth' +checkobnames(): got exact match: 'teeth' +DB: FOUND: ot->name = 'teeth' +DB: setting canstack = false, objecttype 'teeth' not stackable +DB: 'teeth' -> adding 1 x teeth +DB: Creating new object (teeth). +DB: called addobject() for fists, canstack = -1 +DB: Looking for object name 'fists' +checkobnames(): got exact match: 'fists' +DB: FOUND: ot->name = 'fists' +DB: setting canstack = false, objecttype 'fists' not stackable +DB: 'fists' -> adding 1 x fists +DB: Creating new object (fists). +DB: called addobject() for club, canstack = -1 +DB: Looking for object name 'club' +checkobnames(): got exact match: 'club' +DB: FOUND: ot->name = 'club' +DB: setting canstack = false, objecttype 'club' not stackable +DB: 'club' -> adding 1 x club +DB: Creating new object (club). +DB: called addobject() for 1 +0 knife, canstack = -1 +DB: Looking for object name 'knife' +checkobnames(): got exact match: 'knife' +DB: FOUND: ot->name = 'knife' +DB: setting canstack = false, objecttype 'knife' not stackable +DB: '1 +0 knife' -> adding 1 x knife +DB: Creating new object (knife). +DB: called addobject() for 1 potion of haste, canstack = -1 +DB: Looking for object name 'potion of haste' +checkobnames(): got exact match: 'potion of haste' +DB: FOUND: ot->name = 'potion of haste' +DB: '1 potion of haste' -> adding 1 x potion of haste +DB: Looking for stacks... +DB: No stacks found. +DB: Creating new object (potion of haste). +DB: called addobject() for leather armour, canstack = -1 +DB: Looking for object name 'leather armour' +checkobnames(): got exact match: 'leather armour' +DB: FOUND: ot->name = 'leather armour' +DB: setting canstack = false, objecttype 'leather armour' not stackable +DB: 'leather armour' -> adding 1 x leather armour +DB: Creating new object (leather armour). +DB: called addobject() for bone helmet, canstack = -1 +DB: Looking for object name 'bone helmet' +checkobnames(): got exact match: 'bone helmet' +DB: FOUND: ot->name = 'bone helmet' +DB: setting canstack = false, objecttype 'bone helmet' not stackable +DB: 'bone helmet' -> adding 1 x bone helmet +DB: Creating new object (bone helmet). +DB: called addobject() for 1 potion of healing, canstack = -1 +DB: Looking for object name 'potion of healing' +checkobnames(): got exact match: 'potion of healing' +DB: FOUND: ot->name = 'potion of healing' +DB: '1 potion of healing' -> adding 1 x potion of healing +DB: Looking for stacks... +DB: No stacks found. +DB: Creating new object (potion of healing). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for 1 potion of restoration, canstack = -1 +DB: Looking for object name 'potion of restoration' +checkobnames(): got exact match: 'potion of restoration' +DB: FOUND: ot->name = 'potion of restoration' +DB: '1 potion of restoration' -> adding 1 x potion of restoration +DB: Looking for stacks... +DB: No stacks found. +DB: Creating new object (potion of restoration). +DB: called addobject() for 1-5 darts, canstack = -1 +DB: Looking for object name 'darts' +checkobnames(): got match after stripping 's': 'dart' -> 'darts' +DB: FOUND: ot->name = 'dart' +DB: '1-5 darts' -> adding 2 x dart +DB: Looking for stacks... +DB: No stacks found. +DB: Creating new object (dart). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for 1 +0 dagger, canstack = -1 +DB: Looking for object name 'dagger' +checkobnames(): got exact match: 'dagger' +DB: FOUND: ot->name = 'dagger' +DB: setting canstack = false, objecttype 'dagger' not stackable +DB: '1 +0 dagger' -> adding 1 x dagger +DB: Creating new object (dagger). +DB: called addobject() for 1-5 darts, canstack = -1 +DB: Looking for object name 'darts' +checkobnames(): got match after stripping 's': 'dart' -> 'darts' +DB: FOUND: ot->name = 'dart' +DB: '1-5 darts' -> adding 5 x dart +DB: Looking for stacks... +DB: No stacks found. +DB: Creating new object (dart). +DB: called addobject() for buckler, canstack = -1 +DB: Looking for object name 'buckler' +checkobnames(): got exact match: 'buckler' +DB: FOUND: ot->name = 'buckler' +DB: setting canstack = false, objecttype 'buckler' not stackable +DB: 'buckler' -> adding 1 x buckler +DB: Creating new object (buckler). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for 1-5 darts, canstack = -1 +DB: Looking for object name 'darts' +checkobnames(): got match after stripping 's': 'dart' -> 'darts' +DB: FOUND: ot->name = 'dart' +DB: '1-5 darts' -> adding 2 x dart +DB: Looking for stacks... +DB: No stacks found. +DB: Creating new object (dart). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for 1 wand of opening, canstack = -1 +DB: Looking for object name 'wand of opening' +checkobnames(): got exact match: 'wand of opening' +DB: FOUND: ot->name = 'wand of opening' +DB: setting canstack = false, objecttype 'wand of opening' not stackable +DB: '1 wand of opening' -> adding 1 x wand of opening +DB: Creating new object (wand of opening). +DB: called addobject() for 1 +0 scythe, canstack = -1 +DB: Looking for object name 'scythe' +checkobnames(): got exact match: 'scythe' +DB: FOUND: ot->name = 'scythe' +DB: setting canstack = false, objecttype 'scythe' not stackable +DB: '1 +0 scythe' -> adding 1 x scythe +DB: Creating new object (scythe). +DB: called addobject() for leather boots, canstack = -1 +DB: Looking for object name 'leather boots' +DB: FOUND: ot->name = 'pair of leather boots' +DB: setting canstack = false, objecttype 'pair of leather boots' not stackable +DB: 'leather boots' -> adding 1 x pair of leather boots +DB: Creating new object (pair of leather boots). +DB: called addobject() for football helmet, canstack = -1 +DB: Looking for object name 'football helmet' +checkobnames(): got exact match: 'football helmet' +DB: FOUND: ot->name = 'football helmet' +DB: setting canstack = false, objecttype 'football helmet' not stackable +DB: 'football helmet' -> adding 1 x football helmet +DB: Creating new object (football helmet). +DB: called addobject() for 1-25 gold coins, canstack = -1 +DB: Looking for object name 'gold coins' +checkobnames(): got match after stripping 's': 'gold coin' -> 'gold coins' +DB: FOUND: ot->name = 'gold coin' +DB: '1-25 gold coins' -> adding 21 x gold coin +DB: Looking for stacks... +DB: No stacks found. +DB: Creating new object (gold coin). +DB: called addobject() for 1 blessed potion of haste, canstack = -1 +DB: ob is blessed (blessed potion of haste) +DB: Looking for object name 'blessed potion of haste' +checkobnames(): got exact match: 'potion of haste' +DB: FOUND: ot->name = 'potion of haste' +DB: '1 blessed potion of haste' -> adding 1 x potion of haste +DB: Looking for stacks... +DB: No stacks found. +DB: Creating new object (potion of haste). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for 1 bone, canstack = -1 +DB: Looking for object name 'bone' +checkobnames(): got exact match: 'bone' +DB: FOUND: ot->name = 'bone' +DB: '1 bone' -> adding 1 x bone +DB: Looking for stacks... +DB: No stacks found. +DB: Creating new object (bone). +DB: called addobject() for 1 potion of oil, canstack = -1 +DB: Looking for object name 'potion of oil' +checkobnames(): got exact match: 'potion of oil' +DB: FOUND: ot->name = 'potion of oil' +DB: '1 potion of oil' -> adding 1 x potion of oil +DB: Looking for stacks... +DB: No stacks found. +DB: Creating new object (potion of oil). +DB: called addobject() for 1 blessed +0 club, canstack = -1 +DB: ob is blessed (blessed +0 club) +DB: Looking for object name 'blessed +0 club' +checkobnames(): got exact match: 'club' +DB: FOUND: ot->name = 'club' +DB: setting canstack = false, objecttype 'club' not stackable +DB: '1 blessed +0 club' -> adding 1 x club +DB: Creating new object (club). +DB: called addobject() for 1 +0 gas mask, canstack = -1 +DB: Looking for object name 'gas mask' +checkobnames(): got exact match: 'gas mask' +DB: FOUND: ot->name = 'gas mask' +DB: setting canstack = false, objecttype 'gas mask' not stackable +DB: '1 +0 gas mask' -> adding 1 x gas mask +DB: Creating new object (gas mask). +DB: called addobject() for 1 potion of magic, canstack = -1 +DB: Looking for object name 'potion of magic' +checkobnames(): got exact match: 'potion of magic' +DB: FOUND: ot->name = 'potion of magic' +DB: '1 potion of magic' -> adding 1 x potion of magic +DB: Looking for stacks... +DB: No stacks found. +DB: Creating new object (potion of magic). +DB: called addobject() for club, canstack = -1 +DB: Looking for object name 'club' +checkobnames(): got exact match: 'club' +DB: FOUND: ot->name = 'club' +DB: setting canstack = false, objecttype 'club' not stackable +DB: 'club' -> adding 1 x club +DB: Creating new object (club). +DB: called addobject() for tail, canstack = -1 +DB: Looking for object name 'tail' +checkobnames(): got exact match: 'tail' +DB: FOUND: ot->name = 'tail' +DB: setting canstack = false, objecttype 'tail' not stackable +DB: 'tail' -> adding 1 x tail +DB: Creating new object (tail). +DB: called addobject() for 87 gold coins, canstack = -1 +DB: Looking for object name 'gold coins' +checkobnames(): got match after stripping 's': 'gold coin' -> 'gold coins' +DB: FOUND: ot->name = 'gold coin' +DB: '87 gold coins' -> adding 87 x gold coin +DB: Looking for stacks... +DB: No stacks found. +DB: Creating new object (gold coin). +DB: called addobject() for 1 blessed scroll of flame burst, canstack = -1 +DB: ob is blessed (blessed scroll of flame burst) +DB: Looking for object name 'blessed scroll of flame burst' +checkobnames(): got exact match: 'scroll of flame burst' +DB: FOUND: ot->name = 'scroll of flame burst' +DB: '1 blessed scroll of flame burst' -> adding 1 x scroll of flame burst +DB: Looking for stacks... +DB: No stacks found. +DB: Creating new object (scroll of flame burst). +DB: called addobject() for 1 blessed +0 heavy flail, canstack = -1 +DB: ob is blessed (blessed +0 heavy flail) +DB: Looking for object name 'blessed +0 heavy flail' +checkobnames(): got exact match: 'heavy flail' +DB: FOUND: ot->name = 'heavy flail' +DB: setting canstack = false, objecttype 'heavy flail' not stackable +DB: '1 blessed +0 heavy flail' -> adding 1 x heavy flail +DB: Creating new object (heavy flail). +DB: called addobject() for teeth, canstack = -1 +DB: Looking for object name 'teeth' +checkobnames(): got exact match: 'teeth' +DB: FOUND: ot->name = 'teeth' +DB: setting canstack = false, objecttype 'teeth' not stackable +DB: 'teeth' -> adding 1 x teeth +DB: Creating new object (teeth). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for 1 +0 steak knife, canstack = -1 +DB: Looking for object name 'steak knife' +checkobnames(): got exact match: 'steak knife' +DB: FOUND: ot->name = 'steak knife' +DB: setting canstack = false, objecttype 'steak knife' not stackable +DB: '1 +0 steak knife' -> adding 1 x steak knife +DB: Creating new object (steak knife). +DB: called addobject() for 1 potion of restoration, canstack = -1 +DB: Looking for object name 'potion of restoration' +checkobnames(): got exact match: 'potion of restoration' +DB: FOUND: ot->name = 'potion of restoration' +DB: '1 potion of restoration' -> adding 1 x potion of restoration +DB: Looking for stacks... +DB: No stacks found. +DB: Creating new object (potion of restoration). +DB: called addobject() for flak jacket, canstack = -1 +DB: Looking for object name 'flak jacket' +checkobnames(): got exact match: 'flak jacket' +DB: FOUND: ot->name = 'flak jacket' +DB: setting canstack = false, objecttype 'flak jacket' not stackable +DB: 'flak jacket' -> adding 1 x flak jacket +DB: Creating new object (flak jacket). +DB: called addobject() for 1 lockpick, canstack = -1 +DB: Looking for object name 'lockpick' +checkobnames(): got exact match: 'lockpick' +DB: FOUND: ot->name = 'lockpick' +DB: '1 lockpick' -> adding 1 x lockpick +DB: Looking for stacks... +DB: No stacks found. +DB: Creating new object (lockpick). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for 1 potion of water, canstack = -1 +DB: Looking for object name 'potion of water' +checkobnames(): got exact match: 'potion of water' +DB: FOUND: ot->name = 'potion of water' +DB: '1 potion of water' -> adding 1 x potion of water +DB: Looking for stacks... +DB: No stacks found. +DB: Creating new object (potion of water). +DB: called addobject() for leather armour, canstack = -1 +DB: Looking for object name 'leather armour' +checkobnames(): got exact match: 'leather armour' +DB: FOUND: ot->name = 'leather armour' +DB: setting canstack = false, objecttype 'leather armour' not stackable +DB: 'leather armour' -> adding 1 x leather armour +DB: Creating new object (leather armour). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for 1-3 javelins, canstack = -1 +DB: Looking for object name 'javelins' +checkobnames(): got match after stripping 's': 'javelin' -> 'javelins' +DB: FOUND: ot->name = 'javelin' +DB: '1-3 javelins' -> adding 3 x javelin +DB: Looking for stacks... +DB: No stacks found. +DB: Creating new object (javelin). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for 1 small puddle of water, canstack = -1 +DB: Looking for object name 'small puddle of water' +checkobnames(): got exact match: 'small puddle of water' +DB: FOUND: ot->name = 'small puddle of water' +DB: '1 small puddle of water' -> adding 1 x small puddle of water +DB: Looking for stacks... +DB: No stacks found. +DB: Creating new object (small puddle of water). +DB: called addobject() for club, canstack = -1 +DB: Looking for object name 'club' +checkobnames(): got exact match: 'club' +DB: FOUND: ot->name = 'club' +DB: setting canstack = false, objecttype 'club' not stackable +DB: 'club' -> adding 1 x club +DB: Creating new object (club). +DB: called addobject() for tail, canstack = -1 +DB: Looking for object name 'tail' +checkobnames(): got exact match: 'tail' +DB: FOUND: ot->name = 'tail' +DB: setting canstack = false, objecttype 'tail' not stackable +DB: 'tail' -> adding 1 x tail +DB: Creating new object (tail). +DB: called addobject() for teeth, canstack = -1 +DB: Looking for object name 'teeth' +checkobnames(): got exact match: 'teeth' +DB: FOUND: ot->name = 'teeth' +DB: setting canstack = false, objecttype 'teeth' not stackable +DB: 'teeth' -> adding 1 x teeth +DB: Creating new object (teeth). +DB: called addobject() for 1 cursed -1 pair of overalls, canstack = -1 +DB: ob is cursed (cursed -1 pair of overalls) +DB: Looking for object name 'cursed -1 pair of overalls' +checkobnames(): got exact match: 'pair of overalls' +DB: FOUND: ot->name = 'pair of overalls' +DB: setting canstack = false, objecttype 'pair of overalls' not stackable +DB: '1 cursed -1 pair of overalls' -> adding 1 x pair of overalls +DB: Creating new object (pair of overalls). +DB: called addobject() for 1 lockpick, canstack = -1 +DB: Looking for object name 'lockpick' +checkobnames(): got exact match: 'lockpick' +DB: FOUND: ot->name = 'lockpick' +DB: '1 lockpick' -> adding 1 x lockpick +DB: Looking for stacks... +DB: No stacks found. +DB: Creating new object (lockpick). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for 1 +0 pair of sandals, canstack = -1 +DB: Looking for object name 'pair of sandals' +checkobnames(): got exact match: 'pair of sandals' +DB: FOUND: ot->name = 'pair of sandals' +DB: setting canstack = false, objecttype 'pair of sandals' not stackable +DB: '1 +0 pair of sandals' -> adding 1 x pair of sandals +DB: Creating new object (pair of sandals). +DB: called addobject() for 1 cursed +0 gas mask, canstack = -1 +DB: ob is cursed (cursed +0 gas mask) +DB: Looking for object name 'cursed +0 gas mask' +checkobnames(): got exact match: 'gas mask' +DB: FOUND: ot->name = 'gas mask' +DB: setting canstack = false, objecttype 'gas mask' not stackable +DB: '1 cursed +0 gas mask' -> adding 1 x gas mask +DB: Creating new object (gas mask). +DB: called addobject() for 1 potion of restoration, canstack = -1 +DB: Looking for object name 'potion of restoration' +checkobnames(): got exact match: 'potion of restoration' +DB: FOUND: ot->name = 'potion of restoration' +DB: '1 potion of restoration' -> adding 1 x potion of restoration +DB: Looking for stacks... +DB: No stacks found. +DB: Creating new object (potion of restoration). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for acidattack, canstack = -1 +DB: Looking for object name 'acidattack' +checkobnames(): got exact match: 'acidattack' +DB: FOUND: ot->name = 'acidattack' +DB: setting canstack = false, objecttype 'acidattack' not stackable +DB: 'acidattack' -> adding 1 x acidattack +DB: Creating new object (acidattack). +DB: called addobject() for acidattack, canstack = -1 +DB: Looking for object name 'acidattack' +checkobnames(): got exact match: 'acidattack' +DB: FOUND: ot->name = 'acidattack' +DB: setting canstack = false, objecttype 'acidattack' not stackable +DB: 'acidattack' -> adding 1 x acidattack +DB: Creating new object (acidattack). +DB: called addobject() for fists, canstack = -1 +DB: Looking for object name 'fists' +checkobnames(): got exact match: 'fists' +DB: FOUND: ot->name = 'fists' +DB: setting canstack = false, objecttype 'fists' not stackable +DB: 'fists' -> adding 1 x fists +DB: Creating new object (fists). +givejob() starting. + +processing normal flag: 162 +processing normal flag: 213 +processing normal flag: 125 +processing normal flag: 125 +processing normal flag: 125 +processing normal flag: 125 +processing normal flag: 125 +processing normal flag: 125 +processing normal flag: 125 +processing normal flag: 125 +processing normal flag: 125 +processing normal flag: 125 +processing normal flag: 125 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 185 +processing normal flag: 185 +processing normal flag: 185 +processing normal flag: 185 +processing normal flag: 185 +processing normal flag: 185 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +processing normal flag: 184 +DB: called addobject() for short sword of pyromania, canstack = -1 +DB: Looking for object name 'short sword of pyromania' +checkobnames(): got exact match: 'short sword' +DB: FOUND: ot->name = 'short sword' +DB: setting canstack = false, objecttype 'short sword' not stackable +DB: 'short sword of pyromania' -> adding 1 x short sword +DB: Creating new object (short sword). +DB: called addobject() for hand of god, canstack = -1 +DB: Looking for object name 'hand of god' +checkobnames(): got exact match: 'hand of god' +DB: FOUND: ot->name = 'hand of god' +DB: setting canstack = false, objecttype 'hand of god' not stackable +DB: 'hand of god' -> adding 1 x hand of god +DB: Creating new object (hand of god). +DB: called addobject() for 10 blocks of chocolate, canstack = -1 +DB: Looking for object name 'blocks of chocolate' +checkobnames(): got exact match: 'block of chocolate' +DB: FOUND: ot->name = 'block of chocolate' +DB: '10 blocks of chocolate' -> adding 10 x block of chocolate +DB: Looking for stacks... +DB: No stacks found. +DB: Creating new object (block of chocolate). +DB: called addobject() for 10 vials of ambrosia, canstack = -1 +DB: Looking for object name 'vials of ambrosia' +checkobnames(): got exact match: 'vial of ambrosia' +DB: FOUND: ot->name = 'vial of ambrosia' +DB: '10 vials of ambrosia' -> adding 10 x vial of ambrosia +DB: Looking for stacks... +DB: No stacks found. +DB: Creating new object (vial of ambrosia). +DB: called addobject() for leather armour, canstack = -1 +DB: Looking for object name 'leather armour' +checkobnames(): got exact match: 'leather armour' +DB: FOUND: ot->name = 'leather armour' +DB: setting canstack = false, objecttype 'leather armour' not stackable +DB: 'leather armour' -> adding 1 x leather armour +DB: Creating new object (leather armour). +DB: called addobject() for leather boots, canstack = -1 +DB: Looking for object name 'leather boots' +DB: FOUND: ot->name = 'pair of leather boots' +DB: setting canstack = false, objecttype 'pair of leather boots' not stackable +DB: 'leather boots' -> adding 1 x pair of leather boots +DB: Creating new object (pair of leather boots). +DB: called addobject() for leather gloves, canstack = -1 +DB: Looking for object name 'leather gloves' +DB: FOUND: ot->name = 'pair of leather gloves' +DB: setting canstack = false, objecttype 'pair of leather gloves' not stackable +DB: 'leather gloves' -> adding 1 x pair of leather gloves +DB: Creating new object (pair of leather gloves). +DB: called addobject() for graph paper, canstack = -1 +DB: Looking for object name 'graph paper' +DB: FOUND: ot->name = 'piece of graph paper' +DB: 'graph paper' -> adding 1 x piece of graph paper +DB: Looking for stacks... +DB: No stacks found. +DB: Creating new object (piece of graph paper). +DB: called addobject() for a digital watch, canstack = -1 +DB: Looking for object name 'a digital watch' +checkobnames(): got exact match: 'digital watch' +DB: FOUND: ot->name = 'digital watch' +DB: setting canstack = false, objecttype 'digital watch' not stackable +DB: 'a digital watch' -> adding 1 x digital watch +DB: Creating new object (digital watch). +DB: called addobject() for 10 blessed scrolls of create monster, canstack = -1 +DB: ob is blessed (blessed scrolls of create monster) +DB: Looking for object name 'blessed scrolls of create monster' +checkobnames(): got exact match: 'scroll of create monster' +DB: FOUND: ot->name = 'scroll of create monster' +DB: '10 blessed scrolls of create monster' -> adding 10 x scroll of create monster +DB: Looking for stacks... +DB: No stacks found. +DB: Creating new object (scroll of create monster). +DB: called addobject() for ring of invulnerability, canstack = -1 +DB: Looking for object name 'ring of invulnerability' +checkobnames(): got exact match: 'ring of invulnerability' +DB: FOUND: ot->name = 'ring of invulnerability' +DB: setting canstack = false, objecttype 'ring of invulnerability' not stackable +DB: 'ring of invulnerability' -> adding 1 x ring of invulnerability +DB: Creating new object (ring of invulnerability). +DB: called addobject() for fists, canstack = -1 +DB: Looking for object name 'fists' +checkobnames(): got exact match: 'fists' +DB: FOUND: ot->name = 'fists' +DB: setting canstack = false, objecttype 'fists' not stackable +DB: 'fists' -> adding 1 x fists +DB: Creating new object (fists). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for teeth, canstack = -1 +DB: Looking for object name 'teeth' +checkobnames(): got exact match: 'teeth' +DB: FOUND: ot->name = 'teeth' +DB: setting canstack = false, objecttype 'teeth' not stackable +DB: 'teeth' -> adding 1 x teeth +DB: Creating new object (teeth). +DB: called addobject() for teeth, canstack = -1 +DB: Looking for object name 'teeth' +checkobnames(): got exact match: 'teeth' +DB: FOUND: ot->name = 'teeth' +DB: setting canstack = false, objecttype 'teeth' not stackable +DB: 'teeth' -> adding 1 x teeth +DB: Creating new object (teeth). +DB: called addobject() for tail, canstack = -1 +DB: Looking for object name 'tail' +checkobnames(): got exact match: 'tail' +DB: FOUND: ot->name = 'tail' +DB: setting canstack = false, objecttype 'tail' not stackable +DB: 'tail' -> adding 1 x tail +DB: Creating new object (tail). +DB: called addobject() for tail, canstack = -1 +DB: Looking for object name 'tail' +checkobnames(): got exact match: 'tail' +DB: FOUND: ot->name = 'tail' +DB: setting canstack = false, objecttype 'tail' not stackable +DB: 'tail' -> adding 1 x tail +DB: Creating new object (tail). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for teeth, canstack = -1 +DB: Looking for object name 'teeth' +checkobnames(): got exact match: 'teeth' +DB: FOUND: ot->name = 'teeth' +DB: setting canstack = false, objecttype 'teeth' not stackable +DB: 'teeth' -> adding 1 x teeth +DB: Creating new object (teeth). +DB: called addobject() for teeth, canstack = -1 +DB: Looking for object name 'teeth' +checkobnames(): got exact match: 'teeth' +DB: FOUND: ot->name = 'teeth' +DB: setting canstack = false, objecttype 'teeth' not stackable +DB: 'teeth' -> adding 1 x teeth +DB: Creating new object (teeth). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for teeth, canstack = -1 +DB: Looking for object name 'teeth' +checkobnames(): got exact match: 'teeth' +DB: FOUND: ot->name = 'teeth' +DB: setting canstack = false, objecttype 'teeth' not stackable +DB: 'teeth' -> adding 1 x teeth +DB: Creating new object (teeth). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for teeth, canstack = -1 +DB: Looking for object name 'teeth' +checkobnames(): got exact match: 'teeth' +DB: FOUND: ot->name = 'teeth' +DB: setting canstack = false, objecttype 'teeth' not stackable +DB: 'teeth' -> adding 1 x teeth +DB: Creating new object (teeth). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for teeth, canstack = -1 +DB: Looking for object name 'teeth' +checkobnames(): got exact match: 'teeth' +DB: FOUND: ot->name = 'teeth' +DB: setting canstack = false, objecttype 'teeth' not stackable +DB: 'teeth' -> adding 1 x teeth +DB: Creating new object (teeth). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for claws, canstack = -1 +DB: Looking for object name 'claws' +checkobnames(): got exact match: 'claws' +DB: FOUND: ot->name = 'claws' +DB: setting canstack = false, objecttype 'claws' not stackable +DB: 'claws' -> adding 1 x claws +DB: Creating new object (claws). +DB: called addobject() for acidattack, canstack = -1 +DB: Looking for object name 'acidattack' +checkobnames(): got exact match: 'acidattack' +DB: FOUND: ot->name = 'acidattack' +DB: setting canstack = false, objecttype 'acidattack' not stackable +DB: 'acidattack' -> adding 1 x acidattack +DB: Creating new object (acidattack). +DB: called addobject() for acidattack, canstack = -1 +DB: Looking for object name 'acidattack' +checkobnames(): got exact match: 'acidattack' +DB: FOUND: ot->name = 'acidattack' +DB: setting canstack = false, objecttype 'acidattack' not stackable +DB: 'acidattack' -> adding 1 x acidattack +DB: Creating new object (acidattack). +DB: called addobject() for acidattack, canstack = -1 +DB: Looking for object name 'acidattack' +checkobnames(): got exact match: 'acidattack' +DB: FOUND: ot->name = 'acidattack' +DB: setting canstack = false, objecttype 'acidattack' not stackable +DB: 'acidattack' -> adding 1 x acidattack +DB: Creating new object (acidattack). +DB: called addobject() for acidattack, canstack = -1 +DB: Looking for object name 'acidattack' +checkobnames(): got exact match: 'acidattack' +DB: FOUND: ot->name = 'acidattack' +DB: setting canstack = false, objecttype 'acidattack' not stackable +DB: 'acidattack' -> adding 1 x acidattack +DB: Creating new object (acidattack). diff --git a/map.c b/map.c index 6e798d7..5b88783 100644 --- a/map.c +++ b/map.c @@ -31,7 +31,7 @@ cell_t *addcell(map_t *m, int x, int y) { cell->obpile = addobpile(NOOWNER, cell); cell->lf = NULL; cell->roomid = -1; - cell->lit = B_FALSE; + cell->lit = L_NOTLIT; cell->writing = NULL; cell->known = B_FALSE; return cell; @@ -73,7 +73,7 @@ map_t *addmap(void) { } -lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok) { +lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt) { lifeform_t *lf = NULL; race_t *r; int db = B_FALSE; @@ -96,7 +96,6 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok) { //lf = addlf(c, r->id, getrandommonlevel(c->map->depth)); lf = addlf(c, r->id, 1); if (lf) { - int amt; flag_t *f; if (jobok) { @@ -112,23 +111,41 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok) { // appears in groups? f = hasflag(lf->flags, F_NUMAPPEAR); if (f) { + // override amount amt = rnd(f->val[0], f->val[1]); - } else { - amt = 1; } if (amt > 1) { cell_t *adjcell; + cell_t **moncell; + int nmoncells = 1; + + moncell = malloc( amt * sizeof(cell_t *)); + moncell[0] = c; + nmoncells = 1; amt--; // we've already added one - adjcell = c; + + //adjcell = c; for ( ; amt > 0; amt--) { - // add more in adjacent cells - adjcell = getrandomadjcell(adjcell, WE_NOTSOLID); + int n; + // find an adjacent cell to one of the newly added monsters, + // starting with the first one + adjcell = NULL; + for (n = 0; n < nmoncells; n++) { + adjcell = getrandomadjcell(moncell[n], WE_NOTSOLID); + if (adjcell) break; + } + // did we find one? if (!adjcell) break; //lf = addlf(adjcell, r->id, getrandommonlevel(adjcell->map->depth)); - lf = addlf(adjcell, r->id, 1); - if (!lf) break; + if (!addlf(adjcell, r->id, 1)) { + break; + } + + moncell[nmoncells] = adjcell; + nmoncells++; } + free(moncell); } } } @@ -157,7 +174,7 @@ void addrandomthing(cell_t *c) { addrandomob(c); } else { // monster - addmonster(c, R_RANDOM, B_TRUE); + addmonster(c, R_RANDOM, B_TRUE, 1); } } @@ -341,7 +358,7 @@ void calclight(map_t *map) { for (y = 0; y < map->h; y++) { for (x = 0; x < map->w; x++) { c = getcellat(map, x,y); - if (c && (c->lit != B_PERM)) c->lit = B_FALSE; + if (c && (c->lit == L_PERM) && (c->lit != L_DARK)) c->lit = B_FALSE; } } for (y = 0; y < map->h; y++) { @@ -351,22 +368,22 @@ void calclight(map_t *map) { int radius; object_t *o; // lit based on depth - if (map->depth <= 5) { - c->lit = B_PERM; + if ((map->depth <= 5) && (c->lit != L_DARK)) { + c->lit = L_PERM; } // has lightproducing lf? (ie.hasflag f_produceslight) if (c->lf) { if (lfhasflag(c->lf, F_PRODUCESLIGHT)) { sumflags(c->lf->flags, F_PRODUCESLIGHT, &radius, NULL, NULL); - makelitradius(c, radius, B_TEMP); + makelitradius(c, radius, L_TEMP); } // objects in hands or on body... for (o = c->lf->pack->first ; o ; o = o->next) { if (obproduceslight(o) && isequipped(o)) { sumflags(o->flags, F_PRODUCESLIGHT, &radius, NULL, NULL); - makelitradius(c, radius, B_TEMP); + makelitradius(c, radius, L_TEMP); } } } @@ -374,7 +391,7 @@ void calclight(map_t *map) { for (o = c->obpile->first ; o ; o = o->next) { if (obproduceslight(o)) { sumflags(o->flags, F_PRODUCESLIGHT, &radius, NULL, NULL); - makelitradius(c, radius, B_TEMP); + makelitradius(c, radius, L_TEMP); } } @@ -404,10 +421,19 @@ int calcroompos(map_t *map, int w, int h, int *bx, int *by) { for (ry = y; (ry < y+h) && (!notpossible); ry++) { for (rx = x; (rx < x+w) && (!notpossible); rx++) { cell = getcellat(map, rx,ry); - // is this cell adjacent to an empty cell? + // is this cell adjacent to an empty cell and not a + // corner (ie. a valid door location) if (countcellexits(cell)) { score++; - valid = B_TRUE; + if ( ((ry == y) && (rx == x)) || + ((ry == y) && (rx == (x+w-1))) || + ((ry == y+h-1) && (rx == x)) || + ((ry == y+h-1) && (rx == (x+w-1))) ) { + // corner. + } else { + // not corner + valid = B_TRUE; + } } // is this cell empty itself? if (!cell->type->solid) score += 3; @@ -1235,7 +1261,7 @@ void createroom(map_t *map, int minx, int miny, int w, int h, int roomid) { // N npossible = 0; y = miny; - for (x = minx; x <= maxx; x++) { + for (x = minx+1; x <= maxx-1; x++) { cell = getcellat(map, x, y); newcell = getcellindir(cell, D_N); if (newcell && !newcell->type->solid) { @@ -1267,7 +1293,7 @@ void createroom(map_t *map, int minx, int miny, int w, int h, int roomid) { // S npossible = 0; y = maxy; - for (x = minx; x <= maxx; x++) { + for (x = minx+1; x <= maxx-1; x++) { cell = getcellat(map, x, y); newcell = getcellindir(cell, D_S); if (newcell && !newcell->type->solid) { @@ -1299,7 +1325,7 @@ void createroom(map_t *map, int minx, int miny, int w, int h, int roomid) { // W npossible = 0; x = minx; - for (y = miny; y <= maxy; y++) { + for (y = miny+1; y <= maxy-1; y++) { cell = getcellat(map, x, y); newcell = getcellindir(cell, D_W); if (newcell && !newcell->type->solid) { @@ -1329,7 +1355,7 @@ void createroom(map_t *map, int minx, int miny, int w, int h, int roomid) { // E npossible = 0; x = maxx; - for (y = miny; y <= maxy; y++) { + for (y = miny+1; y <= maxy-1; y++) { cell = getcellat(map, x, y); newcell = getcellindir(cell, D_E); if (newcell && !newcell->type->solid) { @@ -1793,6 +1819,25 @@ cell_t *getrandomroomcell(map_t *map, int roomid) { return c; } +// returns how slippery this cell is +int getslipperyness(cell_t *c, object_t **slipob) { + object_t *o; + int totalslip = 0; + if (slipob) *slipob = NULL; + for (o = c->obpile->first ; o ; o = o->next) { + int thisslip; + sumflags(o->flags, F_SLIPPERY, &thisslip, NULL, NULL); + if (thisslip > 0) { + if (slipob && (*slipob == NULL)) { + *slipob = o; + } + } + thisslip *= o->amt; + totalslip += thisslip; + } + return totalslip; +} + object_t *hasenterableobject(cell_t *c) { return hasobwithflag(c->obpile, F_CLIMBABLE); } @@ -1872,31 +1917,7 @@ int isinscanrange(cell_t *c, void **thing, char *desc, char *glyph) { } if (glyph) { // select glyph based on size - switch(getlfsize(c->lf)) { - case SZ_ENORMOUS: - *glyph = '6'; - break; - case SZ_HUGE: - *glyph = '5'; - break; - case SZ_LARGE: - *glyph = '4'; - break; - case SZ_HUMAN: - *glyph = '3'; - break; - case SZ_MEDIUM: - *glyph = '2'; - break; - case SZ_SMALL: - *glyph = '1'; - break; - case SZ_MINI: - case SZ_TINY: - default: - *glyph = '0'; - break; - } + *glyph = '0' + ((int) getlfsize(c->lf)); } return TT_MONSTER; } @@ -1928,8 +1949,12 @@ int isinscanrange(cell_t *c, void **thing, char *desc, char *glyph) { } int islit(cell_t *c) { - if (c->lit) { - return B_TRUE; + switch (c->lit) { + case L_TEMP: + case L_PERM: + return B_TRUE; + default: + break; } return B_FALSE; } @@ -2009,16 +2034,16 @@ void makedoor(cell_t *cell) { } -void makelit(cell_t *c, int how) { - if (how == B_FALSE) { - c->lit = how; - } else if (c->lit != B_PERM) { // don't override permenant light with temp light! +void makelit(cell_t *c, enum LIGHTLEV how) { + // don't override permenant light with temp light! + if ((c->lit == L_PERM) && (how == L_TEMP)) { + return; + } else { c->lit = how; } - } -void makelitradius(cell_t *c, int radius, int how) { +void makelitradius(cell_t *c, int radius, enum LIGHTLEV how) { int x,y; cell_t *c2; diff --git a/map.h b/map.h index 2d7c179..b65273a 100644 --- a/map.h +++ b/map.h @@ -2,7 +2,7 @@ cell_t *addcell(map_t *map, int x, int y); map_t *addmap(void); -lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok); +lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt); void addrandomob(cell_t *c); void addrandomthing(cell_t *c); int cellhaslos(cell_t *c1, cell_t *dest); @@ -35,6 +35,7 @@ cell_t *getrandomcell(map_t *map); cell_t *getrandomcelloftype(map_t *map, int id); int getrandomdir(int dirtype); cell_t *getrandomroomcell(map_t *map, int roomid); +int getslipperyness(cell_t *c, object_t **slipob); object_t *hasenterableobject(cell_t *c); lifeform_t *haslf(cell_t *c); int hasobject(cell_t *c); @@ -49,7 +50,7 @@ int isnewcellok(cell_t *cell, char *err); int isonmap(map_t *map, int x, int y); int iswallindir(cell_t *cell, int dir); void makedoor(cell_t *cell); -void makelit(cell_t *c, int how); -void makelitradius(cell_t *c, int radius, int how); +void makelit(cell_t *c, enum LIGHTLEV how); +void makelitradius(cell_t *c, int radius, enum LIGHTLEV how); void setcelltype(cell_t *cell, int id); void updateknowncells(void); diff --git a/move.c b/move.c index 2d164e8..220edeb 100644 --- a/move.c +++ b/move.c @@ -36,6 +36,7 @@ int canandwillmove(lifeform_t *lf, int dir, enum ERROR *error) { int canmove(lifeform_t *lf, int dir, enum ERROR *error) { cell_t *cell; + flag_t *f; // default if (error) { @@ -53,9 +54,27 @@ int canmove(lifeform_t *lf, int dir, enum ERROR *error) { return B_FALSE; } - // TODO: check if we are burdened, paralyzed, etc + // check if we are paralyzed, frozen, etc + if (isimmobile(lf)) { + if (error) *error = E_CANTMOVE; + return B_FALSE; + } + cell = getcellindir(lf->cell, dir); + f = lfhasflag(lf, F_GRABBEDBY); + if (f) { + lifeform_t *lf2; + lf2 = findlf(NULL, f->val[0]); + if (lf2 && (lf2 != cell->lf)) { + if (error) { + rdata = lf2; + *error = E_GRABBEDBY; + } + return B_FALSE; + } + } + return cellwalkable(lf, cell, error); } @@ -69,9 +88,9 @@ int celldangerous(lifeform_t *lf, cell_t *cell, enum ERROR *error) { rdata = NULL; } - // check for dangerous objects + // check for _known_ dangerous objects iq = getiqname(getattr(lf, A_IQ), NULL); - if (iq >= IQ_AVERAGE) { + if ((iq >= IQ_AVERAGE) && !isblind(lf)) { flag_t *f; object_t *o; for (o = cell->obpile->first ; o ; o = o->next) { @@ -120,9 +139,16 @@ int cellwalkable(lifeform_t *lf, cell_t *cell, enum ERROR *error) { return B_FALSE; } } + + // must check for lf before checking for impassable objects, + // so that we are able to attack monsters embedded in walls. + if (cell->lf && (cell->lf != lf)) { + if (error) *error = E_LFINWAY; + return B_FALSE; + } for (o = cell->obpile->first ; o ; o = o->next) { - if (hasflag(o->flags, F_IMPASSABLE)) { + if (isimpassableob(o, lf)) { if (lf) { if ((lf->race->material->id == MT_GAS) || (lf->race->material->id == MT_SLIME)) { @@ -142,13 +168,40 @@ int cellwalkable(lifeform_t *lf, cell_t *cell, enum ERROR *error) { } } - if (cell->lf && (cell->lf != lf)) { - if (error) *error = E_LFINWAY; - return B_FALSE; - } return B_TRUE; } +int diropposite(int dir) { + switch (dir) { + case D_N: + return D_S; + case D_E: + return D_W; + case D_S: + return D_N; + case D_W: + return D_E; + case DC_N: + return DC_S; + case DC_NE: + return DC_SW; + case DC_E: + return DC_W; + case DC_SE: + return DC_NW; + case DC_S: + return DC_N; + case DC_SW: + return DC_NE; + case DC_W: + return DC_E; + case DC_NW: + return DC_SE; + } + // should never happen! + return dir; +} + void dorandommove(lifeform_t *lf, int badmovesok) { int dir; int tries = 0; @@ -226,7 +279,7 @@ int getdiraway(cell_t *src, cell_t *dst, int wantcheck) { } } if (ok) { - thisdist = getcelldist(c, dst); + thisdist = getcelldistorth(c, dst); } else { thisdist = -1; } @@ -239,12 +292,14 @@ int getdiraway(cell_t *src, cell_t *dst, int wantcheck) { } // TODO: handle ties - + if (bestdir != D_NONE) { + reason = E_OK; + } return bestdir; } -int getdirtowards(cell_t *src, cell_t *dst, int wantcheck) { +int getdirtowards(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck) { int d; cell_t *c; int mindist=9999,bestdir=D_NONE; @@ -260,21 +315,21 @@ int getdirtowards(cell_t *src, cell_t *dst, int wantcheck) { } if (wantcheck) { - if (src->lf && canandwillmove(src->lf, d, NULL)) { + if (srclf && canandwillmove(srclf, d, NULL)) { ok = B_TRUE; - } else if (!src->lf) { + } else if (!srclf) { ok = B_TRUE; } } else { - if (src->lf && cellwalkable(src->lf, c, NULL)) { + if (srclf && cellwalkable(srclf, c, NULL)) { ok = B_TRUE; - } else if (!src->lf) { + } else if (!srclf) { ok = B_TRUE; } } if (ok) { int thisdist; - thisdist = getcelldist(c, dst); + thisdist = getcelldistorth(c, dst); if (thisdist < mindist) { mindist = thisdist; bestdir = d; @@ -287,13 +342,66 @@ int getdirtowards(cell_t *src, cell_t *dst, int wantcheck) { return bestdir; } +int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher) { + int i; + char lfname[BUFLEN]; + int seen; -int moveawayfrom(lifeform_t *lf, cell_t *dst) { + getlfname(lf,lfname); + if (haslos(player, lf->cell)) { + seen = B_TRUE; + } else { + seen = B_FALSE; + } + + if (dir == D_NONE) { + // failed! + return B_TRUE; + } + + // if levitating (not flying), knocked back further. + if (lfhasflag(lf, F_LEVITATING)) { + howfar *= 2; + } + + for (i = 0; i < howfar; i++) { + if (canmove(lf, dir, &reason)) { + if ((i == 0) && seen) { + msg("%s %s knocked backwards!",lfname,isplayer(lf) ? "are" : "is"); + } + trymove(lf, dir); + } + if (reason != E_OK) { + // failed to move + switch (reason) { + case E_WALLINWAY: + msg("%s slam%s into a wall!",lfname,isplayer(lf) ? "" : "s"); + losehp(lf, rnd(1,6), DT_BASH, pusher, "slamming into a wall"); + // stop moving + i = howfar; + break; + default: + break; + } + } + } + return B_FALSE; +} + +int moveawayfrom(lifeform_t *lf, cell_t *dst ) { int dir; int rv = B_TRUE; + + if (isblind(lf)) { + dorandommove(lf, B_TRUE); + return B_FALSE; + } + // move towards them dir = getdiraway(lf->cell, dst, B_TRUE); - if (dir != D_NONE) { + if (dir == D_NONE) { + rv = B_TRUE; + } else { rv = trymove(lf, dir); } return rv; @@ -310,6 +418,8 @@ int movelf(lifeform_t *lf, cell_t *newcell) { int didmsg = B_FALSE; flag_t *f; + getlfname(lf, lfname); + // update current cell lf->cell->lf = NULL; @@ -335,6 +445,14 @@ int movelf(lifeform_t *lf, cell_t *newcell) { bleed(lf); } } + if (lfhasflag(lf, F_PAIN)) { + losehp(lf, rolldie(2,4)+2, DT_DIRECT, NULL, "extreme pain"); + if (isplayer(lf)) { + msg("Your body is wracked with pain!"); + } else if (haslos(player, lf->cell)) { + msg("%s convulses in pain!",lfname); + } + } // check ground objects @@ -346,39 +464,13 @@ int movelf(lifeform_t *lf, cell_t *newcell) { object_t *boots; // has boots on? boots = getequippedob(lf->pack, BP_FEET); - if (boots) { - // crunch the broken glass - getobname(o, obname, 1); - - 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 (lf->controller == C_PLAYER) { - msg("You crush %s underfoot.",obname); - didmsg = B_TRUE; - } else if (haslos(player, newcell)) { - getlfname(lf, lfname); - capitalise(lfname); - msg("%s crushes %s.",lfname, obname); - didmsg = B_TRUE; - } - // kill object - removeob(o, o->amt); - } else { + if (!boots) { // take damage getobname(o, obname, 1); if (lf->controller == C_PLAYER) { msg("Ow - you step on %s!",obname); didmsg = B_TRUE; } else if (haslos(player, newcell)) { - getlfname(lf, lfname); - capitalise(lfname); msg("%s steps on %s!",lfname, obname); didmsg = B_TRUE; } @@ -386,6 +478,40 @@ int movelf(lifeform_t *lf, cell_t *newcell) { losehp(lf, rnd(f->val[0],f->val[1]), DT_SLASH, NULL, buf); } } + + f = hasflag(o->flags, F_CRUSHABLE); + if (f) { + enum LFSIZE crushsize; + crushsize = f->val[0]; + + 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); + } + } + + 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 + removeob(o, o->amt); + } + } // end if crushable } // end foreach object in cell } // end if !flying @@ -434,7 +560,7 @@ int moveto(lifeform_t *lf, cell_t *newcell) { object_t *o; char obname[BUFLEN]; for (o = newcell->obpile->first ; o ; o = o->next) { - if (hasflag(o->flags, F_IMPASSABLE)) { + if (isimpassableob(o, lf)) { getobname(o, obname, o->amt); if (isplayer(lf)) { msg("You seep around %s.", obname); @@ -447,7 +573,7 @@ int moveto(lifeform_t *lf, cell_t *newcell) { object_t *o; char obname[BUFLEN]; for (o = newcell->obpile->first ; o ; o = o->next) { - if (hasflag(o->flags, F_IMPASSABLE)) { + if (isimpassableob(o, lf)) { getobname(o, obname, o->amt); if (isplayer(lf)) { msg("You seep under %s.", obname); @@ -476,8 +602,14 @@ int moveto(lifeform_t *lf, cell_t *newcell) { int movetowards(lifeform_t *lf, cell_t *dst) { int dir; int rv = B_TRUE; + + if (isblind(lf)) { + dorandommove(lf, B_TRUE); + return B_FALSE; + } + // move towards them - dir = getdirtowards(lf->cell, dst, B_TRUE); + dir = getdirtowards(lf->cell, dst, lf, B_TRUE); if (dir != D_NONE) { rv = trymove(lf, dir); } @@ -606,8 +738,11 @@ int closedoor(lifeform_t *lf, object_t *o) { cell_t *cell; char buf[BUFLEN]; char obname[BUFLEN]; + object_t *oo; flag_t *f; + cell = getoblocation(o); + getobname(o, obname, 1); if (!isdoor(o, NULL)) { @@ -624,6 +759,29 @@ int closedoor(lifeform_t *lf, object_t *o) { return B_TRUE; } + if (cell->lf) { + if (lf && isplayer(lf)) { + char inwayname[BUFLEN]; + getlfname(cell->lf, inwayname); + msg("%s is in the way!", haslos(lf, cell) ? inwayname : "Something"); + } + return B_TRUE; + } + + // impassable object other than the door? + for (oo = cell->obpile->first ; oo ; oo = oo->next) { + if (oo != o) { + if (hasflag(oo->flags, F_IMPASSABLE)) { + if (lf && isplayer(lf)) { + char inwayname[BUFLEN]; + getobname(oo, inwayname, oo->amt); + msg("%s is in the way!", haslos(lf, cell) ? inwayname : "Something"); + } + return B_TRUE; + } + } + } + f = hasflag(o->flags, F_OPEN); if (!f) { if (lf && (lf->controller == C_PLAYER)) { @@ -672,7 +830,7 @@ int pullnextto(lifeform_t *lf, cell_t *c) { dst = c; while (dst->lf) { - dir = getdirtowards(dst, lf->cell, B_FALSE); + dir = getdirtowards(dst, lf->cell, lf, B_FALSE); if (dir == D_NONE) { return B_TRUE; } else { @@ -701,6 +859,15 @@ int pullnextto(lifeform_t *lf, cell_t *c) { // teleport somewhere, along with puffs of smoke etc int teleportto(lifeform_t *lf, cell_t *c) { char buf[BUFLEN]; + + // can't teleport on top of something else + if (c->lf) { + if (isplayer(lf)) { + msg("You feel a wrenching sensation."); + } + return B_TRUE; + } + if (!isplayer(lf) && haslos(player, lf->cell)) { getlfname(lf, buf); msg("%s disappears in a cloud of smoke!", buf); @@ -731,7 +898,8 @@ int trymove(lifeform_t *lf, int dir) { cell = getcellindir(lf->cell, dir); if (canandwillmove(lf, dir, &errcode)) { - object_t *o; + object_t *o,*slipob; + int slip; // check for cursed objects + animals for (o = cell->obpile->first ; o ; o = o->next) { @@ -743,12 +911,11 @@ int trymove(lifeform_t *lf, int dir) { char lfname[BUFLEN]; getlfname(lf,lfname); getobname(o, buf, o->amt); - msg("%s shies away from %s!", lfname, buf); + msg("%s %s away from %s!", lfname, isplayer(lf) ? "shy" : "shies", buf); o->blessknown = B_TRUE; - - taketime(lf, getmovespeed(lf)); - reason = E_OK; } + taketime(lf, getmovespeed(lf)); + reason = E_OK; return B_FALSE; } } @@ -756,9 +923,28 @@ int trymove(lifeform_t *lf, int dir) { } } + // slipping on blood before moving? + slip = getslipperyness(lf->cell, &slipob); + if (slip && !skillcheck(lf, SC_SLIP, slip, 0)) { + slipon(lf, slipob); + // don't move + reason = E_OK; + return B_FALSE; + } + + // move to new cell reason = E_OK; moveto(lf, cell); taketime(lf, getmovespeed(lf)); + + // slip on blood in new cell? + slip = getslipperyness(cell, &slipob); + if (slip && !skillcheck(lf, SC_SLIP, slip, 0)) { + slipon(lf, slipob); + // don't move + reason = E_OK; + return B_FALSE; + } } else { object_t *inway; int door, dooropen; @@ -855,18 +1041,39 @@ int trymove(lifeform_t *lf, int dir) { case E_LFINWAY: // attack! return attacklf(lf, cell->lf); - break; case E_GRAVBOOSTED: if (isplayer(lf)) { msg("You try to move but are unable to lift your feet!"); - taketime(lf, getmovespeed(lf)); + } else if (haslos(player, lf->cell)) { + char lfname[BUFLEN]; + getlfname(lf, lfname); + msg("%s tries to move but is unable to lift its feet!",lfname); } + taketime(lf, getmovespeed(lf)); + break; + case E_CANTMOVE: + if (isplayer(lf)) { + msg("You cannot move!"); + } + taketime(lf, getmovespeed(lf)); + break; + case E_GRABBEDBY: + if (isplayer(lf)) { + char lfname[BUFLEN]; + if (rdata) { + getlfname((lifeform_t *)rdata, lfname); + } else { + sprintf(lfname, "whatever is holding you"); + } + msg("You cannot get away from %s!",lfname); + } + taketime(lf, getmovespeed(lf)); break; case E_TOOHEAVY: if (isplayer(lf)) { msg("Your load is too heavy to move with!"); - taketime(lf, getmovespeed(lf)); } + taketime(lf, getmovespeed(lf)); break; default: break; @@ -895,6 +1102,15 @@ int willmove(lifeform_t *lf, int dir, enum ERROR *error) { if (celldangerous(lf, cell, error)) { return B_FALSE; } + + // don't attack other monsters + if (cell->lf) { + if (!isplayer(lf)) { + if (!isplayer(cell->lf) && !isfriendly(cell->lf)) { + return B_FALSE; + } + } + } return B_TRUE; } diff --git a/move.h b/move.h index 245b286..cf24f67 100644 --- a/move.h +++ b/move.h @@ -6,9 +6,11 @@ int celldangerous(lifeform_t *lf, cell_t *cell, enum ERROR *error); int cellwalkable(lifeform_t *lf, cell_t *cell, enum ERROR *error); int closedoorat(lifeform_t *lf, cell_t *c); int closedoor(lifeform_t *lf, object_t *o); +int diropposite(int dir); void dorandommove(lifeform_t *lf, int badmovesok); int getdiraway(cell_t *src, cell_t *dst, int wantcheck); -int getdirtowards(cell_t *src, cell_t *dst, int wantcheck); +int getdirtowards(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck); +int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher); int moveawayfrom(lifeform_t *lf, cell_t *dst); int movelf(lifeform_t *lf, cell_t *newcell); int moveto(lifeform_t *lf, cell_t *newcell); diff --git a/nexus.c b/nexus.c index 6fef69f..bddd874 100644 --- a/nexus.c +++ b/nexus.c @@ -21,6 +21,7 @@ objectclass_t *objectclass = NULL,*lastobjectclass = NULL; objecttype_t *objecttype = NULL,*lastobjecttype = NULL; obmod_t *firstobmod = NULL,*lastobmod = NULL; celltype_t *firstcelltype = NULL,*lastcelltype = NULL; +command_t *firstcommand = NULL,*lastcommand = NULL; race_t *firstrace = NULL,*lastrace = NULL; job_t *firstjob = NULL,*lastjob = NULL; map_t *firstmap = NULL,*lastmap = NULL; @@ -144,7 +145,6 @@ int main(int argc, char **argv) { more(); } - // start game - this will cause debug messages to now // go to the log file instead of stdout. gamestarted = B_TRUE; @@ -243,6 +243,32 @@ celltype_t *addcelltype(int id, char *name, char glyph, int solid, int transpare return a; } +command_t *addcommand(enum COMMAND id, char ch, char *desc) { + command_t *a; + + // add to the end of the list + if (firstcommand == NULL) { + firstcommand = malloc(sizeof(command_t)); + a = firstcommand; + a->prev = NULL; + } else { + // go to end of list + a = lastcommand; + a->next = malloc(sizeof(command_t)); + a->next->prev = a; + a = a->next; + } + lastcommand = a; + a->next = NULL; + + // set props + a->id = id; + a->ch = ch; + a->desc = strdup(desc); + + return a; +} + void checkdeath(void) { lifeform_t *lf, *nextlf; int x,y; @@ -330,7 +356,7 @@ void donextturn(map_t *map) { if (donormalmove) { // paralyzed etc? - if (cannotmove(who)) { + if (isimmobile(who)) { rest(who, B_FALSE); donormalmove = B_FALSE; } @@ -359,7 +385,10 @@ void donextturn(map_t *map) { } } - if (isdead(who) || haslos(player, who->cell)) { + if (hasflag(player->flags, F_RESTING)) { + // ooo is this right ? + needredraw = B_FALSE; + } else if (isdead(who) || haslos(player, who->cell)) { needredraw = B_TRUE; } @@ -415,7 +444,8 @@ void getrarity(int depth, int *min, int *max, int range) { int mid; mid = 100 - (depth * 3); *min = mid - range; if (*min < 0) *min = 0; - *max = mid + range; if (*max > 100) *max = 100; + //*max = mid + range; if (*max > 100) *max = 100; + *max = 100; if (*min > 75) *min = 75; if (*max < 25) *max = 25; @@ -426,6 +456,8 @@ int init(void) { srand(time(NULL)); + + initcommands(); initobjects(); initjobs(); initrace(); @@ -453,6 +485,47 @@ int init(void) { return B_FALSE; } +void initcommands(void) { + // Actions + addcommand(CMD_UP, '<', "Go up stairs."); + addcommand(CMD_DOWN, '>', "Go down stairs, enter a shop/portal."); + addcommand(CMD_REST, '.', "Rest once."); + addcommand(CMD_PICKUP, ',', "Pick up something from the ground."); + addcommand(CMD_CLOSE, 'c', "Close a door."); + addcommand(CMD_DROP, 'd', "Drop an item."); + addcommand(CMD_DROPMULTI, 'D', "Drop multiple items."); + addcommand(CMD_EAT, 'e', "Eat something."); + addcommand(CMD_MAGIC, 'm', "Use magic or abilities."); + addcommand(CMD_OPERATE, 'o', "Operate a tool/wand/device."); + addcommand(CMD_PICKLOCK, 'p', "Pick a lock."); + addcommand(CMD_POUR, 'P', "Pour a potion onto something."); + addcommand(CMD_QUAFF, 'q', "Quaff (drink) a potion."); + addcommand(CMD_READ, 'r', "Read a scroll/book."); + addcommand(CMD_RESTFULL, 'R', "Rest until healed."); + addcommand(CMD_TAKEOFF, 'T', "Take off an item of clothing/jewelery."); + addcommand(CMD_WEILD, 'w', "Weild a weapon."); + addcommand(CMD_WEAR, 'W', "Wear an item of clothing/jewelery."); + // Firearms + addcommand(CMD_FIRE, 'f', "Fire your firearm/bow at your current target."); + addcommand(CMD_FIRENEW, 'F', "Fire your firearm/bow at a new target."); + addcommand(CMD_AIM, 'a', "Aim your current firearm/bow at a new target."); + // Information + addcommand(CMD_HELP, '?', "Display this text."); + addcommand(CMD_INFOPLAYER, '@', "Display player stats."); + addcommand(CMD_INFOARMOUR, ']', "Display player armour."); + addcommand(CMD_FORCEATTACK, 'A', "Force an attack in a given direction."); + addcommand(CMD_LOOKHERE, ':', "Look at current cell."); + addcommand(CMD_LOOKAROUND, '/', "Look at a remote cell."); + addcommand(CMD_INFOKNOWLEDGE, '\\', "Display known items."); + addcommand(CMD_MSGHIST, '|', "Display message history."); + addcommand(CMD_INV, 'i', "Display your inventory."); + // GAME FUNCTIONS + addcommand(CMD_QUIT, 'Q', "Quit the game."); + addcommand(CMD_SAVEQUIT, 'S', "Save and quit the game."); + + sortcommands(); +} + int isplayerturn(void) { if (!player) return B_FALSE; @@ -462,6 +535,19 @@ int isplayerturn(void) { return B_FALSE; } +int limit(int *what, int min, int max) { + int limited = B_FALSE; + if (*what < min) { + *what = min; + limited = B_TRUE; + } + if (*what > max) { + *what = max; + limited = B_TRUE; + } + return limited; +} + float pctof(float pct, float num) { return ((pct / 100.0) * num); } @@ -619,6 +705,50 @@ dblog("doing sort..."); } */ +void sortcommands(void) { + command_t *c; + int donesomething = B_TRUE; + while (donesomething) { + donesomething = B_FALSE; + for (c = firstcommand ; c->next ; c = c->next) { + // move up one position if required. + if (c->ch > c->next->ch) { + command_t *temp; + + // remember next element + temp = c->next; + + // remove this element from list + if (c->prev == NULL) { + // first + firstcommand = c->next; + c->next->prev = NULL; + } else { + // not first + c->prev->next = c->next; + c->next->prev = c->prev; + } + + // re-add element afterwards + c->next = temp->next; + c->prev = temp; + temp->next = c; + if (c->next == NULL) { + lastcommand = c; + } else { + c->next->prev = c; + } + + // mark as done. + donesomething = B_TRUE; + break; + } + } + } +} + + + void timeeffectsworld(map_t *map) { lifeform_t *l; int db = B_FALSE; diff --git a/nexus.h b/nexus.h index 4e0e3fc..90c406e 100644 --- a/nexus.h +++ b/nexus.h @@ -1,6 +1,7 @@ #include "defs.h" celltype_t *addcelltype(int id, char *name, char glyph, int solid, int transparent, enum MATERIAL mat); +command_t *addcommand(enum COMMAND id, char c, char *desc); void checkdeath(void); void checkendgame(void); void cleanup(void); @@ -9,11 +10,14 @@ celltype_t *findcelltype(int id); char *getdirname(int dir); void getrarity(int depth, int *min, int *max, int range); int init(void); +void initcommands(void); int isplayerturn(void); +int limit(int *what, int min, int max); float pctof(float pct, float num); int rnd(int min, int max); int rolldie(int ndice, int sides); int rollhitdice(lifeform_t *lf); int rollmpdice(lifeform_t *lf); //void sortlf(map_t *map); +void sortcommands(void); void timeeffectsworld(map_t *map); diff --git a/objects.c b/objects.c index ef79193..82072ca 100644 --- a/objects.c +++ b/objects.c @@ -44,6 +44,7 @@ char *bookname[] = { "blue book", "clean book", "creepy book", + "damp book", "dog-eared book", "dusty book", "eerie book", @@ -54,13 +55,17 @@ char *bookname[] = { "hot book", "humming book", "icy book", + "jiggling book", "leatherbound book", "luminous book", "mouldy book", + "muddy book", + "night-black book", "orange book", "papyrus book", "pink book", "plain book", + "quivering book", "rainbow-coloured book", "red book", "slimy book", @@ -113,6 +118,9 @@ char *potionname[] = { "clear potion", "cyan potion", "dark potion", + "effervescent potion", + "fizzy potion", + "fuming potion", "green potion", "indigo potion", "luminous potion", // should produce light @@ -170,6 +178,7 @@ enum OBCLASS sortorder[] = { OC_DFEATURE, OC_MONEY, OC_WEAPON, + OC_MISSILE, OC_ARMOUR, OC_POTION, OC_SCROLL, @@ -321,7 +330,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack) { char numstringmax[BUFLEN]; int howmany = 1; int i; - int db = B_FALSE; + int db = B_TRUE; //flag_t *f; char *localname; int wantblessed = B_UNCURSED; @@ -422,37 +431,52 @@ object_t *addobject(obpile_t *where, char *name, int canstack) { - p2 = strstr(p, "corpse"); - if (p2) { + if (strstr(p, "corpse")) { int len; char racename[BUFLEN]; + p2 = strstr(p, "corpse"); len = p2 - p; snprintf(racename, len, "%s",p); corpserace = findracebyname(racename); ot = findot(OT_CORPSE); - } else { - p2 = strstr(p, " head"); - if (p2) { - int len; - char racename[BUFLEN]; - len = p2 - p + 1; - snprintf(racename, len, "%s",p); + } else if (strstr(p, "statue of ")) { + char racename[BUFLEN]; + + // go to end + p2 = strstr(p, "statue of "); + p2 += 10; // now on either 'a' or 'an' + p2++; // now on either ' ' or 'n' + for (;*p2 != ' ';p2++); + p2++; + // now at start of name + sprintf(racename, "%s",p2); - corpserace = findracebyname(racename); - ot = findot(OT_HEAD); - } else { - // make sure we can find the requested object type - if (db) dblog("DB: Looking for object name '%s'", p ); - ot = findotn(p); - if (!ot) { - //if (gamestarted) msg("DB: No match for object name '%s'", p ); - if (db) dblog("DB: No match for object name '%s'", p ); - return NULL; - } + corpserace = findracebyname(racename); + ot = findot(OT_STATUE); + } else if (strstr(p, " head")) { + int len; + char racename[BUFLEN]; + p2 = strstr(p, " head"); + len = p2 - p + 1; + snprintf(racename, len, "%s",p); + + corpserace = findracebyname(racename); + ot = findot(OT_HEAD); + } else { + // make sure we can find the requested object type + if (db) dblog("DB: Looking for object name '%s'", p ); + ot = findotn(p); + if (!ot) { + //if (gamestarted) msg("DB: No match for object name '%s'", p ); + if (db) dblog("DB: No match for object name '%s'", p ); + return NULL; } } if (db) dblog("DB: FOUND: ot->name = '%s'", ot->name ); + if (ot->id == OT_WOODENDOOR) { + dblog("xxx"); + } // don't give nopickup objects to lifeforms if (hasflag(ot->flags, F_NOPICKUP) && where->owner) { @@ -643,7 +667,47 @@ object_t *addobject(obpile_t *where, char *name, int canstack) { } } } + } else if (o->type->id == OT_STATUE) { + flag_t *f, *rf; + float ratio; + + if (!corpserace) { + cell_t *where; + where = getoblocation(o); + // select random race + corpserace = getrandomrace(where->map); + } + ratio = o->material->weightrating / corpserace->material->weightrating; + + o->weight = corpserace->weight * ratio; + + // remember the race type + addflag(o->flags, F_CORPSEOF, corpserace->id, NA, NA, NULL); + + // set impassable size + f = hasflag(o->flags, F_IMPASSABLE); + if (f) { + rf = hasflag(corpserace->flags, F_SIZE); + if (rf) { + f->val[0] = rf->val[0]; + } else { + killflag(f); + } + } + + // set ob hp + f = hasflag(o->flags, F_OBHP); + if (f) { + rf = hasflag(corpserace->flags, F_HITDICE); + if (rf) { + int maxhp; + maxhp = (rf->val[0] * 4) + rf->val[1]; + f->val[0] = maxhp; + f->val[1] = maxhp; + } + } + } else if (o->type->id == OT_HEAD) { flag_t *rf, *cf; @@ -800,6 +864,37 @@ object_t *addobject(obpile_t *where, char *name, int canstack) { } +// add objects in a circle +// returns # added. +int addobburst(cell_t *where, int range, int dirtype, char *name) { + int (*distfunc)(cell_t *, cell_t *); + int x,y; + cell_t *c; + int nadded = 0; + + if (!where) return 0; + + if (dirtype == DT_ORTH) { + distfunc = getcelldistorth; + } else { + distfunc = getcelldist; + } + + for (y = where->y - range; y <= where->y + range; y++) { + for (x = where->x - range; x <= where->x + range; x++) { + c = getcellat(where->map, x,y); + if (distfunc(where, c) <= range) { + if (cellwalkable(NULL, c, NULL)) { + if (addob(c->obpile, name)) nadded++; + } + } + } + } + + return nadded; +} + + obmod_t *addobmod(enum OBMOD id, char *suffix, enum BODYPART bp) { obmod_t *a, *om; char buf[BUFLEN]; @@ -1004,8 +1099,10 @@ void adjustdamob(object_t *o, unsigned int *dam, enum DAMTYPE damtype) { } // only some objects can be hurt if (!hasflag(o->flags, F_DAMAGABLE)) { - *dam = 0; - return; + if (damtype != DT_DIRECT) { + *dam = 0; + return; + } } // immune? if (isimmuneto(o->flags, damtype)) { @@ -1026,7 +1123,7 @@ void adjustdamob(object_t *o, unsigned int *dam, enum DAMTYPE damtype) { // adjust damage if (o->blessed == B_BLESSED) { - // change of no hp loss + // chance of no hp loss if (rnd(1,2) == 1) { lifeform_t *owner; owner = o->pile->owner; @@ -1289,6 +1386,54 @@ int changemat(object_t *o, enum MATERIAL mat) { return B_FALSE; } +objecttype_t *checkobnames(char *haystack, char *needle) { + objecttype_t *ot; + char *pluralname; + int db = B_TRUE; + + // search for exact match + if (!strcmp(haystack, needle)) { + // found it! + if (db) dblog("checkobnames(): got exact match: '%s'",haystack); + return ot; + } + + // search for words ending in "s" (eg. "swords") + pluralname = strdup(needle); + //if (db) dblog("findotn(): plural is '%s'",pluralname); + if (pluralname[strlen(pluralname)-1] == 's') { + // remove trailing 's' + pluralname[strlen(pluralname)-1] = '\0'; + // search again (for exact matches) + if (!strcmp(haystack, pluralname)) { + if (db) dblog("checkobnames(): got match after stripping 's': '%s' -> '%s'",pluralname, needle); + free(pluralname); + return ot; + } + + // search for words ending in "es" (eg. tomatoes) + if ((pluralname[strlen(pluralname)-1] == 'e') && + (pluralname[strlen(pluralname)-2] == 'o') + ) { + // remove trailing 'es' + pluralname[strlen(pluralname)-1] = '\0'; + pluralname[strlen(pluralname)-2] = '\0'; + //if (db) dblog("findotn(): pluralname without 'es' is '%s'",pluralname); + // search again + if (!strcmp(haystack, pluralname)) { + if (db) dblog("checkobnames(): got match after stripping 'es': '%s' -> '%s'",pluralname, needle); + free(pluralname); + return ot; + } + } + } + free(pluralname); + + return NULL; +} + + + void copyobprops(object_t *dst, object_t *src) { dst->material = src->material; dst->weight = src->weight; @@ -1387,7 +1532,6 @@ void explodeob(object_t *o, flag_t *f, int bigness) { */ } - void extinguish(object_t *o) { flag_t *f; char obname[BUFLEN]; @@ -1464,7 +1608,7 @@ objecttype_t *findot(enum OBTYPE id) { objecttype_t *findotn(char *name) { objecttype_t *ot; knowledge_t *k; - char *searchfor, *modname; + char *modname; char *p; int db = B_FALSE; obmod_t *om; @@ -1487,6 +1631,8 @@ objecttype_t *findotn(char *name) { modname = strrep(modname, "puddles ", "puddle ", NULL); modname = strrep(modname, "rings ", "ring ", NULL); modname = strrep(modname, "scrolls ", "scroll ", NULL); + modname = strrep(modname, "splashes ", "splash ", NULL); + modname = strrep(modname, "suits ", "suit ", NULL); modname = strrep(modname, "vials ", "vial ", NULL); // only at start... @@ -1528,14 +1674,24 @@ objecttype_t *findotn(char *name) { } if (db) dblog("findotn(): modname is '%s'",modname); - // check for exact matches on real name first + + // check for exact matches on real name (and plural versions) first for (ot = objecttype ; ot ; ot = ot->next) { - if (!strcmp(ot->name, modname)) { + if (checkobnames(ot->name, modname)) { + free(modname); + return ot; + } + } + + // then matches on hidden name + for (k = knowledge; k ; k = k->next) { + if (checkobnames(k->hiddenname, modname)) { free(modname); // found it! - return ot; - } + return findot(k->id); + } } + // then partial matches on real name for (ot = objecttype ; ot ; ot = ot->next) { if (strstr(ot->name, modname)) { @@ -1545,59 +1701,11 @@ objecttype_t *findotn(char *name) { } } - // then matches on hidden name - for (k = knowledge; k ; k = k->next) { - if (strstr(k->hiddenname, modname)) { - free(modname); - // found it! - return findot(k->id); - } - } - - searchfor = strdup(modname); - // search for words ending in "s" (eg. "swords") - if (searchfor[strlen(searchfor)-1] == 's') { - // remove trailing 's' - searchfor[strlen(searchfor)-1] = '\0'; - if (db) dblog("findotn(): searchfor without 's' is '%s'",searchfor); - // search again - for (ot = objecttype ; ot ; ot = ot->next) { - if (strstr(ot->name, searchfor)) { - free(modname); - free(searchfor); - return ot; - } - } - } - - // reset back to inital word - free(searchfor); - searchfor = strdup(modname); - - // haven't found it yet - check for plurals - // search for words ending in "es" (eg. tomatoes) - if ((searchfor[strlen(searchfor)-1] == 's') && - (searchfor[strlen(searchfor)-2] == 'e') && - (searchfor[strlen(searchfor)-3] == 'o') - ) { - // remove trailing 'es' - searchfor[strlen(searchfor)-1] = '\0'; - searchfor[strlen(searchfor)-2] = '\0'; - if (db) dblog("findotn(): searchfor without 'es' is '%s'",searchfor); - // search again - for (ot = objecttype ; ot ; ot = ot->next) { - if (strstr(ot->name, searchfor)) { - free(modname); - free(searchfor); - return ot; - } - } - } free(modname); - free(searchfor); return NULL; } + // ie. "the apple is xxx" // ie. "the apples are xxx" char *getfillingname(int nutrition) { @@ -1800,6 +1908,17 @@ int getobaccuracy(object_t *wep) { return acc; } +int getobbonus(object_t *o) { + flag_t *f; + int bonus = 0; + for (f = o->flags->first ; f ; f = f->next) { + if (f->id == F_BONUS) { + bonus += f->val[0]; + } + } + return bonus; +} + // returns value of obejcts, in gold int getobvalue(object_t *o) { float price; @@ -1983,6 +2102,7 @@ char *getdamname(enum DAMTYPE damtype) { case DT_DECAY: return "decay"; case DT_MAGIC: return "magical"; case DT_TOUCH: return "touch"; + case DT_UNARMED: return "unarmed"; default: return "unknown"; } return "unknown"; @@ -2011,6 +2131,7 @@ char *getdamnamenoun(enum DAMTYPE damtype) { case DT_WATER: return "water"; case DT_MAGIC: return "magical damage"; case DT_TOUCH: return "touch effects"; + case DT_UNARMED: return "unarmed damage"; default: return "unknown"; } return "unkmown"; @@ -2052,6 +2173,17 @@ int getobattackdelay(object_t *o) { return delay; } +float getobhppct(object_t *o) { + float pct; + flag_t *f; + f = hasflag(o->flags, F_OBHP); + if (f) { + pct = ((float) f->val[0] / (float) f->val[1]) * 100.0; + } else { + pct = 100; + } + return pct; +} int getletidx(char let) { int i; @@ -2102,8 +2234,23 @@ int getmaterialvalue(enum MATERIAL mat) { int getmaxthrowrange(lifeform_t *lf, object_t *o) { int maxdist; - // TODO: adjust for lifeform strength - maxdist = 10 - (getobunitweight(o) / 2); + float strmod; + float modobweight; + // adjust for lifeform strength + // mighty = div by 10 + + // this will give us a number in range -44 - 50 + strmod = getstatmod(lf, A_STR); + // this will give us a number in range 1 - 10 + strmod /= 5; + if (strmod < 1) strmod = 1; + + modobweight = getobunitweight(o) / 2; + modobweight /= strmod; + + maxdist = 10 - modobweight; + + if (maxdist < 0) maxdist = 0; return maxdist; } @@ -2210,6 +2357,17 @@ char *getobdesc(object_t *o, char *buf) { } else { sprintf(buf, "%s", o->type->desc); } + } else if (o->type->id == OT_STATUE) { + flag_t *f; + f = hasflag(o->flags, F_CORPSEOF); + if (f) { + race_t *corpserace; + corpserace = findrace(f->val[0]); + sprintf(buf, "A stone statue of %s %s.", isvowel(corpserace->name[0]) ? "an" : "a", + corpserace->name); + } else { + sprintf(buf, "%s", o->type->desc); + } } else if (o->type->id == OC_SCROLL) { flag_t *f; f = hasflag(o->flags, F_LINKSPELL); @@ -2233,17 +2391,72 @@ char *getobdesc(object_t *o, char *buf) { return buf; } + +char *getobextrainfo(object_t *o, char *buf) { + object_t *ammo = NULL; + flag_t *f; + + strcpy(buf, ""); + + if (o->pile->owner) { + ammo = getammo(o->pile->owner); + } + + // charges + f = hasflag(o->flags, F_CHARGES); + if (f && f->known) { + if (!hasflag(o->flags, F_DONTSHOWCHARGES)) { + char chargestr[BUFLEN]; + if (f->val[0] > 0) { + sprintf(chargestr, " (%d charges left)",f->val[0]); + } else { + sprintf(chargestr, " (empty)"); + } + strcat(buf, chargestr); + } + } + + // activated + f = hasflag(o->flags, F_ACTIVATED); + if (f) { + strcat(buf, " [activated]"); + } + + f = hasflag(o->flags,F_EQUIPPED); + if (f) { + if (f->val[0] == BP_WEAPON) { + if (hasflag(o->flags, F_TWOHANDED)) { + strcat(buf, " (two-handed weapon)"); + } else { + strcat(buf, " (weapon)"); + } + } else { + strcat(buf, " ("); + strcat(buf, getbodypartequipname(f->val[0])); + strcat(buf, " "); + strcat(buf, getbodypartname(f->val[0])); + strcat(buf, ")"); + } + } + + // ammo? + if (ammo && (ammo == o)) { + strcat(buf, " (current ammo)"); + } + return buf; +} + cell_t *getoblocation(object_t *o) { if (o->pile->owner) return o->pile->owner->cell; else return o->pile->where; } char *getobname(object_t *o, char *buf, int count) { - return real_getobname(o, buf, count, B_TRUE, B_TRUE, B_TRUE); + return real_getobname(o, buf, count, B_TRUE, B_TRUE, B_TRUE, B_TRUE); } // buf must already be allocated -char *real_getobname(object_t *o, char *buf, int count, int wantcondition, int adjustforblind, int wantblesscurse) { +char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wantcondition, int adjustforblind, int wantblesscurse) { char *pluralname; char prefix[BUFLEN]; char basename[BUFLEN]; @@ -2301,6 +2514,13 @@ char *real_getobname(object_t *o, char *buf, int count, int wantcondition, int a corpserace = findrace(f->val[0]); sprintf(basename, "%s head",corpserace->name); } + } else if (o->type->id == OT_STATUE) { + f = hasflag(o->flags, F_CORPSEOF); + if (f) { + race_t *corpserace; + corpserace = findrace(f->val[0]); + sprintf(basename, "statue of a %s",corpserace->name); + } } // handle ALL @@ -2385,11 +2605,13 @@ char *real_getobname(object_t *o, char *buf, int count, int wantcondition, int a } // include mods (ie. a flaming sword) - if (hasflag(o->flags, F_ONFIRE)) { - strcat(buf, "flaming "); - } - if (hasflag(o->flags, F_HEADLESS)) { - strcat(buf, "headless "); + if (wantpremods) { + if (hasflag(o->flags, F_ONFIRE)) { + strcat(buf, "flaming "); + } + if (hasflag(o->flags, F_HEADLESS)) { + strcat(buf, "headless "); + } } // condition @@ -2488,7 +2710,6 @@ float getobpileweight(obpile_t *op) { } char *getobconditionname(object_t *o, char *buf) { - flag_t *f; float pct; enum IQBRACKET iqb; if (player) { @@ -2506,12 +2727,8 @@ char *getobconditionname(object_t *o, char *buf) { } } else { if (iqb >= IQ_DIMWITTED) { - f = hasflag(o->flags, F_OBHP); - if (f) { - pct = ((float) f->val[0] / (float) f->val[1]) * 100.0; - } else { - pct = 100; - } + + pct = getobhppct(o); if (pct >= 100) { strcpy(buf, ""); @@ -3006,6 +3223,19 @@ char *getrandomobwithclass(map_t *map, enum OBCLASS cid, char *buf) { return real_getrandomob(map, buf, RO_OBCLASS, cid, NA); } +enum SPELLSCHOOL getschool(enum OBTYPE sid) { + objecttype_t *ot; + ot = findot(sid); + if (ot) { + flag_t *f; + f = hasflag(ot->flags, F_SPELLSCHOOL); + if (f) { + return f->val[0]; + } + } + return SS_NONE; +} + char *getschoolname(enum SPELLSCHOOL sch) { switch (sch) { case SS_ABILITY: return "Abilities"; @@ -3013,7 +3243,9 @@ char *getschoolname(enum SPELLSCHOOL sch) { case SS_DIVINE: return "Divine Powers"; case SS_WILD: return "Wild Magic"; case SS_MENTAL: return "Mental Powers"; - case SS_ELEMENTAL: return "Elemental Magic"; + case SS_AIR: return "Elemental/Air Magic"; + case SS_FIRE: return "Elemental/Fire Magic"; + case SS_ICE: return "Elemental/Ice Magic"; case SS_MODIFICATION: return "Transmutation Magic"; case SS_DEATH: return "Death Magic"; case SS_LIFE: return "Life Magic"; @@ -3022,6 +3254,8 @@ char *getschoolname(enum SPELLSCHOOL sch) { case SS_SUMMONING: return "Summoning Magic"; case SS_GRAVITY: return "Gravitation Magic"; case SS_LAST: return "!invalid school!"; + default: + break; } return "unknown school"; } @@ -3041,12 +3275,25 @@ int getshatterdam(object_t *o) { int getthrowdam(object_t *o) { double dam = 0; flag_t *f; - // base damage is = kilograms. - // ie. 1 kg object does 1 damage - // ie. 5 kg object does 5 damage - // ie. 100 kg object does 100 damage (person) - // ie. 1 tonne object does 1000 damage (car) - dam = ceil((double)getobunitweight(o)); + + // modify if it has a damage value + f = hasflag(o->flags, F_MISSILEDAM); + if (f) { + dam = f->val[0]; + } else { + // base damage is = kilograms. + // ie. 1 kg object does 1 damage + // ie. 5 kg object does 5 damage + // ie. 100 kg object does 100 damage (person) + // ie. 1 tonne object does 1000 damage (car) + dam = ceil((double)getobunitweight(o)); + // missile objects do extra damage + if (hasflag(o->flags, F_MISSILE)) { + dam *= 2; + } + // max + if (dam > 20) dam = 20; + } // modify for bonus f = hasflag(o->flags, F_BONUS); @@ -3069,11 +3316,6 @@ int getthrowdam(object_t *o) { break; } - // misisle objects do extra damage - if (hasflag(o->flags, F_MISSILE)) { - dam *= 2; - } - return (int)dam; } @@ -3166,6 +3408,20 @@ void identify(object_t *o) { } } +void ignite(object_t *o) { + flag_t *f; + if (!hasflag(o->flags, F_DAMAGABLE)) { + addflag(o->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); + } + + f = hasflag(o->flags, F_ONFIRE); + if (!f) { + // on fire for 2 turns + addtempflag(o->flags, F_ONFIRE, B_TRUE, NA, NA, NULL, 2); + } +} + + void initobjects(void) { //int ch; //int i; @@ -3182,13 +3438,15 @@ void initobjects(void) { // object modifiers - flags should be UNKNOWN! addobmod(OM_BALANCE, "of balance", BP_WEAPON); addflag_real(lastobmod->flags, F_BALANCE, B_TRUE, NA, NA, NULL, PERMENANT, B_UNKNOWN, -1); - - addobmod(OM_LEVITATION, "of levitation", BP_FEET); - addflag_real(lastobmod->flags, F_EQUIPCONFER, F_LEVITATING, NA, NA, NULL, PERMENANT, B_UNKNOWN, -1); addobmod(OM_PYROMANIA, "of pyromania", BP_WEAPON); addflag_real(lastobmod->flags, F_FLAMESTRIKE, B_TRUE, NA, NA, NULL, PERMENANT, B_UNKNOWN, -1); addobmod(OM_REVENGE, "of revenge", BP_WEAPON); addflag_real(lastobmod->flags, F_REVENGE, B_TRUE, NA, NA, NULL, PERMENANT, B_UNKNOWN, -1); + addobmod(OM_SHARPNESS, "of sharpness", BP_WEAPON); + addflag_real(lastobmod->flags, F_ARMOURPIERCE, B_TRUE, NA, NA, NULL, PERMENANT, B_UNKNOWN, -1); + + addobmod(OM_LEVITATION, "of levitation", BP_FEET); + addflag_real(lastobmod->flags, F_EQUIPCONFER, F_LEVITATING, NA, NA, NULL, PERMENANT, B_UNKNOWN, -1); addobmod(OM_SWIFTNESS, "of swiftness", BP_FEET); @@ -3201,6 +3459,8 @@ void initobjects(void) { addflag_real(lastobmod->flags, F_EQUIPCONFER, F_ATTRMOD, A_STR, -3, NULL, PERMENANT, B_UNKNOWN, -1); addobmod(OM_DEXTERITY, "of dexterity", BP_HANDS); addflag_real(lastobmod->flags, F_EQUIPCONFER, F_ATTRMOD, A_DEX, 3, NULL, PERMENANT, B_UNKNOWN, -1); + addobmod(OM_IMPACT, "of impact", BP_WEAPON); // TODO: make thisonly go ont obashing weapons + addflag_real(lastobmod->flags, F_HEAVYBLOW, B_TRUE, NA, NA, NULL, PERMENANT, B_UNKNOWN, -1); addobmod(OM_INTELLIGENCE, "of intelligence", BP_HEAD); addflag_real(lastobmod->flags, F_EQUIPCONFER, F_ATTRMOD, A_IQ, 3, NULL, PERMENANT, B_UNKNOWN, -1); addobmod(OM_KNOWLEDGE, "of knowledge", BP_HEAD); @@ -3227,7 +3487,6 @@ void initobjects(void) { addmaterial(MT_FIRE, "fire", 0); addmaterial(MT_GAS, "gas", 0.5); addmaterial(MT_PAPER, "paper", 1); - addflag(lastmaterial->flags, F_DTCONVERT, DT_FIRE, NA, NA, "pile of ash"); addflag(lastmaterial->flags, F_MATCONVERT, MT_WATER, NA, NA, "lump of soggy paper"); addflag(lastmaterial->flags, F_MATCONVERTTEXT, MT_WATER, NA, NA, "goes soggy"); addflag(lastmaterial->flags, F_MATCONVERTTEXTPL, MT_WATER, NA, NA, "go soggy"); @@ -3287,6 +3546,11 @@ void initobjects(void) { addoc(OC_ARMOUR, "Armour/Clothing", "Protective gear.", ']'); addflag(lastobjectclass->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(lastobjectclass->flags, F_ENCHANTABLE, B_TRUE, NA, NA, NULL); + addoc(OC_MISSILE, "Missiles/Ammunition", "An instrument used for the purpose of causing harm or death.", ';'); + addflag(lastobjectclass->flags, F_ENCHANTABLE, B_TRUE, NA, NA, NULL); + addflag(lastobjectclass->flags, F_STACKABLE, B_TRUE, NA, NA, NULL); + addflag(lastobjectclass->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); + addflag(lastobjectclass->flags, F_MISSILE, B_TRUE, NA, NA, NULL); addoc(OC_ROCK, "Rocks/Gems", "Boring (or not so boring) rocks.", '*'); addoc(OC_FOOD, "Food", "Yum!", '%'); addflag(lastobjectclass->flags, F_STACKABLE, B_TRUE, NA, NA, ""); @@ -3316,7 +3580,7 @@ void initobjects(void) { addot(OT_WOODENDOOR, "wooden door", "A sturdy wooden door.", MT_WOOD, 150, OC_DFEATURE); // GLYPH here is a special case in getglyph addflag(lastot->flags, F_DOOR, B_TRUE, NA, NA, NULL); - addflag(lastot->flags, F_IMPASSABLE, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_IMPASSABLE, SZ_MAX, NA, NA, NULL); addflag(lastot->flags, F_BLOCKSVIEW, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_BLOCKSTHROW, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); @@ -3329,7 +3593,8 @@ void initobjects(void) { addot(OT_WOODENTABLE, "wooden table", "A waist-height wooden table.", MT_WOOD, 25, OC_DFEATURE); addflag(lastot->flags, F_RARITY, H_ALL, 70, NA, NULL); addflag(lastot->flags, F_GLYPH, NA, NA, NA, "\\"); - addflag(lastot->flags, F_IMPASSABLE, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_IMPASSABLE, SZ_HUMAN, NA, NA, NULL); + addflag(lastot->flags, F_CRUSHABLE, SZ_LARGE, NA, NA, NULL); addflag(lastot->flags, F_PUSHABLE, 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); @@ -3338,10 +3603,10 @@ void initobjects(void) { addflag(lastot->flags, F_DTVULN, DT_BASH, NA, NA, NULL); addflag(lastot->flags, F_DTVULN, DT_CHOP, NA, NA, NULL); - addot(OT_BOULDER, "boulder", "A massive stone boulder.", MT_STONE, 100, OC_DFEATURE); + addot(OT_BOULDER, "boulder", "A massive stone boulder.", MT_STONE, 80, OC_DFEATURE); addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, ""); addflag(lastot->flags, F_GLYPH, NA, NA, NA, "'"); - addflag(lastot->flags, F_IMPASSABLE, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_IMPASSABLE, SZ_LARGE, NA, NA, NULL); addflag(lastot->flags, F_PUSHABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_BLOCKSVIEW, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_BLOCKSTHROW, B_TRUE, NA, NA, NULL); @@ -3351,6 +3616,16 @@ void initobjects(void) { addflag(lastot->flags, F_MISSILE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OBHP, 80, 80, NA, NULL); + addot(OT_STATUE, "statue", "A stone statue of a monster.", MT_STONE, 80, OC_DFEATURE); + addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, ""); + addflag(lastot->flags, F_GLYPH, NA, NA, NA, "'"); + addflag(lastot->flags, F_IMPASSABLE, SZ_LARGE, NA, NA, NULL); + addflag(lastot->flags, F_PUSHABLE, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_BLOCKSTHROW, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_OBHP, 80, 80, NA, NULL); + addot(OT_STAIRSDOWN, "staircase going down", "A stone staircase winding downwards.", MT_STONE, 3000, OC_DFEATURE); addflag(lastot->flags, F_GLYPH, NA, NA, NA, ">"); addflag(lastot->flags, F_CLIMBABLE, D_DOWN, NA, NA, NULL); @@ -3366,7 +3641,7 @@ void initobjects(void) { addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addot(OT_VENDINGMACHINE, "vending machine", "A gold-operated vending machine.", MT_METAL, 500, OC_DFEATURE); - addflag(lastot->flags, F_RARITY, H_ALL, 25, NA, ""); + addflag(lastot->flags, F_RARITY, H_ALL, 70, NA, ""); addflag(lastot->flags, F_GLYPH, NA, NA, NA, "_"); addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); @@ -3388,6 +3663,7 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, ""); addflag(lastot->flags, F_NUMAPPEAR, 1, 10, NA, ""); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_MISSILE, B_TRUE, NA, NA, NULL); addot(OT_ASH, "pile of ash", "A pile of ash", MT_STONE, 0.1, OC_ROCK); addflag(lastot->flags, F_GLYPH, B_TRUE, NA, NA, ","); @@ -3409,9 +3685,15 @@ void initobjects(void) { addflag(lastot->flags, F_EDIBLE, B_TRUE, 12, NA, ""); addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL); addflag(lastot->flags, F_NUMAPPEAR, 1, 12, NA, ""); - addot(OT_BANANA, "banana", "Ba-na-na-na-na-na na-na na-na-na.", MT_FOOD, 0.5, OC_FOOD); + addot(OT_BANANA, "banana", "Ba-na-na-na-na-na na-na na-na-na.", MT_FOOD, 0.3, OC_FOOD); addflag(lastot->flags, F_EDIBLE, B_TRUE, 50, NA, ""); addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); + + addot(OT_BANANASKIN, "banana skin", "A slippery banana skin.", MT_FOOD, 0.1, OC_FOOD); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); + addflag(lastot->flags, F_SLIPPERY, 15, NA, NA, NULL); + addflag(lastot->flags, F_SLIPMOVE, 15, NA, NA, NULL); + addot(OT_APPLE, "apple", "A crunchy apple.", MT_FOOD, 0.5, OC_FOOD); addflag(lastot->flags, F_EDIBLE, B_TRUE, 50, NA, ""); addflag(lastot->flags, F_RARITY, H_DUNGEON, 85, NA, NULL); @@ -3469,56 +3751,64 @@ void initobjects(void) { addflag(lastot->flags, F_EDIBLE, B_TRUE, 5, NA, ""); - // potions - addot(OT_POT_AMBROSIA, "vial of ambrosia", "The nectar of the gods, said to completely restore the drinker's health.", MT_GLASS, 1, OC_POTION); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 35, NA, NULL); + // potions (sorted by rarity) + addot(OT_POT_JUICE, "potion of fruit juice", "Tasty (but not very fresh) fruit juice!", MT_GLASS, 1, OC_POTION); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, NULL); + addot(OT_POT_WATER, "potion of water", "Plain, regular water.", MT_GLASS, 1, OC_POTION); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL); + addot(OT_POT_HEALINGMIN, "potion of minor healing", "Restores 1-8 health to whoever drinks it.", MT_GLASS, 1, OC_POTION); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL); + addflag(lastot->flags, F_AIHEALITEM, B_TRUE, NA, NA, NULL); + addot(OT_POT_HEALING, "potion of healing", "Restores 10-20 health to whoever drinks it.", MT_GLASS, 1, OC_POTION); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); + addflag(lastot->flags, F_AIHEALITEM, B_TRUE, NA, NA, NULL); + addot(OT_POT_OIL, "potion of oil", "A bottle of cooking oil.", MT_GLASS, 1, OC_POTION); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); addot(OT_POT_ACID, "flask of battery acid", "Causes massive internal burning if ingested.", MT_GLASS, 1, OC_POTION); addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); addflag(lastot->flags, F_MISSILE, B_TRUE, NA, NA, NULL); addot(OT_POT_ACROBATICS, "potion of acrobatics", "Allows the drinker to leap large distances.", MT_GLASS, 1, OC_POTION); addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); - addot(OT_POT_COMPETENCE, "potion of competence", "Permemantly increases the drinker's strength, intelligence or dexterity.", MT_GLASS, 1, OC_POTION); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); - addot(OT_POT_ELEMENTENDURE, "potion of endure elements", "Grants the imbiber temporary resistance to both fire and cold.", MT_GLASS, 1, OC_POTION); addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); - addot(OT_POT_ELEMENTIMMUNE, "potion of elemental immunity", "Grants the imbiber temporary immunity to both fire and cold.", MT_GLASS, 1, OC_POTION); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL); - addot(OT_POT_ETHEREALNESS, "potion of etherealness", "Allows the walker to temporarily pass through walls.", MT_GLASS, 1, OC_POTION); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 65, NA, NULL); - addot(OT_POT_GASEOUSFORM, "potion of gaseous form", "Turns the drinker into a cloud of gas.", MT_GLASS, 1, OC_POTION); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); - addot(OT_POT_HEALING, "potion of healing", "Restores 10-20 health to whoever drinks it.", MT_GLASS, 1, OC_POTION); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); - addot(OT_POT_HEALINGMIN, "potion of minor healing", "Restores 1-8 health to whoever drinks it.", MT_GLASS, 1, OC_POTION); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL); - - addot(OT_POT_INVULN, "potion of invulnerability", "Grants the drinker temporary immunity to physical harm.", MT_GLASS, 1, OC_POTION); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 40, NA, NULL); - + addot(OT_POT_RESTORATION, "potion of restoration", "Restores lost abilities to the drinker.", MT_GLASS, 1, OC_POTION); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); + addot(OT_POT_SPEED, "potion of haste", "Temporarily increasees the drinker's speed.", MT_GLASS, 1, OC_POTION); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); + addflag(lastot->flags, F_AIBOOSTITEM, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_AIFLEEITEM, B_TRUE, NA, NA, NULL); addot(OT_POT_MAGIC, "potion of magic", "Fully restores the drinker's magical energy.", MT_GLASS, 1, OC_POTION); addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); - - addot(OT_POT_OIL, "potion of oil", "A bottle of cooking oil.", MT_GLASS, 1, OC_POTION); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); - - addot(OT_POT_POLYMORPH, "potion of polymorph self", "Transmutes the drinker into another living race.", MT_GLASS, 1, OC_POTION); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); - addflag(lastot->flags, F_MISSILE, B_TRUE, NA, NA, NULL); + addot(OT_POT_ELEMENTIMMUNE, "potion of elemental immunity", "Grants the imbiber temporary immunity to both fire and cold.", MT_GLASS, 1, OC_POTION); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL); addot(OT_POT_SANCTUARY, "potion of sanctuary", "Creates a temporary magical barrier abour the drinker.", MT_GLASS, 1, OC_POTION); addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL); - addot(OT_POT_RESTORATION, "potion of restoration", "Restores lost abilities to the drinker.", MT_GLASS, 1, OC_POTION); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); + addot(OT_POT_ETHEREALNESS, "potion of etherealness", "Allows the walker to temporarily pass through walls.", MT_GLASS, 1, OC_POTION); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 65, NA, NULL); + addot(OT_POT_EXPERIENCE, "potion of experience", "Instantly grants the imbiber the next experience level.", MT_GLASS, 1, OC_POTION); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 40, NA, NULL); + + addot(OT_POT_COMPETENCE, "potion of competence", "Permemantly increases the drinker's strength, intelligence or dexterity.", MT_GLASS, 1, OC_POTION); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); + + addot(OT_POT_GASEOUSFORM, "potion of gaseous form", "Turns the drinker into a cloud of gas.", MT_GLASS, 1, OC_POTION); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); + addflag(lastot->flags, F_AIFLEEITEM, B_TRUE, NA, NA, NULL); + + addot(OT_POT_POLYMORPH, "potion of polymorph self", "Transmutes the drinker into another living race.", MT_GLASS, 1, OC_POTION); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); + addflag(lastot->flags, F_MISSILE, B_TRUE, NA, NA, NULL); + addot(OT_POT_INVULN, "potion of invulnerability", "Grants the drinker temporary immunity to physical harm.", MT_GLASS, 1, OC_POTION); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 40, NA, NULL); + addflag(lastot->flags, F_AIBOOSTITEM, B_TRUE, NA, NA, NULL); + addot(OT_POT_AMBROSIA, "vial of ambrosia", "The nectar of the gods, said to completely restore the drinker's health.", MT_GLASS, 1, OC_POTION); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 35, NA, NULL); + addflag(lastot->flags, F_AIHEALITEM, B_TRUE, NA, NA, NULL); + - addot(OT_POT_SPEED, "potion of haste", "Temporarily increasees the drinker's speed.", MT_GLASS, 1, OC_POTION); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); - addot(OT_POT_WATER, "potion of water", "Plain, regular water.", MT_GLASS, 1, OC_POTION); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL); - addot(OT_POT_JUICE, "potion of fruit juice", "Tasty (but not very fresh) fruit juice!", MT_GLASS, 1, OC_POTION); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, NULL); // scrolls addot(OT_SCR_NOTHING, "scroll of nothing", "Looks like a magic scroll, but doesn't do anything.", MT_PAPER, 0.5, OC_SCROLL); @@ -3532,6 +3822,8 @@ void initobjects(void) { addot(OT_SCR_CREATEMONSTER, "scroll of create monster", "Summons a (probably hostile) monster to a nearby location.", MT_PAPER, 0.5, OC_SCROLL); addflag(lastot->flags, F_LINKSPELL, OT_S_CREATEMONSTER, NA, NA, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); + addflag(lastot->flags, F_AIBOOSTITEM, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_AIFLEEITEM, B_TRUE, NA, NA, NULL); addot(OT_SCR_DETECTAURA, "scroll of detect aura", "Senses holiness or evil near the caster.", MT_PAPER, 0.5, OC_SCROLL); addflag(lastot->flags, F_LINKSPELL, OT_S_DETECTAURA, NA, NA, NULL); @@ -3546,10 +3838,14 @@ void initobjects(void) { addflag(lastot->flags, F_LINKSPELL, OT_S_DETECTMAGIC, NA, NA, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); - addot(OT_SCR_FLAMEPILLAR, "scroll of flame column", "Creates a tall pillar of flame.", MT_PAPER, 0.5, OC_SCROLL); + addot(OT_SCR_FLAMEPILLAR, "scroll of flame pillar", "Creates a tall pillar of flame.", MT_PAPER, 0.5, OC_SCROLL); addflag(lastot->flags, F_LINKSPELL, OT_S_FLAMEPILLAR, NA, NA, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); + addot(OT_SCR_FLAMEBURST, "scroll of flame burst", "Creates a radial blast of fire out from the caster.", MT_PAPER, 0.5, OC_SCROLL); + addflag(lastot->flags, F_LINKSPELL, OT_S_FLAMEBURST, NA, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); + addot(OT_SCR_ENCHANT, "scroll of enchantment", "Magically enhances a weapon or piece of armour.", MT_PAPER, 0.5, OC_SCROLL); addflag(lastot->flags, F_LINKSPELL, OT_S_ENCHANT, NA, NA, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); @@ -3569,6 +3865,7 @@ void initobjects(void) { addot(OT_SCR_LIGHT, "scroll of light", "Creates a permenant light source centred on the caster.", MT_PAPER, 0.5, OC_SCROLL); addflag(lastot->flags, F_LINKSPELL, OT_S_LIGHT, NA, NA, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL); + addflag(lastot->flags, F_AIFLEEITEM, B_TRUE, NA, NA, NULL); addot(OT_SCR_MAPPING, "scroll of sense surroundings", "Magically imbues the caster with a map of his/her surroundings.", MT_PAPER, 0.5, OC_SCROLL); addflag(lastot->flags, F_LINKSPELL, OT_S_MAPPING, NA, NA, NULL); @@ -3581,6 +3878,7 @@ void initobjects(void) { addot(OT_SCR_TELEPORTRND, "scroll of random teleportation", "Causes the caster to teleport to a random location within the same level.", MT_PAPER, 0.5, OC_SCROLL); addflag(lastot->flags, F_LINKSPELL, OT_S_TELEPORTRND, NA, NA, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); + addflag(lastot->flags, F_AIFLEEITEM, B_TRUE, NA, NA, NULL); addot(OT_SCR_REMOVECURSE, "scroll of remove curse", "Removes curses from all weilded equipment.", MT_PAPER, 0.5, OC_SCROLL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 85, NA, NULL); @@ -3629,11 +3927,25 @@ void initobjects(void) { /////////////////// // death /////////////////// + // l2 + addot(OT_S_BLINDNESS, "blindness", "Temporarily blinds the target.", MT_NOTHING, 0, OC_SPELL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); + addflag(lastot->flags, F_AICASTATVICTIM, NA, NA, NA, NULL); // l3 + addot(OT_S_ANIMATEDEAD, "animate dead", "Imbues nearby corpses with life, creating an undead zombie.", MT_NOTHING, 0, OC_SPELL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); + // TODO: should be "castnearob ot_corpse" + addflag(lastot->flags, F_AICASTANYWHERE, NA, NA, NA, NULL); addot(OT_S_WEAKEN, "weaken", "Temporarily lowers the target's muscle strength.", MT_NOTHING, 0, OC_SPELL); addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); addflag(lastot->flags, F_AICASTATVICTIM, NA, NA, NA, NULL); + addot(OT_S_PAIN, "pain", "Causes extreme pain in the target whenever they move.", MT_NOTHING, 0, OC_SPELL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); + addflag(lastot->flags, F_AICASTATVICTIM, NA, NA, NA, NULL); // l8 addot(OT_S_INFINITEDEATH, "infinite death", "Annihilates all life on the caster's level!", MT_NOTHING, 0, OC_SPELL); addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); @@ -3663,28 +3975,56 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINATION, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 8, NA, NA, NULL); /////////////////// - // elemental + // elemental - air /////////////////// + // l3 + addot(OT_S_CLOUDKILL, "cloudkill", "Creates a 3x3 cloud of poisonous gas.", MT_NOTHING, 0, OC_SPELL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_AIR, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); + /////////////////// + // elemental - fire + /////////////////// + // l1 + addot(OT_S_SPARK, "spark", "Creates a tiny spark of flame, sufficient to ignite flammable objects but not enough to deal direct damage.", MT_NOTHING, 0, OC_SPELL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); // l2 addot(OT_S_FIREDART, "flame dart", "Fires a medium-sized dart of fire, dealing 2-6 fire damage.", MT_NOTHING, 0, OC_SPELL); - addflag(lastot->flags, F_SPELLSCHOOL, SS_ELEMENTAL, NA, NA, NULL); - addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); - addflag(lastot->flags, F_AICASTATVICTIM, NA, NA, NA, NULL); - addot(OT_S_CONECOLD, "cone of cold", "Shoots a blast of ice cold air, dealing 2-6 cold damage.", MT_NOTHING, 0, OC_SPELL); - addflag(lastot->flags, F_SPELLSCHOOL, SS_ELEMENTAL, NA, NA, NULL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); addflag(lastot->flags, F_AICASTATVICTIM, NA, NA, NA, NULL); // l3 addot(OT_S_FLAMEPILLAR, "flame pillar", "Creates a tall pillar of flame.", MT_NOTHING, 0, OC_SPELL); - addflag(lastot->flags, F_SPELLSCHOOL, SS_ELEMENTAL, NA, NA, NULL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); addflag(lastot->flags, F_AICASTATVICTIM, NA, NA, NA, NULL); // l4 - addot(OT_S_FIREBALL, "fireball", "Creates a huge ball of fire.", MT_NOTHING, 0, OC_SPELL); - addflag(lastot->flags, F_SPELLSCHOOL, SS_ELEMENTAL, NA, NA, NULL); + addot(OT_S_FLAMEBURST, "flame burst", "Creates a radial blast of fire out from the caster.", MT_NOTHING, 0, OC_SPELL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); + addflag(lastot->flags, F_AICASTNEXTTOVICTIM, NA, NA, NA, NULL); + // l5 + addot(OT_S_BURNINGWAVE, "burning wave", "Fire bursts from the ground in a line towards the target.", MT_NOTHING, 0, OC_SPELL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); + addflag(lastot->flags, F_AICASTATVICTIM, NA, NA, NA, NULL); + addflag(lastot->flags, F_RANGE, 3, NA, NA, NULL); + addot(OT_S_FIREBALL, "fireball", "Creates a huge ball of fire.", MT_NOTHING, 0, OC_SPELL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 5, NA, NA, NULL); addflag(lastot->flags, F_AICASTATVICTIM, NA, NA, NA, NULL); // TODO: should be "near victim" /////////////////// + // elemental - ice + /////////////////// + // l2 + addot(OT_S_CONECOLD, "cone of cold", "Shoots a blast of ice cold air, dealing 2-6 cold damage.", MT_NOTHING, 0, OC_SPELL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_ICE, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); + addflag(lastot->flags, F_AICASTATVICTIM, NA, NA, NA, NULL); + addot(OT_S_FREEZEOB, "freezing touch", "Permenantly changes the next object touched into solid ice.", MT_NOTHING, 0, OC_SPELL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); + /////////////////// // gravity /////////////////// // l4 @@ -3721,10 +4061,15 @@ void initobjects(void) { /////////////////// // mental /////////////////// - // l2 + // l1 addot(OT_S_MINDSCAN, "mind scan", "Reveals detailed information about the target.", MT_NOTHING, 0, OC_SPELL); addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); + // l2 + addot(OT_S_SLEEP, "sleep", "Puts the target creature to sleep.", MT_NOTHING, 0, OC_SPELL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); + addflag(lastot->flags, F_AICASTATVICTIM, NA, NA, NA, NULL); addot(OT_S_TELEKINESIS, "telekinesis", "Mentally move or manipulate nearby objects.", MT_NOTHING, 0, OC_SPELL); addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); @@ -3743,10 +4088,10 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); addflag(lastot->flags, F_AICASTANYWHERE, NA, NA, NA, NULL); - // l2 - addot(OT_S_FREEZEOB, "freezing touch", "Permenantly changes the next object touched into solid ice.", MT_NOTHING, 0, OC_SPELL); + addot(OT_S_DARKNESS, "darkness", "Permenantly darkens the area around the caster.", MT_NOTHING, 0, OC_SPELL); addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL); - addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); + addflag(lastot->flags, F_AICASTANYWHERE, NA, NA, NA, NULL); // l3 addot(OT_S_PASSWALL, "passwall", "Allows the caster to temporarily walk through walls.", MT_NOTHING, 0, OC_SPELL); addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL); @@ -3758,6 +4103,10 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); addflag(lastot->flags, F_AICASTATSELF, NA, NA, NA, NULL); // l6 + addot(OT_S_PETRIFY, "petrify", "Causes the target mosnter to turn into stone.", MT_NOTHING, 0, OC_SPELL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 6, NA, NA, NULL); + addflag(lastot->flags, F_AICASTATVICTIM, NA, NA, NA, NULL); addot(OT_S_POLYMORPHRND, "polymorph", "Transmutes the target into a random living race.", MT_NOTHING, 0, OC_SPELL); addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 6, NA, NA, NULL); @@ -3824,7 +4173,7 @@ void initobjects(void) { addot(OT_S_ENERGYBLAST, "energy blast", "Causes a ring of energy to expand from the caster, causing 2-6 damage to anything in sight.", MT_NOTHING, 0, OC_SPELL); addflag(lastot->flags, F_SPELLSCHOOL, SS_WILD, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); - addflag(lastot->flags, F_AICASTANYWHERE, NA, NA, NA, NULL); + addflag(lastot->flags, F_AICASTNEXTTOVICTIM, NA, NA, NA, NULL); addot(OT_S_FLASH, "flash", "Causes a very bright flash, stunning anyone who sees it.", MT_NOTHING, 0, OC_SPELL); addflag(lastot->flags, F_SPELLSCHOOL, SS_WILD, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); @@ -3844,19 +4193,32 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLLEVEL, 9, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINE, NA, NA, NULL); // abilities + addot(OT_A_GRAB, "grab", "You can grab hold of nearby enemies to prevent their escape.", MT_NOTHING, 0, OC_ABILITY); + addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); + addflag(lastot->flags, F_AICASTATADJVICTIM, NA, NA, NA, NULL); addot(OT_A_JUMP, "jump", "You can leap large distances.", MT_NOTHING, 0, OC_ABILITY); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addot(OT_A_SPRINT, "sprint", "You can run at high speed over short distances.", MT_NOTHING, 0, OC_ABILITY); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); + addflag(lastot->flags, F_AICASTATSELF, NA, NA, NA, NULL); addot(OT_A_DEBUG, "debug", "You can toggle debugging for a lifeform.", MT_NOTHING, 0, OC_ABILITY); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addot(OT_A_EMPLOY, "employ", "Assigns a job to the target lifeform.", MT_NOTHING, 0, OC_ABILITY); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); + addot(OT_A_HEAVYBLOW, "heavy blow", "Mighty blow which knocks enemies backwards.", MT_NOTHING, 0, OC_ABILITY); + addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); + addflag(lastot->flags, F_AICASTATADJVICTIM, NA, NA, NA, NULL); // spellbooks + addot(OT_SB_ANIMATEDEAD, "spellbook of animate dead", "Teaches the spell 'animate dead'.", MT_PAPER, 1.5, OC_BOOK); + addflag(lastot->flags, F_LINKSPELL, OT_S_ANIMATEDEAD, NA, NA, NULL); + addot(OT_SB_PAIN, "spellbook of pain", "Teaches the spell 'pain'.", MT_PAPER, 1.5, OC_BOOK); + addflag(lastot->flags, F_LINKSPELL, OT_S_PAIN, NA, NA, NULL); addot(OT_SB_WEAKEN, "spellbook of weaken", "Teaches the spell 'weaken'.", MT_PAPER, 1.5, OC_BOOK); addflag(lastot->flags, F_LINKSPELL, OT_S_WEAKEN, NA, NA, NULL); + addot(OT_SB_BLINDNESS, "spellbook of blindness", "Teaches the spell 'blindness'.", MT_PAPER, 1.5, OC_BOOK); + addflag(lastot->flags, F_LINKSPELL, OT_S_BLINDNESS, NA, NA, NULL); addot(OT_SB_INFINITEDEATH, "spellbook of infinite death", "Teaches the spell 'infinite death'.", MT_PAPER, 1.5, OC_BOOK); addflag(lastot->flags, F_LINKSPELL, OT_S_INFINITEDEATH, NA, NA, NULL); // divination @@ -3868,13 +4230,18 @@ void initobjects(void) { addflag(lastot->flags, F_LINKSPELL, OT_S_DETECTAURA, NA, NA, NULL); addot(OT_SB_IDENTIFY, "spellbook of identification", "Teaches the spell 'identification'.", MT_PAPER, 1.5, OC_BOOK); addflag(lastot->flags, F_LINKSPELL, OT_S_IDENTIFY, NA, NA, NULL); - // elemental + // elemental - air + addot(OT_SB_CLOUDKILL, "spellbook of cloudkill", "Teaches the spell 'cloudkill'.", MT_PAPER, 1.5, OC_BOOK); + addflag(lastot->flags, F_LINKSPELL, OT_S_CLOUDKILL, NA, NA, NULL); + // elemental - fire + addot(OT_SB_SPARK, "spellbook of spark", "Teaches the spell 'spark'.", MT_PAPER, 1.5, OC_BOOK); + addflag(lastot->flags, F_LINKSPELL, OT_S_SPARK, NA, NA, NULL); addot(OT_SB_FIREDART, "spellbook of flame dart", "Teaches the spell 'flame dart'.", MT_PAPER, 1.5, OC_BOOK); addflag(lastot->flags, F_LINKSPELL, OT_S_FIREDART, NA, NA, NULL); - addot(OT_SB_CONECOLD, "spellbook of cone of cold", "Teaches the spell 'cone of cold'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_CONECOLD, NA, NA, NULL); addot(OT_SB_FLAMEPILLAR, "spellbook of flame pillar", "Teaches the spell 'flame pillar'.", MT_PAPER, 1.5, OC_BOOK); addflag(lastot->flags, F_LINKSPELL, OT_S_FLAMEPILLAR, NA, NA, NULL); + addot(OT_SB_FLAMEBURST, "spellbook of flame burst", "Teaches the spell 'flame burst'.", MT_PAPER, 1.5, OC_BOOK); + addflag(lastot->flags, F_LINKSPELL, OT_S_FLAMEBURST, NA, NA, NULL); addot(OT_SB_FIREBALL, "spellbook of fireball", "Teaches the spell 'fireball'.", MT_PAPER, 1.5, OC_BOOK); addflag(lastot->flags, F_LINKSPELL, OT_S_FIREBALL, NA, NA, NULL); addot(OT_SB_SLOW, "spellbook of slowness", "Teaches the spell 'slowness'.", MT_PAPER, 1.5, OC_BOOK); @@ -3883,6 +4250,9 @@ void initobjects(void) { addflag(lastot->flags, F_LINKSPELL, OT_S_GRAVBOOST, NA, NA, NULL); addot(OT_SB_HASTE, "spellbook of haste", "Teaches the spell 'haste'.", MT_PAPER, 1.5, OC_BOOK); addflag(lastot->flags, F_LINKSPELL, OT_S_HASTE, NA, NA, NULL); + // elemental - ice + addot(OT_SB_CONECOLD, "spellbook of cone of cold", "Teaches the spell 'cone of cold'.", MT_PAPER, 1.5, OC_BOOK); + addflag(lastot->flags, F_LINKSPELL, OT_S_CONECOLD, NA, NA, NULL); // life addot(OT_SB_HEALINGMIN, "spellbook of minor healing", "Teaches the spell 'minor healing'.", MT_PAPER, 1.5, OC_BOOK); addflag(lastot->flags, F_LINKSPELL, OT_S_HEALINGMIN, NA, NA, NULL); @@ -3902,6 +4272,8 @@ void initobjects(void) { addflag(lastot->flags, F_LINKSPELL, OT_S_KNOCK, NA, NA, NULL); addot(OT_SB_LIGHT, "spellbook of light", "Teaches the spell 'light'.", MT_PAPER, 1.5, OC_BOOK); addflag(lastot->flags, F_LINKSPELL, OT_S_LIGHT, NA, NA, NULL); + addot(OT_SB_DARKNESS, "spellbook of darkness", "Teaches the spell 'darkness'.", MT_PAPER, 1.5, OC_BOOK); + addflag(lastot->flags, F_LINKSPELL, OT_S_DARKNESS, NA, NA, NULL); addot(OT_SB_FREEZEOB, "spellbook of freezing touch", "Teaches the spell 'freezing touch'.", MT_PAPER, 1.5, OC_BOOK); addflag(lastot->flags, F_LINKSPELL, OT_S_FREEZEOB, NA, NA, NULL); addot(OT_SB_GASEOUSFORM, "spellbook of gaseous form", "Teaches the spell 'gaseous form'.", MT_PAPER, 1.5, OC_BOOK); @@ -3910,6 +4282,8 @@ void initobjects(void) { addot(OT_SB_PASSWALL, "spellbook of passwall", "Teaches the spell 'passwall'.", MT_PAPER, 1.5, OC_BOOK); addflag(lastot->flags, F_LINKSPELL, OT_S_PASSWALL, NA, NA, NULL); + addot(OT_SB_PETRIFY, "spellbook of petrify", "Teaches the spell 'petrify'.", MT_PAPER, 1.5, OC_BOOK); + addflag(lastot->flags, F_LINKSPELL, OT_S_PETRIFY, NA, NA, NULL); addot(OT_SB_POLYMORPHRND, "spellbook of polymorph", "Teaches the spell 'polymorph'.", MT_PAPER, 1.5, OC_BOOK); addflag(lastot->flags, F_LINKSPELL, OT_S_POLYMORPHRND, NA, NA, NULL); addot(OT_SB_POLYMORPH, "spellbook of controlled polymorph", "Teaches the spell 'controlled polymorph'.", MT_PAPER, 1.5, OC_BOOK); @@ -4009,6 +4383,10 @@ void initobjects(void) { 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_AICASTATVICTIM, NA, NA, NA, NULL); + addot(OT_WAND_WONDER, "wand of wonder", "Produces random effects.", MT_METAL, 0.5, OC_WAND); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); + addflag(lastot->flags, F_OPERNEEDTARGET, TT_NONE, NA, NA, NULL); + addflag(lastot->flags, F_AICASTATVICTIM, NA, NA, NA, NULL); // tech/tools addot(OT_POCKETWATCH, "pocket watch", "A portable timekeeping device made to be carried in a pocket.", MT_METAL, 0.1, OC_TECH); @@ -4181,6 +4559,19 @@ void initobjects(void) { addflag(lastot->flags, F_GLYPH, NA, NA, NA, "^"); addflag(lastot->flags, F_SHARP, 2, 5, NA, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL); + addot(OT_ICESHEET, "sheet of ice", "A large sheet of slippery ice.", MT_ICE, 0.5, OC_MISC); + addflag(lastot->flags, F_STACKABLE, NA, NA, NA, NULL); + addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_GLYPH, NA, NA, NA, "_"); + addflag(lastot->flags, F_DTCONVERT, DT_FIRE, NA, NA, "large puddle of water"); + addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "large puddle of water"); + addflag(lastot->flags, F_DIECONVERTTEXT, NA, NA, NA, "melts"); + addflag(lastot->flags, F_DIECONVERTTEXTPL, NA, NA, NA, "melt"); + addflag(lastot->flags, F_OBHP, 50, 50, NA, NULL); + addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL); + addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_SLIPPERY, 15, NA, NA, NULL); addot(OT_ICECHUNK, "chunk of ice", "A chunk of ice.", MT_ICE, 0.5, OC_MISC); addflag(lastot->flags, F_EDIBLE, B_TRUE, 3, NA, NULL); addflag(lastot->flags, F_STACKABLE, NA, NA, NA, NULL); @@ -4203,6 +4594,7 @@ void initobjects(void) { addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_GLYPH, NA, NA, NA, ","); addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_SLIPPERY, 1, NA, NA, NULL); addot(OT_SLIMEPOOL, "pool of slime", "A disgusting mass of sticky slime.", MT_WATER, 0, OC_MISC); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL); @@ -4217,6 +4609,7 @@ void initobjects(void) { addflag(lastot->flags, F_GLYPH, NA, NA, NA, "{"); addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_DTCONVERT, DT_COLD, NA, NA, "sheet of ice"); addot(OT_PUDDLEWATERL, "large puddle of water", "A large pool of water.", MT_WATER, 0, OC_MISC); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL); @@ -4224,25 +4617,49 @@ void initobjects(void) { addflag(lastot->flags, F_GLYPH, NA, NA, NA, "{"); addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_DTCONVERT, DT_COLD, NA, NA, "sheet of ice"); - addot(OT_BLOODSTAIN, "blood stain", "A small pool of blood.", MT_BLOOD, 0, OC_MISC); + addot(OT_BLOODSTAIN, "blood stain", "A dried stain of blood.", MT_BLOOD, 0, OC_MISC); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_GLYPH, NA, NA, NA, ","); addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); + addot(OT_BLOODSPLASH, "splash of blood", "A small pool of blood.", MT_BLOOD, 0, OC_MISC); + addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_GLYPH, NA, NA, NA, ","); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); + addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_SLIPPERY, 1, NA, NA, NULL); + addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "blood stain"); + addflag(lastot->flags, F_DIECONVERTTEXT, NA, NA, NA, "dries up"); + addflag(lastot->flags, F_DIECONVERTTEXTPL, NA, NA, NA, "dry up"); + addflag(lastot->flags, F_OBHP, 30, 30, NA, NULL); + addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL); + addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL); + + addot(OT_BLOODPOOL, "pool of blood", "A large pool of blood.", MT_BLOOD, 0, OC_MISC); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_GLYPH, NA, NA, NA, ","); addflag(lastot->flags, F_RARITY, H_DUNGEON, 65, NA, NULL); addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_SLIPPERY, 3, NA, NA, NULL); + addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "blood stain"); + addflag(lastot->flags, F_DIECONVERTTEXT, NA, NA, NA, "dries up"); + addflag(lastot->flags, F_DIECONVERTTEXTPL, NA, NA, NA, "dry up"); + addflag(lastot->flags, F_OBHP, 60, 60, NA, NULL); + addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL); + addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL); addot(OT_WOODENBARREL, "wooden barrel", "A solid wooden barrel.", MT_WOOD, 20, OC_MISC); addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, NULL); addflag(lastot->flags, F_GLYPH, NA, NA, NA, "("); - addflag(lastot->flags, F_IMPASSABLE, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_IMPASSABLE, SZ_LARGE, NA, NA, NULL); + addflag(lastot->flags, F_CRUSHABLE, SZ_HUGE, NA, NA, NULL); addflag(lastot->flags, F_PUSHABLE, 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); @@ -4342,7 +4759,7 @@ void initobjects(void) { addot(OT_MAGICBARRIER, "magical barrier", "A glowing, impassable barrier of magical energy.", MT_MAGIC, 0, OC_EFFECT); addflag(lastot->flags, F_GLYPH, NA, NA, NA, "#"); addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); - addflag(lastot->flags, F_IMPASSABLE, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_IMPASSABLE, SZ_MAX, NA, NA, NULL); addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL); addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL); @@ -4357,17 +4774,48 @@ void initobjects(void) { addflag(lastot->flags, F_EVASION, 0, NA, NA, NULL); addflag(lastot->flags, F_OBHP, 1, 1, NA, NULL); addot(OT_ARMOURLEATHER, "leather armour", "Body armour created from soft leather.", MT_LEATHER, 10, OC_ARMOUR); - addflag(lastot->flags, F_RARITY, H_ALL, 70, NA, NULL); + addflag(lastot->flags, F_RARITY, H_ALL, 80, NA, NULL); addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL); addflag(lastot->flags, F_ARMOURRATING, 4, NA, NA, NULL); addflag(lastot->flags, F_EVASION, 0, NA, NA, NULL); addflag(lastot->flags, F_OBHP, 20, 20, NA, NULL); - addot(OT_FLAKJACKET, "flak jacket", "Metal body armour, designed to stop bullets.", MT_METAL, 20, OC_ARMOUR); + addot(OT_ARMOURRING, "suit of ring mail", "Body armour formed by a series of metallic rings sewn to a leather foundation.", MT_METAL, 15, OC_ARMOUR); + addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, NULL); + addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL); + addflag(lastot->flags, F_ARMOURRATING, 6, NA, NA, NULL); + addflag(lastot->flags, F_EVASION, -10, NA, NA, NULL); + addflag(lastot->flags, F_OBHP, 30, 30, NA, NULL); + addot(OT_ARMOURSCALE, "suit of scale armour", "Body armour consisting of many small scales attached to leather.", MT_METAL, 20, OC_ARMOUR); + addflag(lastot->flags, F_RARITY, H_ALL, 72, NA, NULL); + addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL); + addflag(lastot->flags, F_ARMOURRATING, 10, NA, NA, NULL); + addflag(lastot->flags, F_EVASION, -15, NA, NA, NULL); + addflag(lastot->flags, F_OBHP, 35, 35, NA, NULL); + addot(OT_ARMOURCHAIN, "suit of chainmail", "Heavy body armour consisting of tightly meshed metal rings.", MT_METAL, 25, OC_ARMOUR); + addflag(lastot->flags, F_RARITY, H_ALL, 70, NA, NULL); + addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL); + addflag(lastot->flags, F_ARMOURRATING, 15, NA, NA, NULL); + addflag(lastot->flags, F_EVASION, -20, NA, NA, NULL); + addflag(lastot->flags, F_OBHP, 45, 45, NA, NULL); + addot(OT_ARMOURSPLINT, "suit of splint mail", "Heavy armour, consisting of strips of metal attached to a leather backing.", MT_METAL, 35, OC_ARMOUR); + addflag(lastot->flags, F_RARITY, H_ALL, 67, NA, NULL); + addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL); + addflag(lastot->flags, F_ARMOURRATING, 20, NA, NA, NULL); + addflag(lastot->flags, F_EVASION, -25, NA, NA, NULL); + addflag(lastot->flags, F_OBHP, 50, 50, NA, NULL); + addot(OT_ARMOURPLATE, "suit of plate mail", "Heavy armour with embedded metal plates.", MT_METAL, 40, OC_ARMOUR); + addflag(lastot->flags, F_RARITY, H_ALL, 65, NA, NULL); + addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL); + addflag(lastot->flags, F_ARMOURRATING, 25, NA, NA, NULL); + addflag(lastot->flags, F_EVASION, -30, NA, NA, NULL); + addflag(lastot->flags, F_OBHP, 60, 60, NA, NULL); + + addot(OT_FLAKJACKET, "flak jacket", "Heavy metal body armour, designed to stop a bullet.", MT_METAL, 30, OC_ARMOUR); addflag(lastot->flags, F_RARITY, H_ALL, 25, NA, NULL); addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL); - addflag(lastot->flags, F_ARMOURRATING, 8, NA, NA, NULL); - addflag(lastot->flags, F_EVASION, -20, NA, NA, NULL); - addflag(lastot->flags, F_OBHP, 40, 40, NA, NULL); + addflag(lastot->flags, F_ARMOURRATING, 10, NA, NA, NULL); + addflag(lastot->flags, F_EVASION, -10, NA, NA, NULL); + addflag(lastot->flags, F_OBHP, 10, 10, NA, NULL); addot(OT_OVERALLS, "pair of overalls", "Well-made, brightly coloured workman overalls.", MT_CLOTH, 1, OC_ARMOUR); addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, NULL); addflag(lastot->flags, F_GOESON, BP_LEGS, NA, NA, NULL); @@ -4443,6 +4891,13 @@ void initobjects(void) { addflag(lastot->flags, F_EVASION, -10, NA, NA, NULL); // bulky addflag(lastot->flags, F_OBHP, 8, 8, NA, NULL); addflag(lastot->flags, F_EQUIPCONFER, F_DTRESIST, DT_ELECTRIC, NA, NULL); + addot(OT_BOOTSSPIKED, "pair of spiked boots", "A plain pair of leather boots with spikes on the bottom.", MT_LEATHER, 3, OC_ARMOUR); + addflag(lastot->flags, F_RARITY, H_ALL, 70, NA, NULL); + addflag(lastot->flags, F_GOESON, BP_FEET, NA, NA, NULL); + addflag(lastot->flags, F_ARMOURRATING, 2, NA, NA, NULL); + addflag(lastot->flags, F_EVASION, 0, NA, NA, NULL); + addflag(lastot->flags, F_OBHP, 5, 5, NA, NULL); + addflag(lastot->flags, F_EQUIPCONFER, F_STABILITY, NA, NA, NULL); addot(OT_BOOTSLEATHER, "pair of leather boots", "A stout pair of leather boots.", MT_LEATHER, 4, OC_ARMOUR); addflag(lastot->flags, F_RARITY, H_ALL, 80, NA, NULL); addflag(lastot->flags, F_GOESON, BP_FEET, NA, NA, NULL); @@ -4540,7 +4995,21 @@ void initobjects(void) { addflag(lastot->flags, F_SHIELD, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_GOESON, BP_SECWEAPON, NA, NA, NULL); addflag(lastot->flags, F_ARMOURRATING, 4, NA, NA, NULL); + addflag(lastot->flags, F_OBHP, 10, 10, NA, NULL); + addot(OT_SHIELD, "shield", "A medium-sized metal shield.", MT_METAL, 4.00, OC_ARMOUR); + addflag(lastot->flags, F_RARITY, H_ALL, 80, NA, NULL); + addflag(lastot->flags, F_SHIELD, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_GOESON, BP_SECWEAPON, NA, NA, NULL); + addflag(lastot->flags, F_ARMOURRATING, 6, NA, NA, NULL); + addflag(lastot->flags, F_ACCURACY, -10, NA, NA, NULL); addflag(lastot->flags, F_OBHP, 20, 20, NA, NULL); + addot(OT_SHIELDLARGE, "large shield", "A large (if somewhat cumbersome) shield.", MT_METAL, 6.00, OC_ARMOUR); + addflag(lastot->flags, F_RARITY, H_ALL, 80, NA, NULL); + addflag(lastot->flags, F_SHIELD, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_GOESON, BP_SECWEAPON, NA, NA, NULL); + addflag(lastot->flags, F_ARMOURRATING, 8, NA, NA, NULL); + addflag(lastot->flags, F_ACCURACY, -15, NA, NA, NULL); + addflag(lastot->flags, F_OBHP, 30, 30, NA, NULL); // rings addot(OT_RING_INVULN, "ring of invulnerability", "Grants the caster complete immunity to physical harm.", MT_METAL, 0.1, OC_RING); @@ -4563,7 +5032,7 @@ void initobjects(void) { // // DAMTYPE _cannot_ be overridden (yet)! addot(OT_FISTS, "fists", "human fists", MT_FLESH, 0, OC_WEAPON); - addflag(lastot->flags, F_DAMTYPE, DT_BASH, NA, NA, NULL); + addflag(lastot->flags, F_DAMTYPE, DT_UNARMED, NA, NA, NULL); addflag(lastot->flags, F_DAM, 1, 2, NA, NULL); addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL); @@ -4577,16 +5046,6 @@ void initobjects(void) { addflag(lastot->flags, F_DAM, 1, 2, NA, NULL); addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL); - addot(OT_TOUCHPARALYZE, "paralyzing touch", "paralyzing touch object", MT_BONE, 0, OC_WEAPON); - addflag(lastot->flags, F_DAMTYPE, DT_TOUCH, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 0, 1, NA, NULL); - addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL); - addflag(lastot->flags, F_HITCONFER, F_PARALYZED, B_TRUE, NA, "2-4"); - addot(OT_TOUCHPARALYZE2, "strong paralyzing touch", "strong paralyzing touch object", MT_BONE, 0, OC_WEAPON); - addflag(lastot->flags, F_DAMTYPE, DT_TOUCH, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 0, 1, NA, NULL); - addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL); - addflag(lastot->flags, F_HITCONFER, F_PARALYZED, B_TRUE, NA, "5-10"); addot(OT_TAIL, "tail", "tail object", MT_FLESH, 0, OC_WEAPON); addflag(lastot->flags, F_DAMTYPE, DT_BASH, NA, NA, NULL); @@ -4603,6 +5062,70 @@ void initobjects(void) { addflag(lastot->flags, F_DAMTYPE, DT_ACID, NA, NA, NULL); addflag(lastot->flags, F_DAM, 1, 2, NA, NULL); addflag(lastot->flags, F_ACCURACY, 60, NA, NA, NULL); + addot(OT_TOUCHPARALYZE, "paralyzing touch", "paralyzing touch object", MT_BONE, 0, OC_WEAPON); + addflag(lastot->flags, F_DAMTYPE, DT_TOUCH, NA, NA, NULL); + addflag(lastot->flags, F_DAM, 0, 1, NA, NULL); + addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL); + addflag(lastot->flags, F_HITCONFER, F_PARALYZED, B_TRUE, NA, "2-4"); + addot(OT_TOUCHPARALYZE2, "strong paralyzing touch", "strong paralyzing touch object", MT_BONE, 0, OC_WEAPON); + addflag(lastot->flags, F_DAMTYPE, DT_TOUCH, NA, NA, NULL); + addflag(lastot->flags, F_DAM, 0, 1, NA, NULL); + addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL); + addflag(lastot->flags, F_HITCONFER, F_PARALYZED, B_TRUE, NA, "5-10"); + + // missiles + addot(OT_DART, "dart", "A small, sharp projectile weapon.", MT_WOOD, 0.5, OC_MISSILE); + addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, ""); + addflag(lastot->flags, F_MISSILEDAM, 2, NA, NA, ""); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, ""); + addflag(lastot->flags, F_NUMAPPEAR, 1, 10, NA, ""); + + addot(OT_NANODART, "nanodart", "A metal dart with a laser-sharpened point.", MT_METAL, 0.5, OC_MISSILE); + addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, ""); + addflag(lastot->flags, F_MISSILEDAM, 2, NA, NA, ""); + addflag(lastot->flags, F_ARMOURPIERCE, B_TRUE, NA, NA, ""); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, ""); + addflag(lastot->flags, F_NUMAPPEAR, 1, 10, NA, ""); + + addot(OT_JAVELIN, "javelin", "A long, sharp missile weapon.", MT_METAL, 1.5, OC_MISSILE); + addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, ""); + addflag(lastot->flags, F_MISSILEDAM, 3, NA, NA, ""); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, ""); + addflag(lastot->flags, F_NUMAPPEAR, 1, 3, NA, ""); + addflag(lastot->flags, F_OBHP, 5, 5, NA, ""); + + addot(OT_ARROW, "arrow", "A sharp wooden arrow.", MT_WOOD, 0.5, OC_MISSILE); + addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, ""); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, ""); + addflag(lastot->flags, F_NUMAPPEAR, 1, 10, NA, ""); + addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_OBHP, 2, 2, NA, NULL); + addflag(lastot->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL); + + addot(OT_BOLT, "bolt", "A sharp metal spike, meant for firing from a crossbow.", MT_METAL, 1, OC_MISSILE); + addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, ""); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, ""); + addflag(lastot->flags, F_NUMAPPEAR, 1, 5, NA, ""); + addflag(lastot->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL); + + + addot(OT_BULLET, "bullet", "A regular gun bullet.", MT_STONE, 0.1, OC_MISSILE); + addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, ""); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, ""); + addflag(lastot->flags, F_NUMAPPEAR, 1, 10, NA, ""); + addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_OBHP, 1, 1, NA, NULL); + addflag(lastot->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL); + + addot(OT_RUBBERBULLET, "rubber bullet", "A rubber gun bullet - does not do much damage.", MT_STONE, 0.1, OC_MISSILE); + addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, ""); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, ""); + addflag(lastot->flags, F_NUMAPPEAR, 1, 10, NA, ""); + addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_OBHP, 1, 1, NA, NULL); + addflag(lastot->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL); // stabbing weapons addot(OT_DAGGER, "dagger", "A short stabbing weapon with a pointed blade.", MT_METAL, 1, OC_WEAPON); @@ -4655,23 +5178,32 @@ void initobjects(void) { addflag(lastot->flags, F_PICKLOCKS, 10, B_BLUNTONFAIL, NA, NULL); // chopping weapons - addot(OT_AXE, "axe", "A short pole with a heavy, wedge-shaped blade for chopping.", MT_METAL, 2, OC_WEAPON); + addot(OT_AXE, "axe", "A short pole with a heavy, wedge-shaped blade for chopping.", MT_METAL, 4, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 150, NA, NA, NULL); addflag(lastot->flags, F_DAMTYPE, DT_CHOP, NA, NA, NULL); addflag(lastot->flags, F_DAM, 1, 4, 1, NULL); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); - addot(OT_BATTLEAXE, "battleaxe", "An axe specifically designed for combat.", MT_METAL, 3, OC_WEAPON); + addot(OT_HANDAXE, "hand axe", "A fast one-handed axe made for combat.", MT_METAL, 2, OC_WEAPON); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); + addflag(lastot->flags, F_OBATTACKDELAY, 120, NA, NA, NULL); + addflag(lastot->flags, F_DAMTYPE, DT_CHOP, NA, NA, NULL); + addflag(lastot->flags, F_DAM, 1, 6, 1, NULL); + addflag(lastot->flags, F_ACCURACY, 85, NA, NA, NULL); + addflag(lastot->flags, F_MISSILE, B_TRUE, NA, NA, NULL); + addot(OT_BATTLEAXE, "battleaxe", "An axe specifically designed for combat.", MT_METAL, 5, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 140, NA, NA, NULL); addflag(lastot->flags, F_DAMTYPE, DT_CHOP, NA, NA, NULL); addflag(lastot->flags, F_DAM, 1, 9, 1, NULL); + addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); - addot(OT_GREATAXE, "greataxe", "An enormous axe made designed for combat.", MT_METAL, 5, OC_WEAPON); + addot(OT_GREATAXE, "greataxe", "An enormous axe made designed for combat.", MT_METAL, 8, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 180, NA, NA, NULL); addflag(lastot->flags, F_DAMTYPE, DT_CHOP, NA, NA, NULL); addflag(lastot->flags, F_DAM, 1, 10, 2, NULL); + addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_ACCURACY, 70, NA, NA, NULL); // slashing weapons @@ -4722,6 +5254,13 @@ void initobjects(void) { addflag(lastot->flags, F_DAMTYPE, DT_SLASH, NA, NA, NULL); addflag(lastot->flags, F_DAM, 1, 6, NA, NULL); addflag(lastot->flags, F_ACCURACY, 70, NA, NA, NULL); + addot(OT_GREATSWORD, "greatsword", "A massive two-handed sword.", MT_METAL, 10, OC_WEAPON); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); + addflag(lastot->flags, F_OBATTACKDELAY, 180, NA, NA, NULL); + addflag(lastot->flags, F_DAMTYPE, DT_SLASH, NA, NA, NULL); + addflag(lastot->flags, F_DAM, 1, 12, 6, NULL); + addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); + addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); // polearms addot(OT_QUARTERSTAFF, "quarterstaff", "A long, stout pole.", MT_WOOD, 2, OC_WEAPON); @@ -4756,7 +5295,7 @@ void initobjects(void) { addflag(lastot->flags, F_ACCURACY, 65, NA, NA, NULL); addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OPERNEEDDIR, B_TRUE, NA, NA, "Use your spanner in which direction"); - addot(OT_CLUB, "club", "A heavy, blunt wooden instrument to hit things with.", MT_WOOD, 1.5, OC_WEAPON); + addot(OT_CLUB, "club", "A heavy, blunt wooden instrument to hit things with.", MT_STONE, 1.5, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 140, NA, NA, NULL); addflag(lastot->flags, F_DAMTYPE, DT_BASH, NA, NA, NULL); @@ -4768,6 +5307,18 @@ void initobjects(void) { addflag(lastot->flags, F_DAMTYPE, DT_BASH, NA, NA, NULL); addflag(lastot->flags, F_DAM, 1, 8, NA, NULL); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); + addot(OT_FLAIL, "flail", "A flexible chain attached to a heavy weight.", MT_METAL, 6, OC_WEAPON); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); + addflag(lastot->flags, F_OBATTACKDELAY, 140, NA, NA, NULL); + addflag(lastot->flags, F_DAMTYPE, DT_BASH, NA, NA, NULL); + addflag(lastot->flags, F_DAM, 2, 4, NA, NULL); + addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); + addot(OT_FLAILHEAVY, "heavy flail", "A flexible chain attached to a very heavy weight.", MT_METAL, 12, OC_WEAPON); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); + addflag(lastot->flags, F_OBATTACKDELAY, 155, NA, NA, NULL); + addflag(lastot->flags, F_DAMTYPE, DT_BASH, NA, NA, NULL); + addflag(lastot->flags, F_DAM, 2, 6, NA, NULL); + addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addot(OT_MORNINGSTAR, "morningstar", "A heavy, spiked mace.", MT_METAL, 3.5, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 150, NA, NA, NULL); @@ -4775,11 +5326,11 @@ void initobjects(void) { addflag(lastot->flags, F_DAM, 1, 10, NA, NULL); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); - addot(OT_GREATCLUB, "great club", "An enormous, very heavy, blunt instrument to hit things with.", MT_WOOD, 5, OC_WEAPON); + addot(OT_GREATCLUB, "great club", "An enormous, very heavy, blunt instrument to hit things with.", MT_STONE, 5, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 180, NA, NA, NULL); addflag(lastot->flags, F_DAMTYPE, DT_BASH, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 3, 4, NA, NULL); + addflag(lastot->flags, F_DAM, 1, 10, 5, NULL); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); @@ -4788,13 +5339,38 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); addflag(lastot->flags, F_FIREARM, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL); - //addflag(lastot->flags, F_DAMTYPE, DT_BASH, NA, NA, NULL); - //addflag(lastot->flags, F_DAM, 3, 4, NA, NULL); addflag(lastot->flags, F_FIRESPEED, 3, NA, NA, NULL); addflag(lastot->flags, F_ACCURACY, 70, NA, NA, NULL); addflag(lastot->flags, F_RANGE, 5, NA, NA, NULL); addflag(lastot->flags, F_AMMOOB, OT_STONE, NA, NA, NULL); + addot(OT_BOW, "bow", "A weapon which projects arrows via its elasticity.", MT_WOOD, 3, OC_WEAPON); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); + addflag(lastot->flags, F_FIREARM, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_FIRESPEED, 5, NA, NA, NULL); + addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); + addflag(lastot->flags, F_RANGE, 5, NA, NA, NULL); + addflag(lastot->flags, F_AMMOOB, OT_ARROW, NA, NA, NULL); + + addot(OT_LONGBOW, "longbow", "A very large (human-sized) bow, capable of firing arrows with great power.", MT_WOOD, 6, OC_WEAPON); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); + addflag(lastot->flags, F_FIREARM, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_FIRESPEED, 7, NA, NA, NULL); + addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); + addflag(lastot->flags, F_RANGE, 10, NA, NA, NULL); + addflag(lastot->flags, F_AMMOOB, OT_ARROW, NA, NA, NULL); + + addot(OT_CROSSBOWHAND, "hand crossbow", "A small one-handed crossbow. Fast to fire but slower than a full-sized one.", MT_WOOD, 3, OC_WEAPON); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); + addflag(lastot->flags, F_FIREARM, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_FIRESPEED, 5, NA, NA, NULL); + addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); + addflag(lastot->flags, F_RANGE, 10, NA, NA, NULL); + addflag(lastot->flags, F_AMMOOB, OT_BOLT, NA, NA, NULL); + addot(OT_REVOLVER, "revolver", "Basic one-handed firearm.", MT_METAL, 1, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL); addflag(lastot->flags, F_FIREARM, B_TRUE, NA, NA, NULL); @@ -4807,28 +5383,6 @@ void initobjects(void) { addflag(lastot->flags, F_AMMOOB, OT_BULLET, NA, NA, NULL); addflag(lastot->flags, F_AMMOOB, OT_RUBBERBULLET, NA, NA, NULL); - // ammo - addot(OT_BULLET, "bullet", "A regular gun bullet.", MT_STONE, 0.1, OC_MISC); - addflag(lastot->flags, F_GLYPH, NA, NA, NA, ";"); - addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, ""); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, ""); - addflag(lastot->flags, F_NUMAPPEAR, 1, 10, NA, ""); - addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); - addflag(lastot->flags, F_MISSILE, B_TRUE, NA, NA, NULL); - addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); - addflag(lastot->flags, F_OBHP, 1, 1, NA, NULL); - addflag(lastot->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL); - - addot(OT_RUBBERBULLET, "rubber bullet", "A rubber gun bullet - does not do much damage.", MT_STONE, 0.1, OC_MISC); - addflag(lastot->flags, F_GLYPH, NA, NA, NA, ";"); - addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, ""); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, ""); - addflag(lastot->flags, F_NUMAPPEAR, 1, 10, NA, ""); - addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); - addflag(lastot->flags, F_MISSILE, B_TRUE, NA, NA, NULL); - addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); - addflag(lastot->flags, F_OBHP, 1, 1, NA, NULL); - addflag(lastot->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL); // holy weapons addot(OT_HANDOFGOD, "hand of god", "The ultimate power.", MT_FLESH, 0.1, OC_WEAPON); //addflag(lastot->flags, F_RARITY, H_DUNGEON, RR_UNIQUE, NA, NULL); @@ -5062,6 +5616,25 @@ int isidentified(object_t *o) { return B_TRUE; } +int isimpassableob(object_t *o, lifeform_t *lf) { + flag_t *f; + f = hasflag(o->flags, F_IMPASSABLE); + if (f) { + enum LFSIZE lfsize; + enum LFSIZE blocksize; + + if (!lf) return B_TRUE; + + lfsize = getlfsize(lf); + blocksize = f->val[0]; + + if (lfsize <= blocksize) { + return B_TRUE; + } + } + return B_FALSE; +} + int ismetal(enum MATERIAL mat) { int metal = B_FALSE; switch (mat) { @@ -5337,6 +5910,36 @@ lifeform_t *makeanimated(lifeform_t *lf, object_t *o, int level) { return newlf; } +void makeduller(object_t *o, int howmuch) { + char obname[BUFLEN]; + int oldbonus,newbonus; + + // get object name before changing the bonus + getobname(o,obname, 1); + + oldbonus = getobbonus(o); + modbonus(o, -howmuch); + newbonus = getobbonus(o); + + if (newbonus < oldbonus) { + if (o->pile->owner) { + if (isplayer(o->pile->owner)) { + msg("Your %s seems duller!",noprefix(obname)); + } else if (haslos(player, o->pile->owner->cell)) { + char lfname[BUFLEN]; + getlfname(o->pile->owner, lfname); + msg("%s%s %s seems duller!",lfname, getpossessive(lfname), noprefix(obname)); + } + } else { + cell_t *obloc; + obloc = getoblocation(o); + if (haslos(player, obloc)) { + msg("%s seems duller!",obname); + } + } + } +} + void makeknown(enum OBTYPE otid) { knowledge_t *k; object_t *o; @@ -5487,8 +6090,10 @@ void modbonus(object_t *o, int amt) { } else { known = B_FALSE; } - addflag_real(o->flags, F_BONUS, amt, NA, NA, NULL, PERMENANT, known, -1); + f = addflag_real(o->flags, F_BONUS, amt, NA, NA, NULL, PERMENANT, known, -1); } + // enforce limit + limit(&f->val[0], -7, 7); } void obaction(object_t *o, char *text) { @@ -5546,10 +6151,11 @@ void obdie(object_t *o) { f = hasflag(o->flags, F_DIECONVERT); if (f) { flag_t *f2; + object_t *newob; char desc[BUFLEN]; if (!hasflag(o->flags, F_NODIECONVERTTEXT)) { // announce the change - real_getobname(o, obname, o->amt, B_FALSE, B_TRUE, B_TRUE); + real_getobname(o, obname, o->amt, B_TRUE, B_FALSE, B_TRUE, B_TRUE); f2 = NULL; if (o->amt > 1) { @@ -5573,22 +6179,29 @@ void obdie(object_t *o) { if (o->pile->owner->controller == C_PLAYER) { msg("Your %s %s!",noprefix(obname), desc); } else if (haslos(player, o->pile->owner->cell)) { - char monname[BUFLEN]; - getlfname(o->pile->owner, monname); - msg("%s's %s %s!",monname, noprefix(obname), desc); + // don't announce decay death unless we are holding it + if (oblastdamtype(o) != DT_DECAY) { + char monname[BUFLEN]; + getlfname(o->pile->owner, monname); + msg("%s's %s %s!",monname, noprefix(obname), desc); + } } } else if (haslos(player, o->pile->where)) { - capitalise(obname); - msg("%s %s.",obname, desc); + // don't announce decay death unless we are holding it + if (oblastdamtype(o) != DT_DECAY) { + capitalise(obname); + msg("%s %s.",obname, desc); + } } } // change into something else - addob(o->pile, f->text); + newob = addob(o->pile, f->text); + newob->amt = o->amt; } else { char desc[BUFLEN]; - real_getobname(o, obname, o->amt, B_FALSE, B_TRUE, B_TRUE); + real_getobname(o, obname, o->amt, B_TRUE, B_FALSE, B_TRUE, B_TRUE); if (!hasflag(o->flags, F_NOOBDIETEXT)) { // announce the death f = hasflag(o->flags, F_DIETEXT); @@ -5831,8 +6444,6 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { } */ - - if (hasflag(o->flags, F_OPERONOFF)) { // operating toggles on/off flag_t *f; f = hasflag(o->flags, F_ACTIVATED); @@ -5871,6 +6482,49 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { f = hasflag(o->flags, F_LINKSPELL); if (f) { dospelleffects(lf, f->val[0], where ? where->lf : NULL, NULL, where, o->blessed, &willid); + // special wands + } else if (o->type->id == OT_WAND_WONDER) { + // random effect + switch (rnd(0,6)) { + case 0: // slow + dospelleffects(lf, OT_S_SLOW, where ? where->lf : NULL, NULL, where, o->blessed, &willid); + break; + case 1: // gas + dospelleffects(lf, OT_S_CLOUDKILL, where ? where->lf : NULL, NULL, where, o->blessed, &willid); + break; + case 2: // butterflies around user + willid = B_TRUE; + where = getrandomadjcell(lf->cell, WE_NOTSOLID); + addmonster(where, R_BUTTERFLY, B_FALSE, rnd(10,20)); + if (haslos(player, where)) { + msg("A swarm of butterflies appears!"); + } + break; + case 3: // light + dospelleffects(lf, OT_S_LIGHT, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid); + break; + case 4: // dark + dospelleffects(lf, OT_S_DARKNESS, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid); + break; + case 5: // stone + dospelleffects(lf, OT_S_PETRIFY, where ? where->lf : NULL, NULL, where, o->blessed, &willid); + break; + case 6: // fireball + dospelleffects(lf, OT_S_FIREBALL, where ? where->lf : NULL, NULL, where, o->blessed, &willid); + break; +//oooooooooo + } + } + + if (!isknown(o) && willid) { + if (isplayer(lf) || haslos(player, lf->cell)) { + // tell player + makeknown(o->type->id); + if (isplayer(lf)) { + getobname(o, obname, 1); + msg("This is %s!",obname); + } + } } // FROM HERE ON ARE INDIVIDUAL ones } else if (o->type->id == OT_INSECTICIDE) { @@ -6014,7 +6668,13 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { ch = askchar("Dig in which direction (- to cancel)", "yuhjklbn-","-", B_FALSE); dir = chartodir(ch); c = getcellindir(player->cell, dir); - if (c) { + + if (!c) { + // cancel + clearmsg(); + return B_TRUE; + } + if (c->type->solid) { if (isdiggable(c)) { if (isplayer(lf)) { msg("You dig through the wall."); @@ -6026,19 +6686,78 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { // replace wall setcelltype(c, getemptycelltype(c->map->habitat)); // redraw screen + needredraw = B_TRUE; drawscreen(); // takes extra time taketime(lf, getactspeed(lf)*9); } else { + // fail if (isplayer(lf)) { msg("This wall is too hard to dig."); } } - } else { - if (isplayer(lf)) { - msg("You swing your %s through the air.",noprefix(obname)); + } else { // not solid + int failed = B_FALSE; + object_t *door; + + door = hasobwithflag(c->obpile, F_DOOR); + if (door) { + int dooropen; + // only closed doors! + isdoor(door, &dooropen); + if (dooropen) { + door = NULL; + } + } + + if (door) { + // TODO: metal doors are immune to CHOP damage + if (!isimmuneto(door->flags, DT_CHOP)) { + taketime(lf, getactspeed(lf)); + if (isplayer(lf)) { + msg("You smash open a door!"); + } else if (haslos(player, lf->cell)) { + char lfname[BUFLEN]; + getlfname(lf, lfname); + msg("%s smashes open a door.",lfname); + } + removeob(door, door->amt); + needredraw = B_TRUE; + drawscreen(); + failed = B_FALSE; + } + } else if (hasob(c->obpile, OT_STATUE)) { + int dam; + object_t *so; + char statname[BUFLEN]; + + so = hasob(c->obpile, OT_STATUE); + getobname(so, statname, so->amt); + + taketime(lf, getactspeed(lf)); + + // statue takes 1/2 damage + f = hasflag(so->flags, F_OBHP); + if (f) { + dam = (f->val[1] / 2); // ie. half max hp + } else { + dam = 1; + } + // statue ? + if (isplayer(lf)) { + msg("You hit %s with your %s.", statname, noprefix(obname)); + } else if (haslos(player, lf->cell)) { + char lfname[BUFLEN]; + getlfname(lf, lfname); + msg("%s hits %s with %s.", lfname, statname, obname); + } + takedamage(so, dam, DT_CHOP); + } else { + if (isplayer(lf)) { + msg("You swing your %s through the air.",noprefix(obname)); + } + taketime(lf, getactspeed(lf)); } - taketime(lf, getactspeed(lf)); } } else if (o->type->id == OT_SPANNER) { int donesomething = B_FALSE; @@ -6113,18 +6832,6 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { } } } - if (o->type->obclass->id == OC_WAND) { - if (!isknown(o) && willid) { - if (isplayer(lf) || haslos(player, lf->cell)) { - // tell player - makeknown(o->type->id); - if (isplayer(lf)) { - getobname(o, obname, 1); - msg("This is %s!",obname); - } - } - } - } return B_FALSE; } @@ -6241,19 +6948,19 @@ int pour(lifeform_t *lf, object_t *o) { changemat(dst, dst->type->material->id); } // remove blessings/curses - setblessed(o, B_UNCURSED); - o->blessknown = B_TRUE; + setblessed(dst, B_UNCURSED); + dst->blessknown = B_TRUE; // remove bonuses - killflagsofid(o->flags, F_BONUS); + killflagsofid(dst->flags, F_BONUS); // remove temporary flags - for (f = o->flags->first ; f ; f = nextf) { + for (f = dst->flags->first ; f ; f = nextf) { nextf = f->next; if (f->lifetime > 0) { killflag(f); } } - if (!isknown(o)) makeknown(o->type->id); + if (!isknown(dst)) makeknown(dst->type->id); } else { // default if (isplayer(lf)) { msg("You pour %s onto %s.", obname,dstname); @@ -6294,7 +7001,7 @@ void quaff(lifeform_t *lf, object_t *o) { playercansee = B_FALSE; } - taketime(lf, SPEED_DRINK); + taketime(lf, getactspeed(lf)); touch(lf, o); if (hasflag(o->flags, F_DEAD)) return; @@ -6334,7 +7041,7 @@ void quaff(lifeform_t *lf, object_t *o) { if (!isknown(o) && willid) { // id the potion makeknown(o->type->id); - real_getobname(o, obname, 1, B_TRUE, B_FALSE, B_FALSE); // don't adjust for blindness + real_getobname(o, obname, 1, B_FALSE, B_TRUE, B_FALSE, B_FALSE); // don't adjust for blindness if (isplayer(lf)) { // tell the player msg("This is %s!",obname); @@ -6438,7 +7145,7 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE isblessed, in switch (oid) { case OT_POT_ACID: - dam = rnd(5,15); + dam = rnd(5,10); losehp(lf, dam, DT_ACID, NULL, "drinking acid"); if (lf->controller == C_PLAYER) { msg("Your suffer massive internal burning!"); @@ -6568,6 +7275,19 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE isblessed, in case OT_POT_ETHEREALNESS: dospelleffects(lf, OT_S_PASSWALL, lf, NULL, NULL, isblessed, seen); break; + case OT_POT_EXPERIENCE: + // gain xp! + if (hasmr(lf)) { + if (isplayer(lf)) { + msg("You feel momentarily more experienced."); + } + break; + } + if (isplayer(lf)) { + msg("You feel more experienced!"); + } + gainxp(lf, getxpforlev(lf->level+1) - lf->xp); + break; case OT_POT_GASEOUSFORM: dospelleffects(lf, OT_S_GASEOUSFORM, lf, NULL, NULL, isblessed, seen); break; @@ -6654,10 +7374,9 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE isblessed, in } if (failed) { - if (seen) *seen = B_FALSE; - if (isplayer(lf)) nothinghappens(); - } else { - if (seen) *seen = B_TRUE; + if (isplayer(lf)) { + msg("You feel momentarily restored."); + } } break; case OT_POT_SANCTUARY: @@ -6706,7 +7425,7 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE isblessed, in } } -void readsomething(lifeform_t *lf, object_t *o) { +int readsomething(lifeform_t *lf, object_t *o) { flag_t *f; char buf[BUFLEN],obname[BUFLEN]; int playercansee; @@ -6715,6 +7434,10 @@ void readsomething(lifeform_t *lf, object_t *o) { objecttype_t *linkspell; int readtime; + if (isblind(lf)) { + return B_TRUE; + } + getobname(o, obname, 1); if ((lf->controller == C_PLAYER) || haslos(player, lf->cell)) { @@ -6734,7 +7457,7 @@ void readsomething(lifeform_t *lf, object_t *o) { // some checks first... touch(lf, o); if (hasflag(o->flags, F_DEAD)) { - return; + return B_TRUE; } @@ -6793,7 +7516,7 @@ void readsomething(lifeform_t *lf, object_t *o) { if (!isknown(o) && willid) { // id the scroll makeknown(o->type->id); - real_getobname(o, obname, 1, B_TRUE, B_FALSE, B_FALSE); // don't adjust for blindness + real_getobname(o, obname, 1, B_FALSE, B_TRUE, B_FALSE, B_FALSE); // don't adjust for blindness if (lf->controller == C_PLAYER) { // tell the player msg("This is %s!",obname); @@ -6891,7 +7614,7 @@ void readsomething(lifeform_t *lf, object_t *o) { // TODO: manuals etc? } } - + return B_FALSE; } object_t *relinkob(object_t *src, obpile_t *dst) { @@ -7063,6 +7786,27 @@ int takedamage(object_t *o, unsigned int howmuch, int damtype) { extinguish(o); } + // catches on fire? + if (damtype == DT_FIRE) { + if (isflammable(o)) { + ignite(o); + } + } + + // damage type converts this into something else? + f = hasflagval(o->flags, F_DTCONVERT, damtype, NA, NA, NULL); + if (f) { + object_t *newob; + newob = addob(o->pile, f->text); + newob->amt = o->amt; + + // object dies, but don't announce it + addflag(o->flags, F_DEAD, B_TRUE, NA, NA, NULL); + addflag(o->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL); + + return howmuch; + } + adjustdamob(o, &howmuch, damtype); if (howmuch <= 0) { return 0; @@ -7076,7 +7820,9 @@ int takedamage(object_t *o, unsigned int howmuch, int damtype) { addflag(o->flags, F_LASTDAMTYPE, damtype, NA, NA, NULL); } - real_getobname(o, obname, o->amt, B_FALSE, B_TRUE, B_TRUE); + + + real_getobname(o, obname, o->amt, B_TRUE, B_FALSE, B_TRUE, B_TRUE); getobconditionname(o, predamname); hpflag = hasflag(o->flags, F_OBHP); if (hpflag) { @@ -7086,6 +7832,7 @@ int takedamage(object_t *o, unsigned int howmuch, int damtype) { } if (!hpflag || (hpflag->val[0] <= 0)) { + // special cases.... if (damtype == DT_FIRE) { if (o->material->id == MT_FLESH) { // fire roasts flesh @@ -7136,27 +7883,22 @@ int takedamage(object_t *o, unsigned int howmuch, int damtype) { if (o->pile->owner->controller == C_PLAYER) { msg("Your %s %s!",noprefix(obname), getobhurtname(o, damtype)); } else if (haslos(player, o->pile->owner->cell)) { - char monname[BUFLEN]; - getlfname(o->pile->owner, monname); - msg("%s's %s %s!",monname, noprefix(obname), getobhurtname(o, damtype)); + // don't announce decay damage for object you aren't holding + if (damtype != DT_DECAY) { + char monname[BUFLEN]; + getlfname(o->pile->owner, monname); + msg("%s's %s %s!",monname, noprefix(obname), getobhurtname(o, damtype)); + } } } else if (haslos(player, o->pile->where)) { - capitalise(obname); - msg("%s %s!", obname, getobhurtname(o, damtype)); + // don't announce decay damage for object you aren't holding + if (damtype != DT_DECAY) { + msg("%s %s!", obname, getobhurtname(o, damtype)); + } } } - // catches on fire? - if (damtype == DT_FIRE) { - if (isflammable(o)) { - f = hasflag(o->flags, F_ONFIRE); - if (!f) { - // on fire for 2 turns - addtempflag(o->flags, F_ONFIRE, B_TRUE, NA, NA, NULL, 2); - } - } - } // explodes? f = hasflag(o->flags, F_EXPLODEONDAM); @@ -7217,6 +7959,7 @@ int fireat(lifeform_t *thrower, object_t *o, cell_t *where, int speed, object_t char throwverbpres[BUFLEN]; int acc; int youhit; + int db = B_TRUE; reason = E_OK; @@ -7341,7 +8084,7 @@ int fireat(lifeform_t *thrower, object_t *o, cell_t *where, int speed, object_t msg("Something %ss %s.",throwverbpres, obname); } */ - sprintf(throwstring, "%s %s through the air", obname, (o->amt == 1) ? "flies" : "fly"); + sprintf(throwstring, "%s flies through the air", obname); if (target && haslos(player, where)) { strcat(throwstring, " towards "); strcat(throwstring, targetname); @@ -7402,7 +8145,7 @@ int fireat(lifeform_t *thrower, object_t *o, cell_t *where, int speed, object_t // saving throw if (youhit) { - if (savingthrow(target, A_DEX, 0)) { + if (skillcheck(target, SC_DODGE, 20, 0)) { youhit = B_FALSE; } } @@ -7421,7 +8164,12 @@ int fireat(lifeform_t *thrower, object_t *o, cell_t *where, int speed, object_t if (youhit) { int dam = 0,shatterdam = 0; char damstring[BUFLEN]; - dam = getthrowdam(o) * speed; + int reduceamt = 0; + int throwdam; + + throwdam = getthrowdam(o); + dam = throwdam * speed; + if (db) dblog("fireat(): dam = throwdam(%d) * speed(%d) = %d",throwdam, speed, dam); // special case if (o->type->id == OT_RUBBERBULLET) { @@ -7453,10 +8201,20 @@ int fireat(lifeform_t *thrower, object_t *o, cell_t *where, int speed, object_t } sprintf(damstring, "%s (%s by %s)",obname,throwverbpast, throwernamea); - // TODO: at the moment you won't get experience if you telekenetically - // throw an object at something. is this okay? - losehp(target, dam, DT_PROJECTILE, (thrower->cell == srcloc) ? thrower : NULL, damstring); + reduceamt = getarmourdamreduction(target, o, dam, DT_PROJECTILE); + + applyarmourdamreduction(target, o, reduceamt, &dam, DT_PROJECTILE); + + if (dam > 0) { + // TODO: at the moment you won't get experience if you telekenetically + // throw an object at something. is this okay? + losehp(target, dam, DT_PROJECTILE, (thrower->cell == srcloc) ? thrower : NULL, damstring); + } + if (reduceamt && (speed >= 3)) { + applyarmourdamage(target, o, reduceamt, DT_PROJECTILE); + } + if (shatterdam && !isdead(target)) { // extra glass damage if (seen) { @@ -7604,8 +8362,19 @@ int fireat(lifeform_t *thrower, object_t *o, cell_t *where, int speed, object_t } } } + } + // heavy ob? + if (youhit && target) { + if (getobweight(o) >= getlfweight(target, B_NOOBS)) { + int dir; + dir = getdirtowards(thrower->cell, target->cell, target, B_FALSE); + knockback(target, dir, 1, thrower); + } + } + + if (shattered) { // now remove the object removeob(o, 1); } else { @@ -7615,6 +8384,7 @@ int fireat(lifeform_t *thrower, object_t *o, cell_t *where, int speed, object_t newob->birthtime = -1; takedamage(newob, speed, DT_BASH); } + return B_FALSE; } @@ -7964,7 +8734,7 @@ void turnoff(lifeform_t *lf, object_t *o) { removeob(o, 1); stackob->amt++; getobname(stackob, stackname, stackob->amt); - msglower("%c - %s.",stackob->letter, stackname); + msgnocap("%c - %s.",stackob->letter, stackname); } else { // just turn off killflag(f); @@ -8022,7 +8792,7 @@ void turnon(lifeform_t *lf, object_t *o) { // announce new ob addflag(newob->flags, F_ACTIVATED, B_TRUE, NA, NA, NULL); getobname(newob, newobname, 1); - msglower("%c - %s [activated].",newob->letter, newobname); + msgnocap("%c - %s [activated].",newob->letter, newobname); } else { if (isplayer(lf)) { msg("You don't have room for an activated %s!",noprefix(obname)); diff --git a/objects.h b/objects.h index d9d96c1..faf4e19 100644 --- a/objects.h +++ b/objects.h @@ -8,6 +8,7 @@ material_t *addmaterial(enum MATERIAL id, char *name, float weightrating); objectclass_t *addoc(enum OBCLASS id, char *name, char *desc, char glyph); object_t *addob(obpile_t *where, char *name); object_t *addobject(obpile_t *where, char *name, int canstack); +int addobburst(cell_t *where, int range, int dirtype, char *name); obmod_t *addobmod(enum OBMOD id, char *suffix, enum BODYPART bp); obpile_t *addobpile(lifeform_t *owner, cell_t *where); objecttype_t *addot(int id, char *name, char *description, int material, float weight, int obclassid); @@ -20,6 +21,7 @@ void brightflash(cell_t *centre, int range, lifeform_t *immunelf); object_t *canstackob(obpile_t *op, object_t *match); object_t *canstacknewot(obpile_t *op, objecttype_t *match); int changemat(object_t *o, enum MATERIAL mat); +objecttype_t *checkobnames(char *haystack, char *needle); void copyobprops(object_t *dst, object_t *src); int countnames(char **list); int countobs(obpile_t *op); @@ -41,6 +43,7 @@ int geteffecttime(int min, int max, enum BLESSTYPE isblessed); objecttype_t *getlinkspell(object_t *o); int getmissileaccuracy(lifeform_t *thrower, cell_t *where, object_t *missile, object_t *firearm, enum ATTRIB whichatt); int getobaccuracy(object_t *wep); +int getobbonus(object_t *o); int getobvalue(object_t *o); //int getobtypevalue(objecttype_t *ot); char *getaccuracyname(int accpct); @@ -55,6 +58,7 @@ char getglyph(object_t *o); char *genhiddenname(enum OBCLASS id); char *gethiddenname(object_t *o); int getobattackdelay(object_t *o); +float getobhppct(object_t *o); int getletindex(char let); int getmaterialvalue(enum MATERIAL mat ); int getmaxthrowrange(lifeform_t *lf, object_t *o); @@ -63,9 +67,10 @@ int getnumshards(object_t *o); int getnutritionbase(object_t *o); int getnutrition(object_t *o); char *getobdesc(object_t *o, char *buf); +char *getobextrainfo(object_t *o, char *buf); cell_t *getoblocation(object_t *o); char *getobname(object_t *o, char *buf, int count); -char *real_getobname(object_t *o, char *buf, int count, int wantcondition, int adjustforblind, int wantblesscurse); +char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wantcondition, int adjustforblind, int wantblesscurse); float getobpileweight(obpile_t *op); char *getobconditionname(object_t *o, char *buf); char *getobhurtname(object_t *o, enum DAMTYPE damtype); @@ -76,6 +81,7 @@ char *real_getrandomob(map_t *map, char *buf, int cond, int cval, int forcedepth char *getrandomob(map_t *map, char *buf); char *getrandomobwithdt(map_t *map, enum DAMTYPE damtype, char *buf); char *getrandomobwithclass(map_t *map, enum OBCLASS cid, char *buf); +enum SPELLSCHOOL getschool(enum OBTYPE sid); char *getschoolname(enum SPELLSCHOOL sch); int getshatterdam(object_t *o); int getthrowdam(object_t *o); @@ -88,6 +94,7 @@ object_t *hasobwithflag(obpile_t *op, enum FLAG flagid); object_t *hasobwithflagval(obpile_t *op, enum FLAG flagid, int val0, int val1, int val2, char *text); object_t *hasobid(obpile_t *op, int id); void identify(object_t *o); +void ignite(object_t *o); void initobjects(void); flag_t *isarmour(object_t *o); int isactivated(object_t *o); @@ -107,6 +114,7 @@ int isfirearm(object_t *o); int isflammable(object_t *o); int isknown(object_t *o); int isidentified(object_t *o); +int isimpassableob(object_t *o, lifeform_t *lf); int ismetal(enum MATERIAL mat); int ismissile(object_t *o); int isoperable(object_t *o); @@ -123,6 +131,7 @@ void killobpile(obpile_t *o); void killoc(objectclass_t *oc); void killot(objecttype_t *ot); lifeform_t *makeanimated(lifeform_t *lf, object_t *o, int level); +void makeduller(object_t *o, int howmuch); void makeknown(enum OBTYPE otid); object_t *moveob(object_t *src, obpile_t *dst, int howmany); void modbonus(object_t *o, int amt); @@ -141,7 +150,7 @@ int pilehasletter(obpile_t *op, char let); void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE isblessed, int *seen); int pour(lifeform_t *lf, object_t *o); void quaff(lifeform_t *lf, object_t *o); -void readsomething(lifeform_t *lf, object_t *o); +int readsomething(lifeform_t *lf, object_t *o); void removedeadobs(obpile_t *op); int removeob(object_t *o, int howmany); object_t *relinkob(object_t *src, obpile_t *dst); diff --git a/spell.c b/spell.c index f970310..4195f91 100644 --- a/spell.c +++ b/spell.c @@ -4,6 +4,7 @@ #include #include #include +#include "attack.h" #include "defs.h" #include "flag.h" #include "io.h" @@ -21,28 +22,77 @@ extern WINDOW *msgwin; extern job_t *firstjob; -int abilityeffects(lifeform_t *user, enum OBTYPE abilid) { +int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifeform_t *target) { char username[BUFLEN]; char buf[BUFLEN]; + flag_t *f; + getlfname(user, username); - if (abilid == OT_A_JUMP) { + if (abilid == OT_A_GRAB) { + char dirch; + flag_t *f; + + f = lfhasflag(user, F_GRABBING); + if (f) { + if (isplayer(user)) msg("You are already holding someone!"); + return B_TRUE; + } + f = lfhasflag(user, F_GRABBEDBY); + if (f) { + if (isplayer(user)) msg("You are already being held by someone!"); + return B_TRUE; + } + + // ask for direction + if (!targcell) { + dirch = askchar("Grab in which direction (- to cancel)", "yuhjklbn.-","-", B_FALSE); + if (dirch == '.') { + if (isplayer(user)) msg("You can't grab yourself!"); + return B_TRUE; + } else { + int dir; + dir = chartodir(dirch); + if (dir == D_NONE) { + if (isplayer(user)) msg("Cancelled."); + return B_TRUE ; + } else { + targcell = getcellindir(user->cell, dir); + } + } + } + + target = targcell->lf; + if (!target) { + if (isplayer(user)) msg("There is nobody there to grab!"); + return B_TRUE; + } + + addflag(user->flags, F_GRABBING, target->id, NA, NA, NULL); + addflag(target->flags, F_GRABBEDBY, user->id, NA, NA, NULL); + } else if (abilid == OT_A_JUMP) { lifeform_t *victim = NULL; char victimname[BUFLEN]; int dodged = B_FALSE; - cell_t *where = NULL, *origcell; - sprintf(buf, "Jump where (max distance 2)?"); - while (!where) { - // ask where - where = askcoords(buf, TT_NONE); - if (!where) { - return B_TRUE; - } else if (getcelldist(user->cell, where) > 2) { - where = NULL; - sprintf(buf, "You can't jump that far! Jump where (max distance 2)?"); - } else if (!haslos(user, where)) { - where = NULL; - sprintf(buf, "You can't see where to land! Jump where (max distance 2)?"); + cell_t *origcell; + if (!targcell) { + sprintf(buf, "Jump where (max distance 2)?"); + while (!targcell) { + // ask where + targcell = askcoords(buf, TT_NONE); + if (!targcell) { + return B_TRUE; + } else if (getcelldist(user->cell, targcell) > 2) { + targcell = NULL; + if (isplayer(user)) { + sprintf(buf, "You can't jump that far! Jump where (max distance 2)?"); + } + } else if (!haslos(user, targcell)) { + targcell = NULL; + if (isplayer(user)) { + sprintf(buf, "You can't see where to land! Jump where (max distance 2)?"); + } + } } } @@ -63,7 +113,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid) { origcell = user->cell; // did you land on anyone? - victim = haslf(where); + victim = haslf(targcell); if (victim) { cell_t *c; int acc; @@ -86,7 +136,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid) { dodged = B_TRUE; } } - movelf(user, where); + movelf(user, targcell); // announce if (isplayer(user)) { @@ -140,11 +190,16 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid) { msg("You are too tired to sprint right now."); } return B_TRUE; + } else if (lfhasflag(user, F_SPRINTING)) { + if (isplayer(user)) { + msg("You are already sprinting!"); + } + return B_TRUE; } // TODO: calculate time based on: // constitution (or max hp?) // running speed - howlong = 3; + howlong = 5; addtempflag(user->flags, F_SPRINTING, B_TRUE, NA, NA, NULL, howlong); } else if (abilid == OT_A_DEBUG) { cell_t *where; @@ -191,7 +246,60 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid) { } else { msg("There is nobody there!"); } + } else if (abilid == OT_A_HEAVYBLOW) { + object_t *wep; + char dirch; + char targetname[BUFLEN]; + flag_t *f; + + wep = getweapon(user); + if (!wep) { + if (isplayer(user)) msg("You need a bashing weapon to perform a heavy blow!"); + return B_TRUE; + } else if (getdamtype(wep) != DT_BASH) { + if (isplayer(user)) msg("You need a bashing weapon to perform a heavy blow!"); + return B_TRUE; + } + + // ask for direction + if (!targcell) { + dirch = askchar("Attack in which direction (- to cancel)", "yuhjklbn.-","-", B_FALSE); + if (dirch == '.') { + // yourself! + targcell = user->cell; + } else { + int dir; + dir = chartodir(dirch); + if (dir == D_NONE) { + if (isplayer(user)) msg("Cancelled."); + return B_TRUE ; + } else { + targcell = getcellindir(user->cell, dir); + } + } + } + + target = targcell->lf; + if (!target) { + if (isplayer(user)) msg("There is nobody there to attack!"); + return B_TRUE; + } + getlfname(target, targetname); + + f = addflag(wep->flags, F_HEAVYBLOW, B_TRUE, NA, NA, NULL); + attackcell(user, targcell); + killflag(f); } + + // expire ability + f = lfhasflagval(user, F_CANWILL, abilid, NA, NA, NULL); + if (f) { + if (f->val[2] != NA) { + // ie. it will go to 0 next turn. + f->val[1] = -1; + } + } + return B_FALSE; } @@ -207,6 +315,19 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target, // default to unseen if (seenbyplayer) *seenbyplayer = B_FALSE; + + // reverse some spells if cursed + + if (blessed == B_CURSED) { + switch (spellid) { + case OT_S_LIGHT: + spellid = OT_S_DARKNESS; + break; + default: + break; + } + } + if (spellid == OT_S_ABSORBMETAL) { int i; float totalmass = 0; @@ -290,6 +411,33 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target, } else { fizzle(caster); } + } else if (spellid == OT_S_ANIMATEDEAD) { + int i; + object_t *o,*nexto; + int donesomething = B_FALSE; + // animate corpses within los of caster + for (i = 0; i < caster->nlos; i++) { + targcell = caster->los[i]; + for (o = targcell->obpile->first ; o ; o = nexto) { + nexto = o->next; + if (o->type->id == OT_CORPSE) { + lifeform_t *newlf; + newlf = makezombie(o); + if (newlf) { + if (isplayer(caster) && skillcheck(caster, A_IQ, 20, 0)) { + makefriendly(newlf); + } + donesomething = B_TRUE; + } + } + } + } + + if (donesomething) { + if (seenbyplayer) *seenbyplayer = B_TRUE; + } else { + fizzle(caster); + } } else if (spellid == OT_S_ANIMATEMETAL) { object_t *o; o = getweapon(caster); @@ -331,6 +479,40 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target, } else { fizzle(caster); } + } else if (spellid == OT_S_BLINDNESS) { + int failed = B_FALSE; + // ask for target + if (!validatespelllf(caster, &target)) return B_TRUE; + + if (isblind(target)) { + fizzle(caster); + return B_FALSE; + } + + if (hasmr(target) || skillcheck(caster, A_IQ, 24, 0)) { + failed = B_TRUE; + } + + if (target) { + if (failed) { + if (isplayer(target)) { + msg("Your vision darkens for a moment."); + if (seenbyplayer) *seenbyplayer = B_TRUE; + } else if (haslos(player, target->cell)) { + char targetname[BUFLEN]; + getlfname(target, targetname); + msg("%s seems to lose its vision for a moment.", targetname); + if (seenbyplayer) *seenbyplayer = B_TRUE; + } + return B_FALSE; + } else { + int howlong = 7; + howlong = getspellduration(5,10,blessed); + addtempflag(target->flags, F_BLIND, B_TRUE, NA, NA, NULL, howlong); + } + } else { + fizzle(caster); + } } else if (spellid == OT_S_BLINK) { if (hasmr(caster)) { if (isplayer(caster)) { @@ -356,10 +538,50 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target, } teleportto(caster, targcell); } + } else if (spellid == OT_S_BURNINGWAVE) { + cell_t *c; + if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE, spellid)) return B_TRUE; + + if (haslos(player, caster->cell)) { + msg("%s shoots a wave of fire!",castername); + } + + // create a line of fire towards the target cell + c = caster->cell; + while (c != targcell) { + int dir; + dir = getdirtowards(c, targcell, NULL, B_FALSE); + c = getcellindir(c, dir); + if (!c) break; + if (c->type->solid) break; + // set on fire + addob(c->obpile, "medium fire"); + if (c->lf) { + char buf[BUFLEN]; + getlfname(c->lf,buf); + msg("%s burn%s!",buf,isplayer(c->lf) ? "" : "s"); + losehp(c->lf, rolldie(2,10), DT_FIRE, caster, "a wave of fire"); + } + } + + } else if (spellid == OT_S_CLOUDKILL) { + if (!validatespellcell(caster, &targcell, TT_MONSTER, B_FALSE, spellid)) return B_TRUE; + + if (targcell->type->solid) { + fizzle(caster); + return B_FALSE; + } + + addobburst(targcell, 1, DT_COMPASS, "cloud of gas"); + + if (haslos(player, targcell)) { + msg("A cloud of poison gas appears!"); + if (seenbyplayer) *seenbyplayer = B_TRUE; + } } else if (spellid == OT_S_CONECOLD) { char lfname[BUFLEN]; int acc; - if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE, spellid)) return B_TRUE; // animation anim(caster->cell, targcell, '}'); if (isplayer(caster) || haslos(player, caster->cell)) { @@ -385,6 +607,12 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target, msg("A blast of coldness misses %s.",lfname); } } + } else { + object_t *o, *nexto; + for (o = targcell->obpile->first; o ; o = nexto) { + nexto = o->next; + takedamage(o, 0, DT_COLD); + } } } else if (spellid == OT_S_CREATEMONSTER) { cell_t *where; @@ -445,9 +673,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target, if (blessed) { //newlf = addlf(where, r->id, getrandommonlevel(where->map->depth)); - newlf = addmonster(where, r->id, randomjobsok); + newlf = addmonster(where, r->id, randomjobsok, 1); } else { - newlf = addmonster(where, R_RANDOM, randomjobsok); + newlf = addmonster(where, R_RANDOM, randomjobsok, 1); } if (newlf) { // assign job if required @@ -477,6 +705,13 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target, } return B_TRUE; } + } else if (spellid == OT_S_DARKNESS) { + // centre on the caster + if (isplayer(caster) || haslos(player, caster->cell)) { + msg("A cloud of darkness descends!"); + if (seenbyplayer) *seenbyplayer = B_TRUE; + } + makelitradius(caster->cell, 10, L_DARK); } else if (spellid == OT_S_DETECTAURA) { if (isplayer(caster)) { object_t *o; @@ -552,7 +787,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target, */ } else if (spellid == OT_S_DETONATE) { // don't need line of fire! - if (!validatespellcell(caster, &targcell, TT_MONSTER|TT_DOOR, B_FALSE)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_MONSTER|TT_DOOR, B_FALSE, spellid)) return B_TRUE; explodecells(targcell, 20, B_TRUE, NULL, 0, B_TRUE); @@ -563,7 +798,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target, float totalmass = 0; object_t *o, *nexto; - if (!validatespellcell(caster, &targcell, TT_OBJECT, B_FALSE)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_OBJECT, B_FALSE, spellid)) return B_TRUE; // how much metal is there? for (o = targcell->obpile->first ; o ; o = nexto) { @@ -686,7 +921,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target, } else if (spellid == OT_S_ENERGYBOLT) { char lfname[BUFLEN]; int acc; - if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE, spellid)) return B_TRUE; // animation anim(caster->cell, targcell, '}'); if (isplayer(caster) || haslos(player, caster->cell)) { @@ -716,7 +951,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target, } else if (spellid == OT_S_FIREBALL) { int failed = B_FALSE; // ask for a target cell - if (!validatespellcell(caster, &targcell,TT_MONSTER, B_TRUE)) return B_TRUE; + if (!validatespellcell(caster, &targcell,TT_MONSTER, B_TRUE, spellid)) return B_TRUE; if (targcell && haslof(caster, targcell)) { // need line of FIRE for this, not just sight if (!targcell->type->solid || hasflag(targcell->type->material->flags, F_FLAMMABLE)) { int dir; @@ -783,7 +1018,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target, } else if (spellid == OT_S_FIREDART) { char lfname[BUFLEN]; int acc; - if (!validatespellcell(caster, &targcell,TT_MONSTER, B_TRUE)) return B_TRUE; + if (!validatespellcell(caster, &targcell,TT_MONSTER, B_TRUE, spellid)) return B_TRUE; // animation anim(caster->cell, targcell, '}'); if (isplayer(caster) || haslos(player, caster->cell)) { @@ -809,11 +1044,44 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target, msg("A dart of flame misses %s.",lfname); } } + } else { + object_t *o, *nexto; + for (o = targcell->obpile->first; o ; o = nexto) { + nexto = o->next; + takedamage(o, 0, DT_FIRE); + } + } + } else if (spellid == OT_S_FLAMEBURST) { + int range = 1; + int x,y; + // announce + if (isplayer(caster) || haslos(player, caster->cell)) { + msg("%s emit%s a blast of fire!",castername,isplayer(caster) ? "" : "s"); + if (seenbyplayer) *seenbyplayer = B_TRUE; + } + + animradialorth(caster->cell, range, '}'); + + for (y = caster->cell->y - range ; y <= caster->cell->y + range; y++) { + for (x = caster->cell->x - range ; x <= caster->cell->x + range; x++) { + targcell = getcellat(caster->cell->map, x,y); + if (targcell && (getcelldistorth(caster->cell, targcell) <= range)) { + if (targcell->lf && (targcell->lf != caster) && haslof(caster, targcell)) { + char lfname[BUFLEN]; + // automatic hit + getlfname(targcell->lf, lfname); + if (haslos(caster, targcell)) { + msg("%s burn%s!",lfname,isplayer(targcell->lf) ? "" : "s"); + } + losehp(targcell->lf, rolldie(2,8)+3, DT_MAGIC, caster, "a burst of fire"); + } + } + } } } else if (spellid == OT_S_FLAMEPILLAR) { int failed = B_FALSE; // ask for a target cell - if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE, spellid)) return B_TRUE; if (targcell && haslos(caster, targcell)) { if (!targcell->type->solid || hasflag(targcell->type->material->flags, F_FLAMMABLE)) { // create flame there @@ -853,14 +1121,15 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target, } else { int amt; char obname[BUFLEN]; + getobname(o, obname, o->amt); + msg("Your %s glows %s for a moment.", noprefix(obname), (blessed == B_CURSED) ? "black" : "green"); + if (seenbyplayer) *seenbyplayer = B_TRUE; if (blessed == B_CURSED) { amt = -1; } else { amt = 1; } modbonus(o, amt); - getobname(o, obname, o->amt); - msg("Your %s glows %s for a moment.", noprefix(obname), (blessed == B_CURSED) ? "black" : "green"); } } else { // monsters can't id things! @@ -976,7 +1245,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target, } } else if (spellid == OT_S_HASTE) { int howlong = 15; - if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE, spellid)) return B_TRUE; target = targcell->lf; @@ -1001,6 +1270,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target, addtempflag(target->flags, F_FASTMOVE, 5, NA, NA, NULL, howlong); } } else if (spellid == OT_S_HEALING) { + int donesomething = B_FALSE; + flag_t *f; target = caster; if (hasmr(target)) { @@ -1011,6 +1282,12 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target, } return B_FALSE; } + + // cure certain bad effects + if (killflagsofid(target->flags, F_PAIN)) { + donesomething = B_TRUE; + } + if (target->hp < target->maxhp) { switch (blessed) { case B_BLESSED: @@ -1035,12 +1312,23 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target, msg("%s looks healthier!", buf); if (seenbyplayer) *seenbyplayer = B_TRUE; } - } else { + donesomething = B_TRUE; + } + f = lfhasflag(target, F_FOODPOISONED); + if (f) { + killflag(f); + donesomething = B_TRUE; + if (seenbyplayer) *seenbyplayer = B_TRUE; + } + + if (!donesomething) { if (isplayer(target)) { nothinghappens(); } } } else if (spellid == OT_S_HEALINGMIN) { + int donesomething = B_FALSE; + flag_t *f; target = caster; if (hasmr(target)) { if (isplayer(target) || haslos(player, target->cell)) { @@ -1050,6 +1338,12 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target, } return B_FALSE; } + + // cure bad effects instead of healing + if (killflagsofid(target->flags, F_PAIN)) { + return B_FALSE; + } + if (target->hp < target->maxhp) { switch (blessed) { case B_BLESSED: @@ -1071,7 +1365,16 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target, msg("%s looks a little healthier!", buf); if (seenbyplayer) *seenbyplayer = B_TRUE; } - } else { + donesomething = B_TRUE; + } + f = lfhasflag(target, F_FOODPOISONED); + if (f) { + killflag(f); + donesomething = B_TRUE; + if (seenbyplayer) *seenbyplayer = B_TRUE; + } + + if (!donesomething) { if (isplayer(target)) { nothinghappens(); } @@ -1102,9 +1405,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target, // charges charges = getcharges(o); if (charges == -1) { - msglower("%c - %s.",o->letter, buf); + msgnocap("%c - %s.",o->letter, buf); } else { - msglower("%c - %s (%d charges left).",o->letter, buf, charges); + msgnocap("%c - %s (%d charges left).",o->letter, buf, charges); } if (seenbyplayer) *seenbyplayer = B_TRUE; } @@ -1140,7 +1443,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target, char lfname[BUFLEN]; int acc; - if (!validatespellcell(caster, &targcell,TT_MONSTER, B_TRUE)) return B_TRUE; + if (!validatespellcell(caster, &targcell,TT_MONSTER, B_TRUE, spellid)) return B_TRUE; // animation anim(caster->cell, targcell, '}'); if (isplayer(caster) || haslos(player, caster->cell)) { @@ -1339,12 +1642,71 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target, return B_TRUE; } - if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE, spellid)) return B_TRUE; // 4 is the same as ST_TITANIC strength fireat(caster, targob, targcell, 4 , NULL); + } else if (spellid == OT_S_PAIN) { + int failed = B_FALSE; + // ask for target + if (!validatespelllf(caster, &target)) return B_TRUE; + + if (lfhasflag(target, F_PAIN)) { + fizzle(caster); + return B_FALSE; + } + + // make this a constitution skill check ? + //if (hasmr(target) || skillcheck(caster, A_IQ, -5)) { + if (hasmr(target)) { + failed = B_TRUE; + } + + if (target) { + if (failed) { + if (isplayer(target)) { + msg("Your skin hurts for a moment."); + if (seenbyplayer) *seenbyplayer = B_TRUE; + } else if (haslos(player, target->cell)) { + char targetname[BUFLEN]; + getlfname(target, targetname); + msg("%s winces in pain, then recovers.", targetname); + if (seenbyplayer) *seenbyplayer = B_TRUE; + } + return B_FALSE; + } else { + int howlong = 7; + howlong = getspellduration(3,5,blessed); + addtempflag(target->flags, F_PAIN, B_TRUE, NA, NA, NULL, howlong); + } + } else { + fizzle(caster); + } + } else if (spellid == OT_S_PETRIFY) { + if (!validatespelllf(caster, &target)) return B_TRUE; + + // savingthrow + if (skillcheck(target, SC_IQ, 30, 0)) { + if (haslos(player, target->cell)) { + char lfname[BUFLEN]; + getlfname(target, lfname); + msg("%s glows grey momentarily.", lfname); + if (seenbyplayer) *seenbyplayer = B_TRUE; + } + return B_TRUE; + } + + if (!stone(target)) { + // successful + if (haslos(player, target->cell)) { + if (seenbyplayer) *seenbyplayer = B_TRUE; + } + } else { + // failed! + fizzle(caster); + } } else if (spellid == OT_S_PULLMETAL) { - if (!validatespellcell(caster, &targcell,TT_OBJECT, B_TRUE)) return B_TRUE; + if (!validatespellcell(caster, &targcell,TT_OBJECT, B_TRUE, spellid)) return B_TRUE; if (targcell->lf) { object_t *o; @@ -1378,7 +1740,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target, if (hasmr(target)) { failed = B_TRUE; - } else if (metalweight <= getmaxliftweight(caster)) { + } else if (getobpileweight(caster->pack) + metalweight <= getmaxcarryweight(caster)) { // they get pulled towards caster failed = pullnextto(target, caster->cell); } else { @@ -1419,7 +1781,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target, } else if (haslos(player, caster->cell)) { if (seenbyplayer) *seenbyplayer = B_TRUE; } - if (getobweight(targob) < getmaxliftweight(caster) ) { + if (getobpileweight(caster->pack) + getobweight(targob) <= getmaxcarryweight(caster)) { // move it to the player pullobto(targob, caster); } else { @@ -1551,7 +1913,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target, } } else if (spellid == OT_S_KNOCK) { object_t *o; - if (!validatespellcell(caster, &targcell,TT_DOOR, B_FALSE)) return B_TRUE; + if (!validatespellcell(caster, &targcell,TT_DOOR, B_FALSE, spellid)) return B_TRUE; o = hasobwithflag(targcell->obpile, F_DOOR); if (o) { int dooropen; @@ -1566,6 +1928,14 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target, takedamage(o, 999, DT_DIRECT); if (seenbyplayer) *seenbyplayer = B_TRUE; } + } else if (targcell->lf && (targcell->lf != caster)) { + int dir; + target = targcell->lf; + dir = getdirtowards(caster->cell, targcell, target, B_FALSE); + knockback(target, dir, 2, caster); + if (haslos(caster, target->cell)) { + if (seenbyplayer) *seenbyplayer = B_TRUE; + } } else { fizzle(caster); } @@ -1576,7 +1946,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target, msg("The area is lit by a magical light!"); if (seenbyplayer) *seenbyplayer = B_TRUE; } - makelitradius(caster->cell, 10, B_PERM); + makelitradius(caster->cell, 10, L_PERM); // blind anyone with nightvis who sees it // (player last) @@ -1585,8 +1955,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target, if (lfhasflag(l, F_SEEINDARK)) { // if you don't have eyes, your'e safe! if (!lfhasflagval(l, F_NOBODYPART, BP_EYES, NA, NA, NULL)) { - // blind for 5-10 turns - addtempflag(l->flags, F_BLIND, B_TRUE, NA, NA, NULL, rnd(5,10)); + // blind for 1-3 turns + addtempflag(l->flags, F_BLIND, B_TRUE, NA, NA, NULL, rnd(1,3)); } } // undead will flee from light @@ -1724,10 +2094,34 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target, // become the new race! setrace(target, r->id); + + if (haslos(player, target->cell)) { + if (seenbyplayer) *seenbyplayer = B_TRUE; + } } else { fizzle(caster); return B_TRUE; } + } else if (spellid == OT_S_SLEEP) { + int howlong; + if (!validatespelllf(caster, &target)) return B_TRUE; + + if (hasmr(target)) { + if (isplayer(target)) { + msg("You yawn."); + if (seenbyplayer) *seenbyplayer = B_TRUE; + } else if (haslos(player, target->cell)) { + getlfname(target, buf); + msg("%s yawns.", buf); + if (seenbyplayer) *seenbyplayer = B_TRUE; + } + return B_FALSE; + } + howlong = getspellduration(5,15,blessed); + addtempflag(target->flags, F_ASLEEP, B_TRUE, NA, NA, NULL, howlong); + if (isplayer(target) || haslos(player, target->cell)) { + if (seenbyplayer) *seenbyplayer = B_TRUE; + } } else if (spellid == OT_S_SLOW) { int howlong = 15; if (!validatespelllf(caster, &target)) return B_TRUE; @@ -1747,12 +2141,29 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target, howlong = rnd(5,25); addtempflag(target->flags, F_SLOWACT, 5, NA, NA, NULL, howlong); addtempflag(target->flags, F_SLOWMOVE, 5, NA, NA, NULL, howlong); - /* - if (!isplayer(target) && haslos(player, target->cell)) { - getlfname(target, buf); - msg("%s seems to slow down.",buf); + if (isplayer(target) || haslos(player, target->cell)) { + if (seenbyplayer) *seenbyplayer = B_TRUE; + } + } else if (spellid == OT_S_SPARK) { + object_t *o,*nexto; + int donesomething = B_FALSE; + if (!validatespellcell(caster, &targcell,TT_OBJECT | TT_MONSTER, B_FALSE, spellid)) return B_TRUE; + + if (haslos(player, targcell)) { + msg("A small spark appears."); + if (seenbyplayer) *seenbyplayer = B_TRUE; + } + + for (o = targcell->obpile->first ; o ; o = nexto) { + nexto = o->next; + if (isflammable(o)) { + takedamage(o, 0, DT_FIRE); + donesomething = B_TRUE; + } + } + if (targcell->lf) { + losehp(targcell->lf, 0, DT_FIRE, caster, "a spark"); } - */ } else if (spellid == OT_S_TELEPORT) { cell_t *c = NULL; @@ -1981,7 +2392,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target, if (!hasflag(o->flags, F_IMPASSABLE) && canpickup(target, o, ALL)) { relinkob(o, target->pack); // move to pack if (isplayer(target)) { - msglower("%c - %s.", o->letter, obname); + msgnocap("%c - %s.", o->letter, obname); } else { msg("%s is gifted with %s.", lfname, obname); } @@ -2051,6 +2462,49 @@ int getspellduration(int min,int max,int blessed) { return howlong; } +int getspelllevel(enum OBTYPE spellid) { + flag_t *f; + objecttype_t *ot; + int level = 0; + ot = findot(spellid); + if (!ot) { + return 0; + } + f = hasflag(ot->flags, F_SPELLLEVEL); + if (f) { + level = f->val[0]; + } + return level; +} + +enum SPELLSCHOOL getspellschool(enum OBTYPE spellid) { + flag_t *f; + objecttype_t *ot; + ot = findot(spellid); + if (!ot) { + return SS_NONE; + } + f = hasflag(ot->flags, F_SPELLSCHOOL); + if (f) { + return f->val[0]; + } + return SS_NONE; +} + +int getspellrange(enum OBTYPE spellid) { + objecttype_t *st; + int range = UNLIMITED; + st = findot(spellid); + if (st) { + flag_t *f; + f = hasflag(st->flags, F_RANGE); + if (f) { + range = f->val[0]; + } + } + return range; +} + // magically propel an object into lf's hands. // if it's too big it'll hit them! void pullobto(object_t *o, lifeform_t *lf) { @@ -2079,7 +2533,7 @@ void pullobto(object_t *o, lifeform_t *lf) { } // where does it end up? obloc = getoblocation(o); - dir = getdirtowards(lf->cell, obloc, B_FALSE); + dir = getdirtowards(lf->cell, obloc, NULL, B_FALSE); newcell = getcellindir(lf->cell, dir); if (newcell) { // move next to player @@ -2101,26 +2555,37 @@ void pullobto(object_t *o, lifeform_t *lf) { } } -cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, int needlof) { +cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, int needlof, enum OBTYPE spellid) { + int maxrange = UNLIMITED; + + maxrange = getspellrange(spellid); + if (*targcell == NULL) { // ask for a target cell if (isplayer(caster)) { cell_t *where; char buf[BUFLEN]; - sprintf(buf, "Where will you target your spell?"); + if (maxrange == UNLIMITED) { + sprintf(buf, "Where will you target your spell?"); + } else { + sprintf(buf, "Where will you target your spell [max range %d]?",maxrange); + } where = askcoords(buf, targtype); + if (where && haslos(caster, where)) { - if (needlof) { - if (haslof(caster, where)) { - *targcell = where; - } else { - fizzle(caster); - return NULL; - } + if (needlof && !haslof(caster, where)) { + // no line of sight + fizzle(caster); + return NULL; + } else if ((maxrange != UNLIMITED) && (getcelldist(caster->cell, where) > maxrange)) { + // out of range + fizzle(caster); + return NULL; } else { *targcell = where; } } else { + // no line of sight or invalid cell fizzle(caster); return NULL; } @@ -2183,6 +2648,7 @@ int getmpcost(enum OBTYPE oid) { return cost; } + lifeform_t *validatespelllf(lifeform_t *caster, lifeform_t **target) { if (*target) { return *target; diff --git a/spell.h b/spell.h index b91854a..90f9e0c 100644 --- a/spell.h +++ b/spell.h @@ -2,14 +2,17 @@ #define __SPELLS_H #include "defs.h" -int abilityeffects(lifeform_t *user, enum OBTYPE abilid); +int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifeform_t *target); int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target, object_t *targob, cell_t *targcell, int blessed, int *seenbyplayer); void fizzle(lifeform_t *caster); int getiqreq(enum OBTYPE oid); int getmpcost(enum OBTYPE oid); int getspellduration(int min,int max,int blessed); +int getspelllevel(enum OBTYPE spellid); +enum SPELLSCHOOL getspellschool(enum OBTYPE spellid); +int getspellrange(enum OBTYPE spellid); void pullobto(object_t *o, lifeform_t *lf); -cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, int needlof); +cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, int needlof, enum OBTYPE spellid); lifeform_t *validatespelllf(lifeform_t *caster, lifeform_t **lf); #endif diff --git a/text.c b/text.c index 23a3494..e00609f 100644 --- a/text.c +++ b/text.c @@ -110,7 +110,7 @@ char *gettimetextfuzzy(char *retbuf, int wantpm) { } else if (mins <= 35) { sprintf(retbuf, "around half past %d", hours); } else if (mins <= 45) { - sprintf(retbuf, "comung up to %d o'clock", (hours == 12) ? 1 : (hours+1)); + sprintf(retbuf, "coming up to %d o'clock", (hours == 12) ? 1 : (hours+1)); } else { sprintf(retbuf, "nearly %d o'clock", (hours == 12) ? 1 : (hours+1)); } @@ -189,6 +189,10 @@ char *makeplural(char *text) { if (rv) return newtext; newtext = strrep(newtext, "scroll ", "scrolls ", &rv); if (rv) return newtext; + newtext = strrep(newtext, "splash ", "splashes ", &rv); + if (rv) return newtext; + newtext = strrep(newtext, "suit ", "suits ", &rv); + if (rv) return newtext; newtext = strrep(newtext, "vial ", "vials ", &rv); if (rv) return newtext; @@ -200,6 +204,10 @@ char *makeplural(char *text) { // default lastlet = text[strlen(text)-1]; switch (lastlet) { + case 'y': // change to 'ies' + text[strlen(text)-1] = '\0'; + asprintf(&newtext, "%sies",text); + break; case 's': case 'o': // append "es" asprintf(&newtext, "%ses",text);