From 69d14c05fea1cc774506c103938610b4886ab526 Mon Sep 17 00:00:00 2001 From: Rob Pearce Date: Thu, 31 Mar 2011 23:54:44 +0000 Subject: [PATCH] * [+] goblins aren't opening doors... - [+] xat shouldn't be able to open doors! - [+] semicontrolled createmonster * [+] implement semicontrolled teleport (can pick the general direction) * [+] change how semicontrolled teleport works - [+] make identify/remove curse more common - [+] make minorheal/heal more common * [+] NOTDONE. maybe reduce the amount of damage which AR blocks a bit? i got to 30ar very fast! (ie -45% dam) * [+] make a special case for F_FLAKJACKET - [+] BUG: glowbug is causing PERMENANT light, not temp! - [+] diety ability - levelup - [+] new damtype: necrotic - [+] drain life spell - [+] make water evaporate - [+] BUG in validating target cell. was asking a monster for input * [+] boots get wet if you walk in water - [+] why does oil lamp and pil lantern make the same range of light? - [+] fixed another vending maching crash - [+] crash due to sprinting? - [+] 2 blessed flask of battery acids - [+] "This is a wand!" - don't use code for hiding names in the dark! * [+] animals shouldn't eat their own race! - [+] gem of seeing costs nothing! - [+] frozen weapons do +1d4 cold damage - [+] allomancy/psionics don't need spellcasting - [+] poison isn't being announced on mosnters? - [+] "you are full" only interrupt if we went < normal (ie peckish starving etc) - [+] only F_HUMANOID creatures can wear armour / use weapons * [+] what does a masterwork bow do? - [+] implement strength requirements on weapons - [+] UNDEAD cannot be poisoned by eating corpses! - [+] ai lfs shoudlnt' eat tainted food - [+] change how gravboost works wrt movement - [+] smart ai lfs shouldnt move when in pain - [+] don't stop walking if the only things there are non-pickupable - [+] make mosnters swap places with each other if they are the same baseid * [+] scroll of permenance - [+] make more monsters have gold * [+] can learn novice level weapon skills by using one a lot * [+] finish hawks * [+] add colour * [+] job attribs aren't working - [+] pile of ash has weird glyph! * [+] when you learn the first rank of some magic skills, you get a spell with it - [+] add colours to statbar - [+] can only "stop on xxx" if you have feet - [+] monsters shouldn't attack other to get to wanted objects. * [+] "xat throws a knife" - [+] manaspike doing no damage to giant newt - [+] assign colours to rings --- ai.c | 186 ++++++++------ attack.c | 179 +++++++++++-- attack.h | 3 +- defs.h | 126 ++++++++-- flag.c | 95 +++++-- flag.h | 1 + io.c | 414 +++++++++++++++++++++++++----- io.h | 10 +- lf.c | 693 ++++++++++++++++++++++++++++++++++++++------------- lf.h | 7 +- log.txt | 589 +++++++++++++++++++++++++++++++++---------- map.c | 34 ++- map.h | 2 +- move.c | 214 ++++++++++------ move.h | 6 +- nexus.c | 24 +- nexus.h | 2 +- objects.c | 733 ++++++++++++++++++++++++++++++++++++++++-------------- objects.h | 9 +- spell.c | 655 ++++++++++++++++++++++++++++++++++++++++-------- text.c | 69 ++++- text.h | 1 + 22 files changed, 3153 insertions(+), 899 deletions(-) diff --git a/ai.c b/ai.c index 078500e..3248a7e 100644 --- a/ai.c +++ b/ai.c @@ -21,11 +21,21 @@ int wantdb = B_TRUE; void aiattack(lifeform_t *lf, lifeform_t *victim, int timelimit) { int db = B_FALSE; + flag_t *f; if (lfhasflag(lf, F_DEBUG)) { db = B_TRUE; } + // already targetting this lf? + f = lfhasflagval(lf, F_TARGET, victim->id, NA, NA, NULL); + if (f) { + if ((f->lifetime > 0) && (f->lifetime < timelimit)) { + f->lifetime = timelimit; + } + return; + } + if (db) { char lfname[BUFLEN],vicname[BUFLEN]; getlfname(lf, lfname); @@ -47,7 +57,6 @@ void aiattack(lifeform_t *lf, lifeform_t *victim, int timelimit) { makenoise(lf, N_GETANGRY); } - // change allegience ? if (!areenemies(lf, victim)) { if (getallegiance(victim) == AL_FRIENDLY) { @@ -347,7 +356,7 @@ void aimove(lifeform_t *lf) { curarm = getarmour(lf, bp); // do we have a better one? for (o = lf->pack->first ; o ; o = o->next) { - if (isbetterarmourthan(o, curarm)) { + if (canwear(lf, o, BP_NONE) && isbetterarmourthan(o, curarm)) { // wear this armour instead if (!wear(lf, o)) return; } @@ -480,7 +489,7 @@ void aimove(lifeform_t *lf) { // if not adjacent, check for guns, wands, throwing if (goingtomove && (getcelldist(lf->cell, target->cell) > 1) && haslof(lf, target->cell, B_FALSE, NULL)) { - // can we attack by firing something? + // can we attack by firing a weapon? gun = getfirearm(lf); if (goingtomove && gun && getammo(lf)) { if (db) { @@ -500,8 +509,7 @@ void aimove(lifeform_t *lf) { } // can we attack by throwing something? - if (goingtomove) { - // + if (goingtomove && hasbp(lf, BP_HANDS)) { o = getbestthrowmissile(lf); if (o) { if (db) dblog(".oO { will throw %s at my target instead of moving }", o->type->name); @@ -516,37 +524,39 @@ void aimove(lifeform_t *lf) { } // do we have a wand we can zap? - if (lfhasflag(lf, F_FLEEFROM)) { - o = aigetwand(lf, F_AICASTTOFLEE); - } else { - o = aigetwand(lf, F_AICASTTOATTACK); - } - if (o) { - objecttype_t *st; - cell_t *zapcell = NULL; - - st = getlinkspell(o); - if (st) { - enum FLAG purpose; - if (lfhasflag(lf, F_FLEEFROM)) { - purpose = F_AICASTTOFLEE; - } else { - purpose = F_AICASTTOATTACK; - } - aigetspelltarget(lf, st, target, NULL, &zapcell, NULL, purpose); + if (lfhasflag(lf, F_HUMANOID) || hasbp(lf, BP_HANDS)) { + if (lfhasflag(lf, F_FLEEFROM)) { + o = aigetwand(lf, F_AICASTTOFLEE); } else { - // no linkspell - just zap it. - zapcell = NULL; + o = aigetwand(lf, F_AICASTTOATTACK); } + if (o) { + objecttype_t *st; + cell_t *zapcell = NULL; - // zap it - if (db) dblog(".oO { will zap %s instead of moving }", o->type->name); + st = getlinkspell(o); + if (st) { + enum FLAG purpose; + if (lfhasflag(lf, F_FLEEFROM)) { + purpose = F_AICASTTOFLEE; + } else { + purpose = F_AICASTTOATTACK; + } + aigetspelltarget(lf, st, target, NULL, &zapcell, NULL, purpose); + } else { + // no linkspell - just zap it. + zapcell = NULL; + } - if (!operate(lf, o, zapcell)) { - // succesful - goingtomove = B_FALSE; - } else { - if (db) dblog(".oO { zap failed! }"); + // zap it + if (db) dblog(".oO { will zap %s instead of moving }", o->type->name); + + if (!operate(lf, o, zapcell)) { + // succesful + goingtomove = B_FALSE; + } else { + if (db) dblog(".oO { zap failed! }"); + } } } } @@ -558,7 +568,7 @@ void aimove(lifeform_t *lf) { } if (goingtomove) { - if (!movetowards(lf, target->cell)) { + if (!movetowards(lf, target->cell, DT_ORTH)) { // success return; } else { @@ -599,7 +609,7 @@ void aimove(lifeform_t *lf) { if (db) dblog(".oO { walking from %d,%d towards f_targetcell (%d,%d) ... }", lf->cell->x, lf->cell->y, x, y); c = getcellat(lf->cell->map, x, y); if (c) { - if (movetowards(lf, c)) { + if (movetowards(lf, c, DT_ORTH)) { // couldn't move towards it for some reason. // so stop trying. if (db) dblog(".oO { couldn't walk towards f_targetcell. abandoning it. }"); @@ -659,7 +669,7 @@ void aimove(lifeform_t *lf) { if (db) dblog(".oO { moving towards my new target }"); if (curwep) { - if (!movetowards(lf, c)) return; + if (!movetowards(lf, c, DT_ORTH)) return; } else { if (db) dblog(".oO { won't move towards target - i have no weapon. }"); } @@ -684,7 +694,7 @@ void aimove(lifeform_t *lf) { addtempflag(lf->flags, F_TARGET, c->lf->id, c->x, c->y, NULL, AI_FOLLOWTIME); // then move towards them... if (db) dblog(".oO { moving towards my new target }"); - if (!movetowards(lf, c)) return; + if (!movetowards(lf, c, DT_ORTH)) return; } } } @@ -908,6 +918,25 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG if ((ot->id == OT_S_BLINDNESS) && isblind(victim)) { specificcheckok = B_FALSE; } + if ((ot->id == OT_S_DRAINLIFE) && isimmuneto(victim->flags, DT_NECROTIC)) { + specificcheckok = B_FALSE; + } + if (ot->id == OT_A_SWOOP) { + flag_t *srflag; + int srange = 5; + srflag = lfhasflag(lf, F_SWOOPRANGE); + if (srflag) { + srange = srflag->val[0]; + } + + if (!haslof(lf, victim->cell, LOF_NEED,NULL)) { + specificcheckok = B_FALSE; + } else if (isimmobile(lf) || !lfhasflag(lf, F_FLYING)) { + specificcheckok = B_FALSE; + } else if (getcelldist(lf->cell, victim->cell) > srange) { + specificcheckok = B_FALSE; + } + } if ((ot->id == OT_S_HASTE) && lfhasflag(lf, F_FASTACT)) { specificcheckok = B_FALSE; } @@ -1046,28 +1075,33 @@ int lookforobs(lifeform_t *lf, int covetsonly) { } } // current cell has better weapon? - f = hasflag(lf->flags, F_WANTSBETTERWEP); - if (f ) { - if (!covetsonly || (f->val[1] == B_COVETS)) { - o = hasbetterweapon(lf, lf->cell->obpile); - if (o && !isdangerousob(o, lf, B_TRUE) && canpickup(lf, o, 1)) { - if (db) dblog(".oO { current cell has better weapon (%s) }",o->type->name); - // try to pick it up - if (!aipickup(lf, o)) return B_TRUE; - if (db) dblog(".oO { pickup of better wep %s failed! }",o->type->name); + if (lfhasflag(lf, F_HUMANOID) && hasbp(lf, BP_WEAPON)) { + f = hasflag(lf->flags, F_WANTSBETTERWEP); + if (f) { + if (!covetsonly || (f->val[1] == B_COVETS)) { + o = hasbetterweapon(lf, lf->cell->obpile); + if (o && !isdangerousob(o, lf, B_TRUE) && canpickup(lf, o, 1)) { + if (db) dblog(".oO { current cell has better weapon (%s) }",o->type->name); + // try to pick it up + if (!aipickup(lf, o)) return B_TRUE; + if (db) dblog(".oO { pickup of better wep %s failed! }",o->type->name); + } } } } - // current cell has better armour? - f = hasflag(lf->flags, F_WANTSBETTERARM); - if (f ) { - if (!covetsonly || (f->val[1] == B_COVETS)) { - o = hasbetterarmour(lf, lf->cell->obpile); - if (o && !isdangerousob(o, lf, B_TRUE) && canpickup(lf, o, 1)) { - if (db) dblog(".oO { current cell has better armour (%s) }",o->type->name); - // try to pick it up - if (!aipickup(lf, o)) return B_TRUE; - if (db) dblog(".oO { pickup of better armour %s failed! }",o->type->name); + + if (lfhasflag(lf, F_HUMANOID)) { + // current cell has better armour? + f = hasflag(lf->flags, F_WANTSBETTERARM); + if (f ) { + if (!covetsonly || (f->val[1] == B_COVETS)) { + o = hasbetterarmour(lf, lf->cell->obpile); + if (o && !isdangerousob(o, lf, B_TRUE) && canpickup(lf, o, 1)) { + if (db) dblog(".oO { current cell has better armour (%s) }",o->type->name); + // try to pick it up + if (!aipickup(lf, o)) return B_TRUE; + if (db) dblog(".oO { pickup of better armour %s failed! }",o->type->name); + } } } } @@ -1079,7 +1113,7 @@ int lookforobs(lifeform_t *lf, int covetsonly) { int gothere = B_FALSE; c = lf->los[i]; - if (c != lf->ignorecell) { + if (!c->lf && (c != lf->ignorecell)) { o = hasobmulti(c->obpile, oid, noids); if (o && !isdangerousob(o, lf, B_TRUE) && (canpickup(lf, o, 1) || caneat(lf,o)) ) { if (db) dblog(".oO { remote cell has ob i want (%s). setting f_targetcell. }",o->type->name); @@ -1096,29 +1130,33 @@ int lookforobs(lifeform_t *lf, int covetsonly) { } } if (!gothere) { - // remote cell has better weapon? - f = hasflag(lf->flags, F_WANTSBETTERWEP); - if (f) { - if (!covetsonly || (f->val[1] == B_COVETS)) { - - o = hasbetterweapon(lf, c->obpile); - if (o && !isdangerousob(o, lf, B_TRUE) && canpickup(lf, o, 1)) { - if (db) dblog(".oO { remote cell has better weapon (%s). setting f_targetcell }",o->type->name); - gothere = B_TRUE; + if (lfhasflag(lf, F_HUMANOID) && hasbp(lf, BP_WEAPON)) { + // remote cell has better weapon? + f = hasflag(lf->flags, F_WANTSBETTERWEP); + if (f) { + if (!covetsonly || (f->val[1] == B_COVETS)) { + + o = hasbetterweapon(lf, c->obpile); + if (o && !isdangerousob(o, lf, B_TRUE) && canpickup(lf, o, 1)) { + if (db) dblog(".oO { remote cell has better weapon (%s). setting f_targetcell }",o->type->name); + gothere = B_TRUE; + } } } } } if (!gothere) { - // remote cell has better armour? - f = hasflag(lf->flags, F_WANTSBETTERARM); - if (f) { - if (!covetsonly || (f->val[1] == B_COVETS)) { - - o = hasbetterarmour(lf, c->obpile); - if (o && !isdangerousob(o, lf, B_TRUE) && canpickup(lf, o, 1)) { - if (db) dblog(".oO { remote cell has better armour (%s). setting f_targetcell }",o->type->name); - gothere = B_TRUE; + if (lfhasflag(lf, F_HUMANOID)) { + // remote cell has better armour? + f = hasflag(lf->flags, F_WANTSBETTERARM); + if (f) { + if (!covetsonly || (f->val[1] == B_COVETS)) { + + o = hasbetterarmour(lf, c->obpile); + if (o && !isdangerousob(o, lf, B_TRUE) && canpickup(lf, o, 1)) { + if (db) dblog(".oO { remote cell has better armour (%s). setting f_targetcell }",o->type->name); + gothere = B_TRUE; + } } } } diff --git a/attack.c b/attack.c index 8dea92c..5fe6b8e 100644 --- a/attack.c +++ b/attack.c @@ -18,20 +18,60 @@ extern lifeform_t *player; int applyarmourdamage(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damtype) { - object_t *armour; - int adam; + object_t *armour = NULL; 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); + + // figure out what bit of armour was hit + + // special case - missiles against flak jacket + if (damtype == DT_PROJECTILE) { + object_t *o; + o = getequippedob(lf->pack, BP_BODY); + if (o && (o->type->id == OT_FLAKJACKET)) { + // stop ALL missile damage + armour = o; + } } - // pick a random piece of armour - armour = getrandomarmour(lf); + + if (!armour) { + // pick a random piece of armour + armour = getrandomarmour(lf); + } + + + if (armour) { - damtaken = takedamage(armour,adam, damtype); + int actualdam; + flag_t *rust; + // adjust how much damage to do to armour + if ( ((armour->type->id == OT_FLAKJACKET) && (damtype == DT_PROJECTILE)) || + (damtype == DT_ACID) || + hasflag(wep->flags, F_ARMOURPIERCE)) { + // ALL of damage reduction goes towards armour + actualdam = dam; + } else { + // half the damage reduction goes towards armour + actualdam = (dam / 2); + } + + // modify for rust + rust = hasflag(armour->flags, F_RUSTED); + if (rust) { + int multiplier = 1; + switch (rust->val[0]) { + case R_RUSTY: + multiplier = 2; + case R_VRUSTY: + multiplier = 6; + case R_TRUSTY: + multiplier = 10; + } + actualdam *= multiplier; + } + + + // actually apply the damage to the armour + damtaken = takedamage(armour,actualdam, damtype); } return damtaken; } @@ -268,9 +308,12 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) { ndam = 1; // determine extra damage for flaming etc. + // getextradam from USER too if (!willheal) { - getextradam(wep, &dam[0], &damtype[0], &ndam); + getextradamwep(wep, &dam[0], &damtype[0], &ndam); + getextradamlf(lf, &dam[0], &damtype[0], &ndam); } + } else { hit = B_FALSE; ndam = 0; @@ -282,8 +325,8 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) { flag_t *f; for (i = 0; i < ndam; i++) { int reduceamt; - int backstab = B_FALSE; + flag_t *rust; if (firstisbackstab && (i == 0)) backstab = B_TRUE; dblog("initial dam[%d] = %d",i,dam[i]); @@ -293,6 +336,25 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) { dblog("heavy blow makes dam[%d] = %d",i,dam[i]); } + // modify for rust + rust = hasflag(wep->flags, F_RUSTED); + if (rust) { + switch (damtype[i]) { + case DT_PIERCE: + case DT_SLASH: + if (rust->val[0] >= R_TRUSTY) { + dam[i] -= (pctof(50, dam[i])); + } else if (rust->val[0] >= R_VRUSTY) { + dam[i] -= (pctof(25, dam[i])); + } else { + dam[i] -= (pctof(10, dam[i])); + } + break; + default: + break; + } + } + // modify based on resistances adjustdamlf(victim, &dam[i], damtype[i]); dblog("adjusted for lf to dam[%d] = %d",i,dam[i]); @@ -525,6 +587,16 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) { fightback(victim, lf); } + // practice? + if (hit) { + skill_t *sk; + // extra damage for being skilled? + sk = getobskill(wep); + if (sk && !getskill(lf, sk->id)) { + practice(lf, sk->id); + } + } + // get rid of temp unarmed object pile if (op) { killobpile(op); @@ -624,7 +696,8 @@ int attackob(lifeform_t *lf, object_t *o) { // don't need to check for blessed vs mosnters // determine extra damage - getextradam(wep, &dam[0], &damtype[0], &ndam); + getextradamwep(wep, &dam[0], &damtype[0], &ndam); + getextradamlf(lf, &dam[0], &damtype[0], &ndam); for (i = 0; i < ndam; i++) { @@ -703,11 +776,22 @@ int getarmourdamreduction(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE d int reduceamt = 0; float reducepct; int ar; + object_t *o; ar = getarmourrating(lf); + reducepct = getdamreducepct(ar); reduceamt = (int) ceil((reducepct / 100.0) * (float)dam); + // special case + if (damtype == DT_PROJECTILE) { + o = getequippedob(lf->pack, BP_BODY); + if (o && (o->type->id == OT_FLAKJACKET)) { + // stop ALL missile damage + reduceamt = dam; + } + } + if (reduceamt < 0) reduceamt = 0; return reduceamt; } @@ -891,13 +975,60 @@ enum DAMTYPE getdamtype(object_t *wep) { return dt; } -int getextradam(object_t *wep, int *dam, enum DAMTYPE *damtype, int *ndam) { +int getextradamlf(lifeform_t *lf, int *dam, enum DAMTYPE *damtype, int *ndam) { + flag_t *f; + // special case - EXTRADAM goes onto INITIAL dam[] if the same type, rather than + // adding a new one. + for (f = lf->flags->first ; f ; f = f->next) { + if (f->id == F_EXTRADAM) { + int *damwhere; + int *damtypewhere; + int doinc = B_FALSE; + + if ((f->val[0] == NA) || (f->val[0] == *damtype)) { + damwhere = dam; + damtypewhere = damtype; + *(damwhere) += roll(f->text); // addition + } else { + damwhere = (dam + *ndam); + damtypewhere = (damtype + *ndam); + *(damwhere) = roll(f->text); // set + doinc = B_TRUE; + } + + *(damtypewhere) = f->val[0]; + + if ((f->lifetime == FROMOBEQUIP) || + (f->lifetime == FROMOBHOLD) || + (f->lifetime == FROMOBACTIVATE) ) { + object_t *obfrom; + obfrom = findobbyid(lf->pack, f->obfrom); + if (obfrom) { + int bonusdam = 0; + sumflags(obfrom->flags, F_BONUS, &bonusdam, NULL, NULL); + *(damwhere) += bonusdam; + } + } + + if (doinc) { + (*ndam)++; + } + } + } + return *dam; +} + +int getextradamwep(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 + *ndam) = rolldie(2,8); + *(dam + *ndam) = rolldie(2,6); *(damtype + *ndam) = DT_FIRE; (*ndam)++; + } else if (f->id == F_FROZEN) { + *(dam + *ndam) = rolldie(1,4); + *(damtype + *ndam) = DT_COLD; + (*ndam)++; } } return *dam; @@ -1019,6 +1150,7 @@ void getdamrangeunarmed(flag_t *f, int *min, int *max) { // roll for damage int getdamroll(object_t *o, lifeform_t *victim) { int dam; + int bonusdam = 0; flag_t *f; f = hasflag(o->flags, F_DAM); if (f) { @@ -1041,10 +1173,8 @@ int getdamroll(object_t *o, lifeform_t *victim) { } // modify for bonus - f = hasflag(o->flags, F_BONUS); - if (f) { - dam += f->val[0]; - } + sumflags(o->flags, F_BONUS, &bonusdam, NULL, NULL); + dam += bonusdam; if (dam < 0) dam = 0; @@ -1359,7 +1489,8 @@ void wepeffects(flagpile_t *fp, cell_t *where, int dam) { fid = f->val[0]; if (!lfhasflag(victim, fid)) { int passedcheck = B_FALSE; - if (!f->val[1] == NA) { + // do they get a saving throw? + if (f->val[1] != NA) { int scdiff; if (f->val[2] == NA) { scdiff = 20; // default @@ -1372,8 +1503,6 @@ void wepeffects(flagpile_t *fp, cell_t *where, int dam) { } if (!passedcheck) { - int val0; - val0 = f->val[1]; if (f->text) { char loctext[BUFLEN]; char *word, *dummy; @@ -1415,9 +1544,9 @@ void wepeffects(flagpile_t *fp, cell_t *where, int dam) { } else { strcpy(frombuf, "something unknown"); } - addtempflag(victim->flags, fid, val0, NA, NA, frombuf, howlong); + addtempflag(victim->flags, fid, NA, NA, NA, frombuf, howlong); } else { - addtempflag(victim->flags, fid, val0, NA, NA, NULL, howlong); + addtempflag(victim->flags, fid, NA, NA, NA, NULL, howlong); } } // end if passedcheck } // end (if victim doesn't already have the flag) diff --git a/attack.h b/attack.h index eeade8c..70fe95b 100644 --- a/attack.h +++ b/attack.h @@ -10,7 +10,8 @@ int getarmourdamreduction(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE d char *getattackverb(lifeform_t *lf, object_t *wep, 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 *ndam); +int getextradamlf(lifeform_t *lf, int *dam, enum DAMTYPE *damtype, int *ndam); +int getextradamwep(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); diff --git a/defs.h b/defs.h index 1b62811..25582bc 100644 --- a/defs.h +++ b/defs.h @@ -4,6 +4,30 @@ // MACROS #define MAXOF(a,b) (a > b ? a : b) +#define PRACTICETIME 50 // #attempts it takes to learn new skill + +#define WETTIME 10 // how long it takes for things to dry + +// ncurses colours +enum COLOUR { + C_BLACK = 0, + C_RED = 1, + C_GREEN = 2, + C_BROWN = 3, + C_BLUE = 4, + C_MAGENTA = 5, + C_CYAN = 6, + C_GREY = 7, + // bolded colours + C_YELLOW = 8, + C_WHITE = 9, + C_BOLDCYAN = 10, + C_BOLDBLUE = 11, + C_BOLDMAGENTA = 12, + C_ORANGE = 13, + C_BOLDGREEN = 14, +}; + // save/load #define MAPDIR "data/maps" #define SAVEDIR "data/save" @@ -169,7 +193,8 @@ enum LFCONDITION { #define DEF_WINDOWPCT 5 // -#define ANIMDELAY (1000000 / 100) // 1/100 of a second +//#define ANIMDELAY (1000000 / 100) // 1/100 of a second +#define ANIMDELAY (1000000 / 50) // 1/100 of a second #define MAXVISRANGE 10 // max visible range in full light @@ -386,9 +411,10 @@ enum DAMTYPE { DT_FALL = 23, DT_PETRIFY = 24, DT_POISON = 25, - DT_NONE = 26, // for direclty dealt damage, not really any type + DT_NECROTIC = 26, + DT_NONE = 27, // for direclty dealt damage, not really any type }; -#define MAXDAMTYPE 27 +#define MAXDAMTYPE 28 // Object Classes enum OBCLASS { @@ -482,7 +508,8 @@ enum RACE { R_ANT, R_ANTS, R_BAT, - R_HAWK, + R_HAWKBLOOD, + R_HAWKFROST, R_NEWT, R_RAT, R_SNAKE, @@ -507,6 +534,7 @@ enum JOB { J_GOD, J_ADVENTURER, J_ALLOMANCER, + J_BARBARIAN, J_COMMANDO, J_PLUMBER, J_PRINCE, @@ -635,6 +663,7 @@ enum OBTYPE { OT_SCR_LIGHT, OT_SCR_MAPPING, OT_SCR_MINDSCAN, + OT_SCR_PERMENANCE, OT_SCR_ENCHANT, OT_SCR_FREEZEOB, OT_SCR_REMOVECURSE, @@ -678,8 +707,10 @@ enum OBTYPE { // allomancy can't be learned from books // -- death OT_SB_ANIMATEDEAD, + OT_SB_DRAINLIFE, OT_SB_PAIN, OT_SB_PARALYZE, + OT_SB_POISONBOLT, OT_SB_INFINITEDEATH, OT_SB_WEAKEN, OT_SB_BLINDNESS, @@ -749,11 +780,14 @@ enum OBTYPE { OT_S_METALHEAL, // -- death OT_S_ANIMATEDEAD, + OT_S_DRAINLIFE, OT_S_PAIN, OT_S_PARALYZE, OT_S_INFINITEDEATH, OT_S_WEAKEN, OT_S_BLINDNESS, + OT_S_POISONBOLT, + OT_S_POSSESSION, // -- divination OT_S_DETECTAURA, OT_S_DETECTLIFE, @@ -772,6 +806,7 @@ enum OBTYPE { OT_S_FLAMEBURST, OT_S_BURNINGWAVE, // -- elemental - ice + OT_S_COLDBURST, OT_S_CONECOLD, OT_S_FREEZEOB, // -- gravity @@ -824,11 +859,13 @@ enum OBTYPE { OT_A_DEBUG, OT_A_ENHANCE, OT_A_LEARN, + OT_A_LEVELUP, // abilities OT_A_GRAB, OT_A_CRUSH, OT_A_JUMP, OT_A_SPRINT, + OT_A_SWOOP, OT_A_EMPLOY, OT_A_HEAVYBLOW, OT_A_INSPECT, @@ -852,6 +889,7 @@ enum OBTYPE { OT_BUGLAMP, OT_CANDLE, OT_GUNPOWDER, + OT_LAMPOIL, OT_LANTERNOIL, OT_LOCKPICK, OT_PICKAXE, @@ -881,6 +919,7 @@ enum OBTYPE { OT_BROKENGLASS, OT_ICECHUNK, OT_ICESHEET, + OT_SPLASHWATER, OT_PUDDLEWATER, OT_PUDDLEWATERL, OT_ACIDPUDDLE, @@ -953,11 +992,14 @@ enum OBTYPE { // rings OT_RING_INVIS, OT_RING_INVULN, + OT_RING_LUCK, + OT_RING_MANA, OT_RING_MPREGEN, OT_RING_PROTFIRE, OT_RING_REGENERATION, OT_RING_RESISTMAG, OT_RING_SEEINVIS, + OT_RING_WOUNDING, // animal weapons OT_CLAWS, OT_FISTS, @@ -1018,6 +1060,7 @@ enum OBTYPE { OT_SLING, OT_BOW, OT_LONGBOW, + OT_CROSSBOW, OT_CROSSBOWHAND, // holy weapons OT_HANDOFGOD, @@ -1093,7 +1136,8 @@ enum FLAG { F_BONUS, // val0=bonus/penalty to damage/armour. ie. +1 sword F_THROWMISSILE, // weapon would make a good thrown missle - used by AI F_UNIQUE, // only one may appear - F_GLYPH, // override the glyph with the first char of text + F_GLYPH, // override the glyph with the first char of text. + // v0 is either NA (white) or colourid (C_xxx). F_NOPICKUP, // cannot pick this up 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 @@ -1179,6 +1223,11 @@ enum FLAG { 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 (ie fire damage) + F_CANGETWET, // object will get F_WET if hit by water + // v0 = enum WETNESS. v1 = how long + F_WET, // object is wet + F_RUSTED, // object is rusty + // v0 = enum RUSTINESS. // object mods/effects F_ONFIRE, // burning, also deals extra fire damage F_HEADLESS, // for corpses. can go on LFs too. @@ -1189,6 +1238,7 @@ enum FLAG { F_OBATTACKDELAY, // how long weapon takes to attack F_USESSKILL, // weapon needs skill sk_v0 F_CANHAVEOBMOD, // weapon can have obmod om_v0 applied + F_ATTREQ, // requires attrib v0 to be at least bracket v1 F_DAMTYPE, // val0 = damage type F_DAM, // val0 = ndice, val1 = nsidesondie, val2 = mod F_MISSILEDAM, // val0 = dam if it hits (without speed multiplier) @@ -1196,7 +1246,7 @@ enum FLAG { 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 + F_FIRESPEED, // how fast this weapon shoots projectiles F_AMMOOB, // what object this weapon fires F_RANGE, // range of projectile firing weapon F_FLAMESTRIKE, // causes fires where you hit @@ -1257,7 +1307,7 @@ enum FLAG { // using their strength // player only flags F_DONEDARKMSG, // tells the game not to say 'it is very dark here' - // lifeform flags + // lifeform flags / lf flags F_DEBUG, // debugging enabled F_ATTRMOD, // modify attribute val0 by val1. ie. 0=A_STR,1=-3 F_ATTRSET, // forces attribute val0 to be val1. ie. 0=A_STR,1=18 @@ -1283,9 +1333,10 @@ enum FLAG { F_GUNTARGET, // current projectile weapon target F_CASTINGSPELL, // set while the player is casting a spell // v0 is spell id - // ABILITY/SPELL FLAGS + // ABILITY/SPELL FLAGS / ability flags / spell flags F_FAILEDINSPECT, // lf has failed an inspect check for item id v0 F_BOOSTSPELL, // v0 is active boost spell + F_SWOOPRANGE, // v0 = how far a flying creature can swoop // MONSTER AI FLAGS F_XPVAL, // force xp val for killing this lf to v0 F_HOSTILE, // lf will attack the player if in sight @@ -1334,6 +1385,7 @@ enum FLAG { // v0=slot (0-9) // text=spell text // for monsters + F_HUMANOID, // this race can wear armour / use weapons F_INSECT, // this race is classed as an insect F_ANIMAL, // this race is classed as an animal F_UNDEAD, // this race is classed as undead @@ -1355,19 +1407,26 @@ enum FLAG { F_BEINGSTONED,// turn to stone when v0 drops to zero. (drops 1/turn) F_BLIND, // cannot see anything F_CANCAST, // can cast the spell val0 (need MP) - F_CANWILL, // can cast the spell val0 without using MP + F_CANWILL, // can cast the spell/ability val0 without using MP // v1 is counter untiluse // v2 is what you need to use it // ie. when v1 == v2, ability is ready. // text is other options, semicolon seperated: // pw:xx; cast the spell at power xx + // dam:xdy+b; damage + // needgrab:xx; do you need to grab first? F_CHARMEDBY,// you've been charmed by lf id v0 F_DETECTAURAS, // autodetect bless/curse F_DETECTLIFE, // autodetect nearby lifeforms in orthogonal dist v0 F_DETECTMAGIC, // autodetect magic/special objects F_DETECTMETAL, // autodetect nearby metal F_DETECTOBS, // autodetect nearby obs in orthog dist v0 + F_EXTRADAM, // do 'text' extra damage of damtype v0 when you hit + // if v1 is TRUE, also deal extra damage based on + // the flagpile's F_BONUS flag. F_EXTRAINFO, // knows extra info + F_EXTRALUCK, // lf gets +v0 to all skill checks! + F_EXTRAMP, // lf has +v0 % extra maxmp F_FLYING, // lf is flying F_FASTACT, // modifier for action speed F_FASTMOVE, // modifier for move speed @@ -1406,13 +1465,14 @@ enum FLAG { F_SLOWMOVE, // modifier for move speed F_XRAYVIS, //val0=num of walls we can see through F_CANSEETHROUGHMAT, //val0=kind of material you can see through - F_SPRINTING, // you are sprinting + F_SPRINTING, // v0=true: you are sprinting. false=you are tired F_TIRED, // you are too tired to sprint F_DODGES, // you dodge missed attacks F_NOTIME, // this lf's actions don't take time F_PERCEPTION, // v0 = 0-20. perception level. // skills F_HASSKILL, // lf has skill v0 at level v1 + F_PRACTICINGSKILL, // lf is pract skill v0 // COMBAT F_HASATTACK, // objecttype id to use when attacking unarmed // if val0-3 are filled in, they override the object's @@ -1569,6 +1629,13 @@ enum ERROR { E_NOTKNOWN = 35, E_TOOPOWERFUL = 36, E_NEEDGRAB = 37, + E_DOORINWAY = 38, + E_NOCANNIBUL = 39, + E_LOWCON = 40, + E_LOWDEX = 41, + E_LOWIQ = 42, + E_LOWSTR = 43, + E_WONT = 44, }; @@ -1657,9 +1724,18 @@ typedef struct cell_s { int visited; } cell_t; +typedef struct glyph_s { + char ch; + int colour; +} glyph_t; + typedef struct celltype_s { int id; // eg. dungeonfloor, wall, door + struct glyph_s glyph; + /* char glyph; // how to display it + int colour; // which colour? + */ char *name; // name of cell type int solid; // can you walk through it? int transparent; // can you see through it? @@ -1676,7 +1752,7 @@ typedef struct race_s { enum RACE baseid; struct material_s *material; char *name; - char glyph; + struct glyph_s glyph; float weight; struct flagpile_s *flags; // speed modifiers @@ -1853,7 +1929,7 @@ typedef struct objectclass_s { enum OBCLASS id; char *name; char *desc; - char glyph; + glyph_t glyph; struct flagpile_s *flags; struct objectclass_s *next, *prev; } objectclass_t; @@ -1890,6 +1966,19 @@ typedef struct object_s { struct object_s *next, *prev; } object_t; +// wetness +enum WETNESS { + W_DRY = 0, + W_DAMP = 1, + W_WET = 2, + W_SOAKED = 3, +}; +enum RUSTINESS { + R_RUSTY = 1, + R_VRUSTY = 2, + R_TRUSTY = 3, +}; + enum OBMOD { OM_FLAMING, OM_FROZEN, @@ -1897,17 +1986,24 @@ enum OBMOD { OM_MASTERWORK, OM_POISONED, OM_SHODDY, + OM_WET1, + OM_WET2, + OM_WET3, + OM_RUSTY1, + OM_RUSTY2, + OM_RUSTY3, }; #define MAXOBMODS 4 enum BRAND { BR_BALANCE, - BR_DEXTERITY, + BR_NIMBLENESS, BR_FEEBLENESS, BR_FLIGHT, BR_GIANTSTRENGTH, + BR_HEALTH, BR_IMPACT, - BR_INTELLIGENCE, + BR_THINKING, BR_KNOWLEDGE, BR_LEVITATION, BR_FEATHERFALL, @@ -1918,7 +2014,7 @@ enum BRAND { BR_REVENGE, BR_SLOTH, BR_SPEED, - BR_STRENGTH, + BR_POWER, BR_SWIFTNESS, BR_TELEKINESIS, BR_TELEPATHY, diff --git a/flag.c b/flag.c index 062f5f5..3ad2aa0 100644 --- a/flag.c +++ b/flag.c @@ -49,6 +49,13 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, } } + // override values sometimes + /* + if ((id == F_WET) && (val2 == NA)) { + val2 = WETTIME; + } + */ + if (fp->first == NULL) { fp->first = malloc(sizeof(flag_t)); f = fp->first; @@ -165,6 +172,16 @@ flagpile_t *addflagpile(lifeform_t *owner, object_t *ob) { return fp; } +void copyflag(flagpile_t *dst, flagpile_t *src, enum FLAG id) { + flag_t *f; + for (f = src->first ; f ; f = f->next) { + if (f->id == id) { + addflag_real(dst, f->id, f->val[0], f->val[1], f->val[2], f->text, + f->lifetime, f->known, -1); + } + } +} + void copyflags(flagpile_t *dst, flagpile_t *src, int lifetime) { flag_t *f; for (f = src->first ; f ; f = f->next) { @@ -328,24 +345,6 @@ void killflag(flag_t *f) { lf->polyrevert = B_TRUE; } - if (lf && (f->id == F_SPRINTING)) { - int howlong; - int slev; - - // you get tired when you finish sprinting - howlong = 15; - // adjust for athletics skill. -2 per level. - slev = getskill(lf, SK_ATHLETICS); - if (slev != PR_INEPT) { - howlong -= (2*slev); - } - // adjust for constitution - howlong = howlong - (int) ((float)howlong * (getstatmod(lf, A_CON) / 100) ); - // enforce minimum - if (howlong < 1) howlong = 1; - addtempflag(f->pile, F_TIRED, B_TRUE, NA, NA, NULL, howlong); - } - // free mem // remove from list @@ -419,6 +418,18 @@ void timeeffectsflag(flag_t *f, int howlong) { break; } } + } else if (f->lifetime == 5) { + if (isplayer(f->pile->owner)) { + switch (f->id) { + case F_SPRINTING: + if (f->val[0]) { + warn("You will have to stop sprinting soon..."); + } + break; + default: + break; + } + } } else if (f->lifetime == 2) { if (isplayer(f->pile->owner)) { switch (f->id) { @@ -461,6 +472,38 @@ void timeeffectsflag(flag_t *f, int howlong) { break; } } + // sprinting is special + if (f->id == F_SPRINTING) { + if (f->val[0]) { + enum SKILLLEVEL slev; + lifeform_t *who; + int tiredtime; + who = f->pile->owner; + // now you get slow + // you get tired when you finish sprinting + tiredtime = 15; + + // adjust for athletics skill. -2 per level. + slev = getskill(who, SK_ATHLETICS); + if (slev != PR_INEPT) { + tiredtime -= (2*slev); + } + // adjust for constitution + tiredtime = tiredtime - (int) ((float)tiredtime * (getstatmod(who, A_CON) / 100) ); + // enforce minimum + if (tiredtime < 1) tiredtime = 1; + f->val[0] = B_FALSE; + f->lifetime = tiredtime; + + if (isplayer(who)) { + msg("You are exhausted."); + } else if (cansee(player, who)) { + char lfname[BUFLEN]; + getlfname(who, lfname); + msg("%s looks exhausted.",lfname); + } + } + } } } @@ -473,6 +516,22 @@ void timeeffectsflag(flag_t *f, int howlong) { } else { // stoning failed. stop being stoned. killflag(f); + return; + } + } + } + + if (f->id == F_WET) { + f->val[1]--; + if (f->val[1] <= 0) { + f->val[0]--; + if (f->val[0] <= W_DRY) { + killflag(f); + return; + } else { + // reset timer + f->val[1] = WETTIME; + // TODO: announce } } } diff --git a/flag.h b/flag.h index f2bcf31..1c1a687 100644 --- a/flag.h +++ b/flag.h @@ -6,6 +6,7 @@ flag_t *addflag(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char flag_t *addtempflag(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char *text, int timeleft); flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char *text, int lifetime, int known, long obfromid); flagpile_t *addflagpile(lifeform_t *owner, object_t *o); +void copyflag(flagpile_t *dst, flagpile_t *src, enum FLAG id); void copyflags(flagpile_t *dst, flagpile_t *src, int lifetime); int flagcausesredraw(lifeform_t *lf, enum FLAG fid); int flagstacks(enum FLAG fid); diff --git a/io.c b/io.c index 090f129..1ef7172 100644 --- a/io.c +++ b/io.c @@ -26,6 +26,8 @@ WINDOW *statwin; int statdirty = B_TRUE; +int hascolour = B_TRUE; + extern int needredraw; extern int numdraws; @@ -117,7 +119,7 @@ void addpromptq(prompt_t *p, char *q) { p->nqs++; } -void anim(cell_t *src, cell_t *dst, char ch) { +void anim(cell_t *src, cell_t *dst, char ch, int colour) { int deltax, deltay; int numpixels; int d; @@ -127,6 +129,7 @@ void anim(cell_t *src, cell_t *dst, char ch) { int x1,y1; int x; int y; + glyph_t gl; //int maxvisrange; //int modmaxvisrange; //int xray = B_FALSE; @@ -181,8 +184,13 @@ void anim(cell_t *src, cell_t *dst, char ch) { yinc2 = - yinc2; } + x = x1; y = y1; + gl.ch = ch; + gl.colour = colour; + // hide cursor + curs_set(0); for (i = 0; i < numpixels ; i++) { cell_t *cell; @@ -190,11 +198,12 @@ void anim(cell_t *src, cell_t *dst, char ch) { cell = getcellat(src->map, x, y); // update screen - updateviewfor(cell); - drawlevelfor(player); if (haslos(player, cell)) { + updateviewfor(cell); + drawlevelfor(player); // draw char & cursor at its current pos... - mvwprintw(gamewin, cell->y - viewy, cell->x - viewx, "%c", ch); + drawglyph(&gl, cell->x - viewx, cell->y - viewy); + //mvwprintw(gamewin, cell->y - viewy, cell->x - viewx, "%c", gl.ch); wmove(gamewin, cell->y - viewy, cell->x - viewx); wrefresh(gamewin); usleep(ANIMDELAY); @@ -215,13 +224,20 @@ void anim(cell_t *src, cell_t *dst, char ch) { x += xinc; y += yinc; } + // show cursor + curs_set(1); } -void animradial(cell_t *src, int radius, char ch) { +void animradial(cell_t *src, int radius, char ch, int colour) { + glyph_t gl; int i; int x,y; cell_t *c; + gl.ch = ch; + gl.colour = colour; + // hide cursor + curs_set(0); for (i = 0; i <= radius; i++) { int drawn = B_FALSE; @@ -234,7 +250,8 @@ void animradial(cell_t *src, int radius, char ch) { c = getcellat(src->map, x, y); if (c && haslos(player, c) && (getcelldistorth(src, c) <= i)) { // draw char & cursor at its current pos... - mvwprintw(gamewin, c->y - viewy, c->x - viewx, "%c", ch); + //mvwprintw(gamewin, c->y - viewy, c->x - viewx, "%c", ch); + drawglyph(&gl, c->x - viewx, c->y - viewy); drawn = B_TRUE; } } @@ -245,14 +262,21 @@ void animradial(cell_t *src, int radius, char ch) { usleep(ANIMDELAY); } } + // show cursor + curs_set(1); } -void animradialorth(cell_t *src, int radius, char ch) { +void animradialorth(cell_t *src, int radius, char ch,int colour) { + glyph_t gl; int i; int x,y; cell_t *c; + gl.ch = ch; + gl.colour = colour; + // hide cursor + curs_set(0); for (i = 0; i <= radius; i++) { int drawn = B_FALSE; @@ -265,7 +289,8 @@ void animradialorth(cell_t *src, int radius, char ch) { 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); + //mvwprintw(gamewin, c->y - viewy, c->x - viewx, "%c", ch); + drawglyph(&gl, c->x - viewx, c->y - viewy); drawn = B_TRUE; } } @@ -276,7 +301,8 @@ void animradialorth(cell_t *src, int radius, char ch) { usleep(ANIMDELAY); } } - + // show cursor + curs_set(1); } char askchar(char *prompt, char *validchars, char *def, int showchars) { @@ -826,8 +852,24 @@ int announceflaggain(lifeform_t *lf, flag_t *f) { } break; case F_POISONED: + msg("%s %s very sick.", lfname, isplayer(lf) ? "feel" : "looks"); + donesomething = B_TRUE; + break; + case F_EXTRADAM: if (isplayer(lf)) { // don't know if monsters get it - msg("You feel very sick."); + msg("You feel more dangerous!"); + donesomething = B_TRUE; + } + break; + case F_EXTRAMP: + if (isplayer(lf)) { // don't know if monsters get it + msg("Your magical power feels boosted!"); + donesomething = B_TRUE; + } + break; + case F_EXTRALUCK: + if (isplayer(lf)) { // don't know if monsters get it + msg("You feel lucky!"); donesomething = B_TRUE; } break; @@ -938,13 +980,13 @@ int announceflaggain(lifeform_t *lf, flag_t *f) { msg("%s %s sprinting!",lfname, isplayer(lf) ? "start" : "starts"); donesomething = B_TRUE; break; + case F_TIRED: if (isplayer(lf)) { msg("You are exhausted."); - } else { + } else if (cansee(player, lf)) { msg("%s looks exhausted.",lfname); } - donesomething = B_TRUE; break; case F_VISRANGEMOD: if (isplayer(lf)) { // don't know if monsters get it @@ -1104,6 +1146,24 @@ int announceflagloss(lifeform_t *lf, flag_t *f) { donesomething = B_TRUE; } break; + case F_EXTRADAM: + if (isplayer(lf)) { // don't know if monsters lose it + msg("You no longer feel more dangerous."); + donesomething = B_TRUE; + } + break; + case F_EXTRALUCK: + if (isplayer(lf)) { // don't know if monsters get it + msg("You feel less lucky."); + donesomething = B_TRUE; + } + break; + case F_EXTRAMP: + if (isplayer(lf)) { // don't know if monsters get it + msg("Your magical power no longer feels boosted."); + donesomething = B_TRUE; + } + break; case F_FASTACT: msg("%s %s",lfname, isplayer(lf) ? "are no longer accelerated." : "is no longer accelerated."); donesomething = B_TRUE; @@ -1120,10 +1180,8 @@ int announceflagloss(lifeform_t *lf, flag_t *f) { msg("%s no longer looks quite so friendly!", lfname); break; case F_POISONED: - if (isplayer(lf)) { // don't know if monsters lose it - msg("You feel less sick now."); - donesomething = B_TRUE; - } + msg("%s %s less sick now.", lfname, isplayer(lf) ? "feel" : "looks"); + donesomething = B_TRUE; break; case F_DODGES: if (isplayer(lf)) { // don't know if monsters lose it @@ -1291,9 +1349,17 @@ int announceflagloss(lifeform_t *lf, flag_t *f) { donesomething = B_TRUE; break; case F_SPRINTING: - if (isplayer(lf)) { // don't know if monsters lose it (but you'll see them get exhausted) - msg("You stop sprinting."); - donesomething = B_TRUE; + if (f->val[0]) { + if (isplayer(lf)) { // don't know if monsters lose it (but you'll see them get exhausted) + msg("You stop sprinting."); + donesomething = B_TRUE; + } + } else { + if (isplayer(lf)) { // don't know if monsters get it + msg("You are no longer exhausted."); + } else { + msg("%s looks less exhausted.",lfname); + } } break; case F_TIRED: @@ -1383,7 +1449,7 @@ int announceobflaggain(object_t *o, flag_t *f) { break; case F_PRODUCESLIGHT: donesomething = B_TRUE; - if (o->birthtime != curtime) msg("%s starts glowing!",prefix); + if (o->birthtime != curtime) msg("%s start%s glowing!",prefix, (o->amt == 1) ? "s" : ""); break; default: // no message break; @@ -1394,6 +1460,7 @@ int announceobflaggain(object_t *o, flag_t *f) { void announceobflagloss(object_t *o, flag_t *f) { char obname[BUFLEN]; char prefix[BUFLEN]; + char isare[BUFLEN]; cell_t *loc; loc = getoblocation(o); @@ -1418,17 +1485,20 @@ void announceobflagloss(object_t *o, flag_t *f) { } if (o->amt == 1) { - strcat(prefix, " is"); + strcat(isare, "is"); } else { - strcat(prefix, " are"); + strcat(isare, "are"); } switch (f->id) { case F_ONFIRE: - msg("%s no longer on fire.",prefix); + msg("%s %s no longer on fire.",prefix,isare); break; case F_PRODUCESLIGHT: - msg("%s no longer glowing.",prefix); + msg("%s %s no longer glowing.",prefix,isare); + break; + case F_WET: + msg("%s %s out.",prefix, (o->amt == 1) ? "dries" : "dry"); break; default: // no message break; @@ -2195,6 +2265,13 @@ void describeob(object_t *o) { sprintf(buf, "It inflicts %d-%d %s damage",mindam,maxdam, getdamname(damtype)); } + dicetotext(f->val[0], f->val[1], f->val[2], NULL, NULL, dicebuf, NULL); + + strcat(buf, " ("); + strcat(buf, dicebuf); + strcat(buf, ")."); + + /* if (f->val[2] == NA) { sprintf(dicebuf, " (%dd%d).", f->val[0], f->val[1]); } else { @@ -2203,6 +2280,7 @@ void describeob(object_t *o) { abs(f->val[2])); } strcat(buf,dicebuf); + */ mvwprintw(mainwin, y, 0, "%s",buf); y++; } else { @@ -2330,6 +2408,18 @@ void describeob(object_t *o) { y++; } + f = hasflag(o->flags, F_WET); + if (f) { + mvwprintw(mainwin, y, 0, "It is wet."); + y++; + } + f = hasflag(o->flags, F_RUSTED); + if (f) { + mvwprintw(mainwin, y, 0, "It is rusty."); + y++; + } + + f = hasflag(o->flags, F_ACTIVATED); if (f) { mvwprintw(mainwin, y, 0, "It is activated."); @@ -2366,7 +2456,7 @@ void describeob(object_t *o) { mvwprintw(mainwin, y, 0, "%s will detect nearby objects.", buf); y++; break; case F_DETECTMAGIC: - mvwprintw(mainwin, y, 0, "%s will detect magical enchantemnts on objects.", buf); y++; + mvwprintw(mainwin, y, 0, "%s will detect magical enchantments on objects.", buf); y++; break; case F_DETECTMETAL: mvwprintw(mainwin, y, 0, "%s will detect nearby metal.", buf); y++; @@ -2374,6 +2464,15 @@ void describeob(object_t *o) { case F_EXTRAINFO: mvwprintw(mainwin, y, 0, "%s provides enhanced knowledge to you.", buf); y++; break; + case F_EXTRADAM: + mvwprintw(mainwin, y, 0, "%s will cause you to deal more damage.", buf); y++; + break; + case F_EXTRALUCK: + mvwprintw(mainwin, y, 0, "%s will give you a bonus to all skill checks.", buf); y++; + break; + case F_EXTRAMP: + mvwprintw(mainwin, y, 0, "%s will increase your mana pool by %d%%.", buf, f->val[0]); y++; + break; case F_FASTACT: mvwprintw(mainwin, y, 0, "%s will speed up your actions.", buf); y++; break; @@ -2968,7 +3067,7 @@ void dovendingmachine(lifeform_t *lf, object_t *vm) { ch = f->val[0]; if (strlen(f->text)) { - o = addob(op, f->text); + o = addobject(op, f->text, B_FALSE); // no stacking! // remember letter o->letter = ch; // make object fully known @@ -3004,6 +3103,7 @@ void dovendingmachine(lifeform_t *lf, object_t *vm) { strcat(choices, temp); // construct string o = hasobletter(op, ch); + // get the name of the object getobname(o, obname, o->amt); sprintf(buf, "%c - %s", ch, obname); sprintf(buf2, "%-60s$%d",buf,getobvalue(o)); @@ -3204,6 +3304,8 @@ void dolook(cell_t *where) { seensomething = B_TRUE; } + + // writing here? if (where->writing && !isblind(player)) { msg("There is a magical inscription here:"); @@ -3886,7 +3988,7 @@ void dorest(void) { // can we rest? if (canrest(player)) { int willtrain = B_FALSE; - if (player->skillpoints) { + if (player->skillpoints || lfhasflag(player, F_STATGAINREADY)) { int ch; ch = askchar("Would you like to train your skills?","yn","y", B_TRUE); if (ch == 'y') { @@ -4016,6 +4118,11 @@ void dothrow(obpile_t *op) { object_t *o; char buf[BUFLEN],buf2[BUFLEN]; + if (!hasbp(player, BP_HANDS)) { + msg("You have no hands to throw with!"); + return; + } + // ask which object to throw o = askobject(op, "Throw what", NULL, AO_NONE); if (o) { @@ -4131,48 +4238,58 @@ int downline(int *y, int h, char *heading, char *subheading, char *bottomstring, // draw a cell which we remember, but can't see void drawunviscell(cell_t *cell, int x, int y) { - char glyph; + glyph_t glyph; object_t *o; - if (cell->type->glyph == '.') { - glyph = ' '; - } else { - glyph = cell->type->glyph; + + // copy from cell + glyph = cell->type->glyph; + + if (glyph.ch == '.') { + glyph.ch = ' '; } // show staircases... o = hasobwithflag(cell->obpile, F_CLIMBABLE); if (o) { - glyph = getglyph(o); + glyph = *(getglyph(o)); } // show dungeon features o = hasobofclass(cell->obpile, OC_DFEATURE); if (o) { - glyph = getglyph(o); + glyph = *(getglyph(o)); } - mvwprintw(gamewin, y, x, "%c", glyph); + //mvwprintw(gamewin, y, x, "%c", glyph); + drawglyph(&glyph, x, y); +} + +void drawglyph(glyph_t *g, int x, int y) { + int col; + col = g->colour; + setcol(gamewin, g->colour); + mvwprintw(gamewin, y, x, "%c", g->ch); + unsetcol(gamewin, g->colour); } void drawcell(cell_t *cell, int x, int y) { - // draw ground - mvwprintw(gamewin, y, x, "%c", cell->type->glyph); + drawglyph(&cell->type->glyph, x, y); } // draw a cell that we have LOS to. void drawcellwithcontents(cell_t *cell, int x, int y) { if (cell->lf && cansee(player, cell->lf)) { // lifeform here that we can see - char ch; + glyph_t *gl; // draw the lf's race glyph - ch = getlfglyph(cell->lf); - mvwprintw(gamewin, y, x, "%c", ch); + gl = getlfglyph(cell->lf); + drawglyph(gl, x, y); return; } else { void *thing; - char glyph; + glyph_t glyph; // scanned lf here? if (isinscanrange(cell, &thing, NULL, &glyph) == TT_MONSTER) { //mvwprintw(gamewin, y-viewy, x-viewx, "%c", glyph); - mvwprintw(gamewin, y, x, "%c", glyph); + drawglyph(&glyph, x, y); return; } } @@ -4183,12 +4300,13 @@ void drawcellwithcontents(cell_t *cell, int x, int y) { // draw highest object in sort order o = gettopobject(cell); if (o) { - mvwprintw(gamewin, y, x, "%c", getglyph(o)); + drawglyph(getglyph(o), x, y); } else { // should never happen. if it does, just show the // first object dblog("Warn: sorted object glyph drawing matching nothing!"); - mvwprintw(gamewin, y, x, "%c", cell->obpile->first->type->obclass->glyph); + //mvwprintw(gamewin, y, x, "%c", cell->obpile->first->type->obclass->glyph); + drawglyph(&cell->obpile->first->type->obclass->glyph, x, y); } } else { // draw cell normally @@ -4217,7 +4335,7 @@ void drawlevelfor(lifeform_t *lf) { if (cell) { void *thing; char desc[BUFLEN]; - char glyph; + glyph_t glyph; if (haslos(lf, cell)) { drawcellwithcontents(cell, x-viewx, y-viewy); } else { @@ -4225,7 +4343,7 @@ void drawlevelfor(lifeform_t *lf) { switch (isinscanrange(cell, &thing, desc, &glyph)) { case TT_MONSTER: case TT_OBJECT: - mvwprintw(gamewin, y-viewy, x-viewx, "%c", glyph); + drawglyph(&glyph, x, y); break; default: if (cell->known) { @@ -4254,11 +4372,33 @@ void initgfx(void) { int msgwinh = 2; int statwinh = 2; mainwin = initscr(); + + // colour setup if (!has_colors()) { printf("Terminal does not support colour.\n"); + hascolour = B_FALSE; exit(1); } start_color(); + + init_pair(C_BLACK, COLOR_BLACK, COLOR_BLACK); + init_pair(C_RED, COLOR_RED, COLOR_BLACK); + init_pair(C_GREEN, COLOR_GREEN, COLOR_BLACK); + init_pair(C_BROWN, COLOR_YELLOW, COLOR_BLACK); + init_pair(C_YELLOW, COLOR_YELLOW, COLOR_BLACK); + init_pair(C_BLUE, COLOR_BLUE, COLOR_BLACK); + init_pair(C_MAGENTA, COLOR_MAGENTA, COLOR_BLACK); + init_pair(C_CYAN, COLOR_CYAN, COLOR_BLACK); + init_pair(C_GREY, COLOR_WHITE, COLOR_BLACK); + + init_pair(C_YELLOW, COLOR_YELLOW, COLOR_BLACK); + init_pair(C_WHITE, COLOR_WHITE, COLOR_BLACK); + init_pair(C_BOLDCYAN, COLOR_CYAN, COLOR_BLACK); + init_pair(C_BOLDBLUE, COLOR_BLUE, COLOR_BLACK); + init_pair(C_BOLDMAGENTA, COLOR_MAGENTA, COLOR_BLACK); + init_pair(C_BOLDGREEN, COLOR_GREEN, COLOR_BLACK); + init_pair(C_ORANGE, COLOR_RED, COLOR_BLACK); + noecho(); cbreak(); nodelay(mainwin, FALSE); @@ -4709,10 +4849,21 @@ void handleinput(void) { f = hasflag(player->flags, F_RUNNING); if (f) { int dir; + int hasgettableobs = B_FALSE; dir = f->val[0]; + object_t *o; + + + for (o = player->cell->obpile->first ; o ; o = o->next) { + if (!hasflag(o->flags, F_NOPICKUP)) { + hasgettableobs = B_TRUE; + break; + } + } + // something here? - if (player->cell->obpile->first) { + if (hasgettableobs) { stoprunning(player); } else if (!canmove(player, dir, NULL)) { // can't move anymore? stoprunning(player); @@ -5152,6 +5303,8 @@ void msg_real(char *format, ... ) { if (db) dblog("adding to msgbuf: [%s]",buf); + + assert(!strchr(buf, '#')); // ie. can the message buffer fit: // what is already there + 2 spaces + the new text + '--more--' ? //if (strlen(msgbuf) + 2 + strlen(buf) + strlen(MORESTRING) >= SCREENW) { @@ -5177,6 +5330,21 @@ void msg_real(char *format, ... ) { } +int needsbold(enum COLOUR col) { + switch (col) { + case C_YELLOW: + case C_WHITE: + case C_BOLDCYAN: + case C_BOLDBLUE: + case C_BOLDMAGENTA: + case C_BOLDGREEN: + case C_ORANGE: + return B_TRUE; + default: + break; + } + return B_FALSE; +} void nothinghappens(void) { msg("Nothing seems to happen."); @@ -5198,40 +5366,78 @@ void drawstatus(void) { wclear(statwin); xpleft = getxpforlev(player->level + 1) - player->xp; - sprintf(buf, "[%-26s] Lv:%d Next:%ld", pname, - player->level, xpleft); + sprintf(buf, "[%-26s] Lv:%d", pname, + player->level); + mvwprintw(statwin, 0, 0, buf); + if ((player->skillpoints == 0) && (getattpoints(player) == 0)) { + wprintw(statwin, " Next:%ld",xpleft); + } else { + setcol(statwin, C_BOLDGREEN); + wprintw(statwin, " LevUp",xpleft); + unsetcol(statwin, C_BOLDGREEN); + } + // blinded? + if (isblind(player)) { + setcol(statwin, C_RED); + wprintw(statwin, " Blind"); + unsetcol(statwin, C_RED); + } // paralysed somehow? if (isimmobile(player)) { - strcat(buf, " Immobile"); + setcol(statwin, C_RED); + wprintw(statwin, " Immobile"); + unsetcol(statwin, C_RED); } else { // show player action speed getspeedname(getactspeed(player), buf2); if (strcmp(buf2, "normal")) { - strcat(buf, " Act:"); + enum COLOUR col; + if (getactspeed(player) < SP_NORMAL) { + col = C_GREEN; + } else { + col = C_RED; + } + setcol(statwin, col); + wprintw(statwin, " Act:"); capitaliseall(buf2); - strcat(buf, buf2); + wprintw(statwin, "%s", buf2); + unsetcol(statwin, col); } // show player movement speed getspeedname(getmovespeed(player), buf2); if (strcmp(buf2, "normal")) { - strcat(buf, " Mv:"); + enum COLOUR col; + if (getmovespeed(player) < SP_NORMAL) { + col = C_GREEN; + } else { + col = C_RED; + } + setcol(statwin, col); + wprintw(statwin, " Mv:"); capitaliseall(buf2); - strcat(buf, buf2); + wprintw(statwin, "%s", buf2); + unsetcol(statwin, col); } } // burdened somehow? switch (isburdened(player)) { case BR_BURDENED: - strcat(buf, " Burdened"); + setcol(statwin, C_BROWN); + wprintw(statwin, " Burdened"); + unsetcol(statwin, C_BROWN); break; case BR_STRAINED: - strcat(buf, " Strained"); + setcol(statwin, C_RED); + wprintw(statwin, " Strained"); + unsetcol(statwin, C_RED); break; case BR_OVERLOADED: - strcat(buf, " Overloaded"); + setcol(statwin, C_YELLOW); + wprintw(statwin, " Overloaded"); + unsetcol(statwin, C_YELLOW); break; default: break; @@ -5239,11 +5445,12 @@ void drawstatus(void) { // show certain flags if (lfhasflag(player, F_POISONED)) { - strcat(buf, " Poisoned"); + setcol(statwin, C_GREEN); + wprintw(statwin, " Poisoned"); + unsetcol(statwin, C_GREEN); } - mvwprintw(statwin, 0, 0, buf); - + //mvwprintw(statwin, 0, 0, buf); f = hasflag(player->flags, F_HUNGER); if (f) { @@ -5260,7 +5467,9 @@ void drawstatus(void) { } if (strlen(buf2) > 0) { + setcol(statwin, C_BROWN); wprintw(statwin, " %s", buf2); + unsetcol(statwin, C_BROWN); } // construct waiting string @@ -5419,6 +5628,19 @@ void redraw(void) { wrefresh(gamewin); } +void setcol(WINDOW *win, enum COLOUR col) { + if (needsbold(col)) { + wattron(win, A_BOLD); + } + wattron(win, COLOR_PAIR(col)); +} +void unsetcol(WINDOW *win, enum COLOUR col) { + wattroff(win, COLOR_PAIR(col)); + if (needsbold(col)) { + wattroff(win, A_BOLD); + } +} + void showlfarmour(lifeform_t *lf) { enum BODYPART bp; object_t *o; @@ -5598,12 +5820,7 @@ void showlfstats(lifeform_t *lf, int showall) { } if (isplayer(lf)) { int attpoints; - f = lfhasflag(lf, F_STATGAINREADY); - if (f) { - attpoints = f->val[2]; - } else { - attpoints = 0; - } + attpoints = getattpoints(lf); mvwprintw(mainwin, y, 0, ftext, "Training"); if ((lf->skillpoints == 0) && (attpoints == 0)) { wprintw(mainwin, "n/a"); @@ -6122,8 +6339,13 @@ void showlfstats(lifeform_t *lf, int showall) { } f = lfhasknownflag(lf, F_SPRINTING); if (f) { - mvwprintw(mainwin, y, 0, "%s %s sprinting.", you(lf), isplayer(lf) ? "are" : "is"); - y++; + if (f->val[0]) { + mvwprintw(mainwin, y, 0, "%s %s sprinting.", you(lf), isplayer(lf) ? "are" : "is"); + y++; + } else { + mvwprintw(mainwin, y, 0, "%s %s exhausted.", you(lf), isplayer(lf) ? "are" : "is"); + y++; + } } @@ -6155,7 +6377,6 @@ void showlfstats(lifeform_t *lf, int showall) { strcat(expirebuf, ",after grab"); } - if (strlen(expirebuf)) { sprintf(eb2,"(%s)",expirebuf); } else { @@ -6351,6 +6572,61 @@ void showlfstats(lifeform_t *lf, int showall) { mvwprintw(mainwin, y, 0, "%s automatically detect nearby objects.", you(lf)); y++; } + + + // extra dam - can have it multiple times + for (f = lf->flags->first ; f; f = f->next) { + if (f->id == F_EXTRADAM) { + int ndice,nsides,bonus; + char dicebuf[BUFLEN]; + char mmbuf[BUFLEN]; + char damtypebuf[BUFLEN]; + int min = 0,max = 0; + texttodice(f->text, &ndice,&nsides,&bonus); + + if ((f->lifetime == FROMOBEQUIP) || + (f->lifetime == FROMOBHOLD) || + (f->lifetime == FROMOBACTIVATE) ) { + object_t *obfrom; + obfrom = findobbyid(lf->pack, f->obfrom); + if (obfrom) { + int bonusdam; + sumflags(obfrom->flags, F_BONUS, &bonusdam, NULL, NULL); + bonus += bonusdam; + } + } + + if (f->val[0] == NA) { + strcpy(damtypebuf, "damage"); + } else { + sprintf(damtypebuf, "%s damage", getdamname(f->val[0])); + } + + dicetotext(ndice, nsides, bonus, &min, &max, dicebuf, mmbuf); + if (strcmp(dicebuf, mmbuf)) { + mvwprintw(mainwin, y, 0, "%s deal%s %s (%s) extra %s each hit.", you(lf), + isplayer(lf) ? "" : "s", dicebuf, mmbuf, damtypebuf); + } else { + mvwprintw(mainwin, y, 0, "%s deal%s %s extra %s each hit.", you(lf), + isplayer(lf) ? "" : "s", dicebuf, damtypebuf); + } + y++; + + } + } + + f = lfhasknownflag(lf, F_EXTRALUCK); + if (f) { + mvwprintw(mainwin, y, 0, "Your luck is being boosted.", you(lf)); + y++; + } + + f = lfhasknownflag(lf, F_EXTRAMP); + if (f) { + mvwprintw(mainwin, y, 0, "Your mana pool is being boosted.", you(lf)); + y++; + } + f = lfhasknownflag(lf, F_EXTRAINFO); if (f && (f->known)) { mvwprintw(mainwin, y, 0, "%s receive enhanced knowledge about the world.", you(lf)); diff --git a/io.h b/io.h index ccac7aa..6d2d65a 100644 --- a/io.h +++ b/io.h @@ -4,9 +4,9 @@ void addchoice(prompt_t *p, char ch, char *text, char *desc, void *data); void addheading(prompt_t *p, char *text); 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 anim(cell_t *src, cell_t *dst, char ch, int colour); +void animradial(cell_t *src, int radius, char ch, int colour); +void animradialorth(cell_t *src, int radius, char ch, int colour); //void announceob(enum OBTYPE oid); int announceflaggain(lifeform_t *lf, flag_t *f); int announceflagloss(lifeform_t *lf, flag_t *f); @@ -62,6 +62,7 @@ void dovendingmachine(lifeform_t *lf, object_t *vm); int dowear(obpile_t *op); int doweild(obpile_t *op); int downline(int *y, int h, char *heading, char *subheading, char *bottomstring, char *cmdchars, char *retchar); +void drawglyph(glyph_t *g, int x, int y); void drawunviscell(cell_t *cell, int x, int y); void drawcellwithcontents(cell_t *cell, int x, int y); void drawcursor(void); @@ -84,10 +85,13 @@ void warn(char *format, ... ); void msg(char *format, ... ); void msgnocap(char *format, ... ); void msg_real(char *format, ... ); +int needsbold(enum COLOUR col); void nothinghappens(void); void dblog(char *format, ... ); void redraw(void); int savequit(void); +void setcol(WINDOW *win, enum COLOUR col); +void unsetcol(WINDOW *win, enum COLOUR col); void showlfarmour(lifeform_t *lf); void showlfstats(lifeform_t *lf, int showall); void tombstone(lifeform_t *lf); diff --git a/lf.c b/lf.c index 900157c..9e3c7b0 100644 --- a/lf.c +++ b/lf.c @@ -24,6 +24,9 @@ extern skill_t *firstskill, *lastskill; extern objecttype_t *objecttype; extern lifeform_t *player; +extern glyph_t playerglyph; +extern glyph_t tempglyph; + extern int needredraw; extern prompt_t prompt; @@ -165,7 +168,7 @@ 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 *addrace(enum RACE id, char *name, float weight, char glyph, int glyphcolour, enum MATERIAL mat) { race_t *a; assert(!findrace(id)); @@ -194,7 +197,8 @@ race_t *addrace(enum RACE id, char *name, float weight, char glyph, enum MATERIA assert(a->material); a->name = strdup(name); a->weight = weight; - a->glyph = glyph; + a->glyph.ch = glyph; + a->glyph.colour = glyphcolour; a->flags = addflagpile(NULL, NULL); return a; @@ -236,7 +240,7 @@ void adjustdamlf(lifeform_t *lf, int *amt, enum DAMTYPE damtype) { return; } - if ((damtype == DT_MAGIC) && skillcheck(lf, SC_RESISTMAG, (*amt * 2), 0)) { + if ((damtype == DT_MAGIC) && getmr(lf) && skillcheck(lf, SC_RESISTMAG, 10 + (*amt * 2), 0)) { *amt = 0; return; } @@ -305,6 +309,7 @@ lifeform_t *makezombie(object_t *o) { 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_DTIMMUNE, DT_NECROTIC, NA, NA, NULL); addflag(lf->flags, F_DTVULN, DT_HOLY, NA, NA, NULL); if (hasflag(o->flags, F_HEADLESS)) { @@ -389,7 +394,14 @@ int areenemies(lifeform_t *lf1, lifeform_t *lf2) { int areallies(lifeform_t *lf1, lifeform_t *lf2) { if (getallegiance(lf1) == getallegiance(lf2)) { - return B_TRUE; + if (isplayer(lf1) || isplayer(lf2)) { + // if one of them is the player + return B_TRUE; + } else { + if (lf1->race->baseid == lf2->race->baseid) { + return B_TRUE; + } + } } return B_FALSE; } @@ -410,7 +422,7 @@ void autoskill(lifeform_t *lf) { for (o = lf->pack->first ; o ; o = o->next) { if (isweapon(o) && canweild(lf, o)) { sk = getobskill(o); - if (sk) { + if (sk && !getskill(lf, sk->id)) { giveskilllev(lf, sk->id, slev); } nweps++; @@ -736,11 +748,37 @@ int candrink(lifeform_t *lf, object_t *o) { return B_TRUE; } -// TODO: reason = xx ? +// if false, returns why you can't eat it in 'reason' int caneat(lifeform_t *lf, object_t *o) { if (!isedible(o)) { + reason = E_WRONGOBTYPE; return B_FALSE; } + if ((o->type->id == OT_CORPSE) || (o->type->id == OT_HEAD)) { + flag_t *f; + f = hasflag(o->flags, F_CORPSEOF); + if (f) { + race_t *r; + r = findrace(f->val[0]); + // same race? + if ((r->id == lf->race->id) || (r->baseid == lf->race->baseid)) { + // race which doens't eat its own? + if (hasflag(lf->flags, F_ANIMAL) || (lf->race->id == R_HUMAN)) { + // no cannibulism! + reason = E_NOCANNIBUL; + return B_FALSE; + } + } + } + } + + // ai lifeforms won't eat tainted food + if (!isplayer(lf)) { + if (hasflag(o->flags, F_TAINTED)) { + reason = E_WONT; + return B_FALSE; + } + } return B_TRUE; } @@ -836,6 +874,10 @@ int canpickup(lifeform_t *lf, object_t *o, int amt) { reason = E_GRAVBOOSTED; return B_FALSE; } + if ((getlfmaterial(lf) == MT_GAS) || lfhasflag(lf, F_NONCORPOREAL)) { + reason = E_INSUBSTANTIAL; + return B_FALSE; + } // too heavy to lift? //max = getlfweight(lf, B_NOOBS) * 2; // twice your body weight @@ -860,7 +902,7 @@ int canpush(lifeform_t *lf, object_t *o, int dir) { cell_t *obcell, *dstcell; reason = E_OK; - if (getlfmaterial(lf) == MT_GAS) { + if ((getlfmaterial(lf) == MT_GAS) || lfhasflag(lf, F_NONCORPOREAL)) { reason = E_INSUBSTANTIAL; return B_FALSE; } @@ -945,7 +987,7 @@ int canwear(lifeform_t *lf, object_t *o, enum BODYPART where) { return B_FALSE; } // wearable at all? - if (!iswearable(o)) { + if (!iswearable(o) || !lfhasflag(lf, F_HUMANOID)) { reason = E_IMPOSSIBLE; return B_FALSE; } @@ -1010,19 +1052,65 @@ int canweild(lifeform_t *lf, object_t *o) { object_t *oo; flag_t *f; - if (!hasbp(lf, BP_WEAPON)) { + if (!hasbp(lf, BP_WEAPON) || !lfhasflag(lf, F_HUMANOID)) { reason = E_NOHANDS; return B_FALSE; } + if (o) { - if (hasflag(o->flags, F_TWOHANDED)) { - if (lfhasflagval(lf, F_NOBODYPART, BP_SECWEAPON, NA, NA, NULL)) { - reason = E_NOHANDS; - return B_FALSE; - } + for (f = o->flags->first ; f; f = f->next) { + if (f->id == F_ATTREQ) { + enum ATTRIB att; + int brackneeded; + int myatt; + int mybrack; + enum ERROR why; + att = f->val[0]; + brackneeded = f->val[1]; + + // modify for masterwork + if (hasflag(o->flags, F_MASTERWORK)) { + brackneeded--; + if (brackneeded < 0) brackneeded = 0; + } + + myatt = getattr(lf, att); + + switch (att) { + case A_DEX: + mybrack = getdexname(myatt, NULL); + why = E_LOWDEX; + break; + case A_CON: + mybrack = getconname(myatt, NULL); + why = E_LOWCON; + break; + case A_IQ: + mybrack = getiqname(myatt, NULL); + why = E_LOWIQ; + break; + case A_STR: + mybrack = getstrname(myatt, NULL); + why = E_LOWSTR; + break; + case A_NONE: + break; + } + if (mybrack < brackneeded) { + reason = why; + return B_FALSE; + } + } else if (f->id == F_TWOHANDED) { + if (lfhasflagval(lf, F_NOBODYPART, BP_SECWEAPON, NA, NA, NULL)) { + reason = E_NOHANDS; + return B_FALSE; + } + } + } } + reason = E_OK; // already weilding it? for (oo = lf->pack->first ; oo ; oo = oo->next) { @@ -1256,6 +1344,16 @@ void die(lifeform_t *lf) { } else if (lf->lastdamtype == DT_MELT) { // drop a pool of water addob(lf->cell->obpile, "large puddle of water"); + } else if (lf->lastdamtype == DT_NECROTIC) { + int n; + int numbones = 0; + char bonestring[BUFLEN]; + for (n = 0; n < getlfsize(lf); n++) { + numbones += rnd(1,10); + } + // drop bones + sprintf(bonestring, "%d bones",numbones); + addob(lf->cell->obpile, bonestring); } else { char corpseprefix[BUFLEN]; char corpsename[BUFLEN]; @@ -1270,6 +1368,9 @@ void die(lifeform_t *lf) { strcat(corpseprefix, "frozen "); break; default: + if (lfhasflag(lf, F_FROZEN)) { + strcat(corpseprefix, "frozen "); + } break; } if (lfhasflag(lf, F_BEHEADED)) { @@ -1293,6 +1394,11 @@ void die(lifeform_t *lf) { if ((lf->lastdamtype == DT_POISONGAS) || lfhasflag(lf, F_POISONOUS) || lfhasflag(lf, F_POISONED)) { addflag(corpse->flags, F_TAINTED, B_TRUE, NA, NA, NULL); } + + // set colour based on monster + if (corpse->type->id == OT_CORPSE) { + colourmatchob(corpse, lf); + } } @@ -1302,6 +1408,7 @@ void die(lifeform_t *lf) { // drop head too sprintf(headname, "%s head",lf->race->name); headob = addob(lf->cell->obpile, headname); + colourmatchob(headob, lf); } } @@ -1381,8 +1488,9 @@ void dumpxp(void) { } // dump + dblog("%-10s%-30s%s","XP", "Race", "Rarity"); for (i = 0; i < nposs; i++) { - dblog("%-10d%s",xpposs[i], raceposs[i]->name); + dblog("%-10d%-30s%d",xpposs[i], raceposs[i]->name,getracerarity(raceposs[i]->id)); } // free mem @@ -1423,7 +1531,15 @@ int eat(lifeform_t *lf, object_t *o) { } else { if (!caneat(lf, o)) { if (isplayer(lf)) { - msg("You can't eat that!"); + switch (reason) { + case E_NOCANNIBUL: + msg("The idea of eating your own race is abhorrent to you."); + break; + case E_WRONGOBTYPE: + default: + msg("You can't eat that!"); + break; + } } return B_TRUE; } @@ -1470,18 +1586,20 @@ int eat(lifeform_t *lf, object_t *o) { } if (isrotting(o)) { - char dambuf[BUFLEN]; - // lose hp - if (isplayer(lf)) { - msg("That %s was bad!", drinking ? "liquid" : "food"); + if (!isimmuneto(lf->flags, DT_POISON)) { + char dambuf[BUFLEN]; + // lose hp + if (isplayer(lf)) { + msg("That %s was bad!", drinking ? "liquid" : "food"); + } + // food poisoning for 20 turns + if (drinking) { + sprintf(dambuf, "%s",obname); + } else { + sprintf(dambuf, "a bad %s",noprefix(obname)); + } + addtempflag(lf->flags, F_POISONED, B_TRUE, NA, NA, obname, 20); } - // food poisoning for 20 turns - if (drinking) { - sprintf(dambuf, "%s",obname); - } else { - sprintf(dambuf, "a bad %s",noprefix(obname)); - } - addtempflag(lf->flags, F_POISONED, B_TRUE, NA, NA, obname, 20); } // change hunger @@ -1569,6 +1687,7 @@ void enhanceskills(lifeform_t *lf) { skill_t *sk; char ch = 'a'; int moretraining = B_FALSE; + int newskillcost = 1; // increase str/int etc if we can f = lfhasflag(lf, F_STATGAINREADY); @@ -1635,7 +1754,7 @@ void enhanceskills(lifeform_t *lf) { } - if (skillstolearn && (lf->skillpoints >= 2)) { + if (skillstolearn && (lf->skillpoints >= newskillcost)) { if (skillstoenhance) { eorl = askchar("Enhance your current skills or Learn a new one?","el","e", B_TRUE); } else { @@ -1657,7 +1776,8 @@ void enhanceskills(lifeform_t *lf) { // any skills to get? if (skillstoenhance) { char ques[BUFLEN]; - sprintf(ques, "Which skill will you enhance (%d points left)?", lf->skillpoints); + sprintf(ques, "Which skill will you enhance (%d point%s left)?", lf->skillpoints, + (lf->skillpoints == 1) ? "" : "s"); initprompt(&prompt, ques); ch = 'a'; @@ -1684,8 +1804,8 @@ void enhanceskills(lifeform_t *lf) { // learn a new skill // enough points? - if (player->skillpoints < 2) { - msg("You need at least 2 skill points to learn a new skill."); + if (player->skillpoints < newskillcost) { + msg("You need at least %d skill points to learn a new skill.", newskillcost); return; } @@ -1708,7 +1828,7 @@ void enhanceskills(lifeform_t *lf) { sk = (skill_t *)prompt.result; if (sk) { giveskill(player, sk->id); - player->skillpoints -= 2; + player->skillpoints -= newskillcost; } } else { msg("There is nothing more that you can learn."); @@ -1761,11 +1881,9 @@ void fightback(lifeform_t *lf, lifeform_t *attacker) { // any nearby monsters which will help out? if (getallegiance(lf) != AL_FRIENDLY) { for (l = lf->cell->map->lf ; l ; l = l->next) { - if (l->race->baseid == lf->race->baseid) { - if (!isdead(l) && areallies(l,lf)) { - if (cansee(l, attacker)) { - aiattack(l, attacker, AI_FOLLOWTIME); - } + if (!isdead(l) && areallies(l,lf)) { + if (cansee(l, attacker)) { + aiattack(l, attacker, AI_FOLLOWTIME); } } } @@ -1917,7 +2035,7 @@ int flee(lifeform_t *lf) { } // move away from them - if (!moveawayfrom(lf, fleefrom->cell)) { + if (!moveawayfrom(lf, fleefrom->cell, DT_ORTH)) { // announce if (isplayer(lf)) { char buf[BUFLEN]; @@ -2220,6 +2338,16 @@ int getattackspeed(lifeform_t *lf) { return (int)speed; } +int getattpoints(lifeform_t *lf) { + flag_t *f; + int attpoints = 0; + f = lfhasflag(lf, F_STATGAINREADY); + if (f) { + attpoints = f->val[2]; + } + return attpoints; +} + int getattr(lifeform_t *lf, enum ATTRIB attr) { int val = 0; flag_t *f; @@ -2711,18 +2839,21 @@ char *getseenlfconditionname(lifeform_t *lf, lifeform_t *viewer) { return getlfconditionname(cond); } -char getlfglyph(lifeform_t *lf) { +glyph_t *getlfglyph(lifeform_t *lf) { flag_t *f; + /* if (isplayer(lf) && !ispolymorphed(lf)) { - return '@'; + return &playerglyph; } + */ f = lfhasflag(lf, F_GLYPH); if (f) { - return f->text[0]; + tempglyph.ch = f->text[0]; + return &tempglyph; } - return lf->race->glyph; + return &lf->race->glyph; } enum MATERIAL getlfmaterial(lifeform_t *lf) { @@ -2805,13 +2936,25 @@ int getmaxmp(lifeform_t *lf) { flag_t *f; int activemp = 0; int maxmp; + int extrapct = 0; + + // base + maxmp = lf->maxmp; + + // extras + sumflags(lf->flags, F_EXTRAMP, &extrapct, NULL, NULL); + maxmp += pctof(maxmp, extrapct); + + // losses + activemp = 0; for (f = lf->flags->first ; f ; f = f->next) { if (f->id == F_BOOSTSPELL) { activemp += getmpcost(NULL, f->val[0]); } } - maxmp = lf->maxmp - activemp; + maxmp -= activemp; //if (maxmp < 0) maxmp = 0; // ???? + return maxmp; } @@ -2874,7 +3017,11 @@ int getmovespeed(lifeform_t *lf) { } else if (f->id == F_FASTMOVE) { speed -= f->val[0]; } else if (f->id == F_SPRINTING) { - speed -= 10; + if (f->val[0]) { + speed -= 10; + } else { + speed += 5; + } } else if (f->id == F_TIRED) { speed += 5; } @@ -3080,6 +3227,21 @@ char *getplayernamefull(char *buf) { } +int getracerarity(enum RACE rid) { + race_t *r; + int rarity = -1; + r = findrace(rid); + if (r) { + flag_t *f; + f = hasflag(r->flags, F_RARITY); + if (f) { + // ignore habitat for now! + rarity = f->val[1]; + } + } + return rarity; +} + object_t *getrandomarmour(lifeform_t *lf) { object_t *o; flag_t *f; @@ -3726,18 +3888,19 @@ void giveobflags(lifeform_t *lf, object_t *o, enum FLAG whattype) { int known = B_FALSE; int addit = B_FALSE; + if (isknown(o) || !isplayer(lf)) { + known = B_TRUE; + } + if (f->val[2] == IFKNOWN) { // only confer if known - if (isknown(o)) { + if (known) { addit = B_TRUE; } } else { addit = B_TRUE; } - if (isknown(o)) { - known = B_TRUE; - } if (addit) { newflag = addflag_real(lf->flags, f->val[0], f->val[1], f->val[2], NA, f->text, lifetimeval, known, o->id); @@ -3752,6 +3915,12 @@ void giveobflags(lifeform_t *lf, object_t *o, enum FLAG whattype) { // if all conferred flags now known, object is known if (flagsfound && (flagsknown == flagsfound)) { makeknown(o->type->id); + // in some cases, identify the object fully + if (isplayer(lf)) { + if (o->type->id == OT_RING_WOUNDING) { + identify(o); + } + } } } @@ -3806,17 +3975,34 @@ int giveskill(lifeform_t *lf, enum SKILL id) { } } } + } else if (id == SK_SS_ALLOMANCY) { + // give all allomantic spells + mayusespellschool(lf->flags, SS_ALLOMANCY, F_CANCAST); + } else if (id == SK_SS_MENTAL) { + // give a spell + if (!lfhasflagval(lf, F_CANCAST, OT_S_MINDSCAN, NA, NA, NULL)) { + addflag(lf->flags, F_CANCAST, OT_S_MINDSCAN, NA, NA, NULL); + } } return B_FALSE; } int giveskilllev(lifeform_t *lf, enum SKILL id, enum SKILLLEVEL slev) { flag_t *f; + if (id == SK_AXES) { + dblog("xxx"); + } f = lfhasflagval(lf, F_HASSKILL, id, NA, NA, NULL); + if (!f) { + // give one rank of the skill + giveskill(lf, id); + f = lfhasflagval(lf, F_HASSKILL, id, NA, NA, NULL); + } + if (f) { f->val[1] = slev; } else { - addflag(lf->flags, F_HASSKILL, id, slev, NA, NULL); + assert(1 == 0); } return B_FALSE; } @@ -4486,6 +4672,7 @@ void initjobs(void) { addflag(lastjob->flags, F_STARTSKILL, SK_SS_DEATH, PR_MASTER, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_SS_TRANSLOCATION, PR_MASTER, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_SS_DIVINATION, PR_MASTER, NA, NULL); + addflag(lastjob->flags, F_STARTSKILL, SK_SS_SUMMONING, PR_MASTER, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_RESEARCH, PR_NOVICE, NA, NULL); // gods may use all abilities and cast any spell at will for (i = SS_NONE+1; i < SS_LAST; i++) { @@ -4499,6 +4686,7 @@ void initjobs(void) { addflag(lastjob->flags, F_STARTATT, A_STR, ST_AVERAGE, NA, NULL); addflag(lastjob->flags, F_STARTATT, A_DEX, DX_AVERAGE, NA, NULL); addflag(lastjob->flags, F_STARTATT, A_IQ, IQ_AVERAGE, NA, NULL); + addflag(lastjob->flags, F_STARTATT, A_CON, CN_AVERAGE, NA, NULL); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "short sword"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "2 bananas"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "leather armour"); @@ -4521,8 +4709,43 @@ void initjobs(void) { addflag(lastjob->flags, F_STARTATT, A_DEX, DX_DEXTROUS, NA, NULL); addflag(lastjob->flags, F_STARTATT, A_IQ, IQ_AVERAGE, NA, NULL); addflag(lastjob->flags, F_DETECTMETAL, B_TRUE, NA, NA, NULL); - mayusespellschool(lastjob->flags, SS_ALLOMANCY, F_CANCAST); + addflag(lastjob->flags, F_STARTSKILL, SK_SS_ALLOMANCY, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_LOCKPICKING, PR_NOVICE, NA, NULL); + mayusespellschool(lastjob->flags, SS_ALLOMANCY, F_CANCAST); + // TODO skill: court knowledge ?? + // TODO skill: bartering 2 + addjob(J_BARBARIAN, "Barbarian"); + addflag(lastjob->flags, F_STARTATT, A_STR, ST_STRONG, NA, NULL); + addflag(lastjob->flags, F_STARTATT, A_DEX, DX_DEXTROUS, NA, NULL); + addflag(lastjob->flags, F_STARTATT, A_IQ, IQ_DOPEY, NA, NULL); + addflag(lastjob->flags, F_STARTATT, A_CON, CN_FIT, NA, NULL); + addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "hand axe"); + addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "buckler"); + addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "leather armour"); + addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "10 gold coins"); + addflag(lastjob->flags, F_STARTSKILL, SK_AXES, PR_BEGINNER, NA, NULL); + addflag(lastjob->flags, F_STARTSKILL, SK_CLUBS, PR_NOVICE, NA, NULL); + addflag(lastjob->flags, F_STARTSKILL, SK_SHORTBLADES, PR_NOVICE, NA, NULL); + addflag(lastjob->flags, F_STARTSKILL, SK_LONGBLADES, PR_NOVICE, NA, NULL); + addflag(lastjob->flags, F_STARTSKILL, SK_ATHLETICS, PR_NOVICE, NA, NULL); + addjob(J_COMMANDO, "Commando"); + addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "combat knife"); + addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "revolver"); + addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "helmet"); + addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "flak jacket"); + addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "combat pants"); + addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "leather boots"); + addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "nightvis goggles"); + addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "1-2 blocks of c4"); + addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "1-3 grenades"); + addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "1-3 flashbangs"); + addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "digital watch"); + addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "10 bullets"); + addflag(lastjob->flags, F_STARTATT, A_STR, ST_STRONG, NA, NULL); + addflag(lastjob->flags, F_STARTATT, A_IQ, IQ_DOPEY, NA, NULL); + addflag(lastjob->flags, F_STARTATT, A_DEX, DX_AVERAGE, NA, NULL); + addflag(lastjob->flags, F_STARTATT, A_CON, CN_HEALTHY, NA, NULL); + addflag(lastjob->flags, F_STARTSKILL, SK_ATHLETICS, PR_ADEPT, NA, NULL); addjob(J_PLUMBER, "Plumber"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "spanner"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "10 gold coins"); @@ -4542,25 +4765,6 @@ void initjobs(void) { addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "silk shirt"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "riding trousers"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "leather boots"); - // TODO skill: court knowledge ?? - // TODO skill: bartering 2 - addjob(J_COMMANDO, "Commando"); - addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "combat knife"); - addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "revolver"); - addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "helmet"); - addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "flak jacket"); - addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "combat pants"); - addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "leather boots"); - addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "nightvis goggles"); - addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "1-2 blocks of c4"); - addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "1-3 grenades"); - addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "1-3 flashbangs"); - addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "digital watch"); - addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "10 bullets"); - addflag(lastjob->flags, F_STARTATT, A_STR, ST_STRONG, NA, NULL); - addflag(lastjob->flags, F_STARTATT, A_IQ, IQ_DOPEY, NA, NULL); - addflag(lastjob->flags, F_STARTSKILL, SK_ATHLETICS, PR_ADEPT, NA, NULL); - // TODO skill: athletics 2 addjob(J_WIZARD, "Wizard"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "knife"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "robe"); @@ -4614,7 +4818,7 @@ void initjobs(void) { void initrace(void) { // races / monsters - addrace(R_HUMAN, "human", 75, '@', MT_FLESH); + addrace(R_HUMAN, "human", 75, '@', C_GREY, MT_FLESH); 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, 2, 2, NA, NULL); @@ -4633,10 +4837,11 @@ void initrace(void) { // TODO: humans start with a random job sometimes? addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, NA, NA, "shouts^a shout"); // addflag(lastrace->flags, F_RESTHEALMPAMT, 1, NA, NA, NULL); + addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); // monsters - addrace(R_BEHOLDER, "beholder", 5, 'e', MT_FLESH); + addrace(R_BEHOLDER, "beholder", 5, 'e', C_GREY, MT_FLESH); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_GENIUS, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); @@ -4664,7 +4869,7 @@ void initrace(void) { addflag(lastrace->flags, F_HASSKILL, SK_SPELLCASTING, PR_EXPERT, NA, NULL); addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL); - addrace(R_BUGBEAR, "bugbear", 120, 'G', MT_FLESH); + addrace(R_BUGBEAR, "bugbear", 120, 'G', C_BROWN, MT_FLESH); 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); @@ -4681,8 +4886,9 @@ void initrace(void) { addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, NA, NA, "roars^a roars"); addflag(lastrace->flags, F_SEEINDARK, 3, NA, NA, NULL); addflag(lastrace->flags, F_CANWILL, OT_A_HEAVYBLOW, 2, 2, NULL); + addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addrace(R_COCKATRICE, "cockatrice", 5, 'c', MT_FLESH); + addrace(R_COCKATRICE, "cockatrice", 5, 'c', C_YELLOW, MT_FLESH); addflag(lastrace->flags, F_STARTATT, A_DEX, DX_SWIFT, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); addflag(lastrace->flags, F_COLDBLOOD, B_TRUE, NA, NA, NULL); @@ -4702,7 +4908,7 @@ void initrace(void) { addflag(lastrace->flags, F_HASATTACK, 1, 6, 3, "teeth"); // special attack handled in attack.c - addrace(R_DARKMANTLE, "darkmantle", 70, 'Q', MT_FLESH); + addrace(R_DARKMANTLE, "darkmantle", 70, 'Q', C_BLUE, MT_FLESH); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, ST_MIGHTY, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_DEX, DX_SUPERSONIC, NA, NULL); @@ -4732,7 +4938,7 @@ void initrace(void) { addflag(lastrace->flags, F_DTVULN, DT_LIGHT, NA, NA, "0d6+5"); addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL); - addrace(R_EYEBAT, "eyebat", 5, 'e', MT_FLESH); + addrace(R_EYEBAT, "eyebat", 5, 'e', C_BLUE, MT_FLESH); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_SMART, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 65, NA, NULL); @@ -4759,7 +4965,7 @@ void initrace(void) { addflag(lastrace->flags, F_HASSKILL, SK_SPELLCASTING, PR_EXPERT, NA, NULL); addflag(lastrace->flags, F_NOISETEXT, N_FLY, NA, NA, "^flapping wings"); - addrace(R_GIANTHILL, "hill giant", 160, 'H', MT_FLESH); + addrace(R_GIANTHILL, "hill giant", 160, 'H', C_BROWN, 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); @@ -4785,8 +4991,9 @@ void initrace(void) { addflag(lastrace->flags, F_WANTS, OT_BOULDER, NA, NA, NULL); addflag(lastrace->flags, F_CANWILL, OT_A_HEAVYBLOW, NA, NA, NULL); addflag(lastrace->flags, F_FLEEONHPPCT, 50, NA, NA, NULL); + addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addrace(R_GIANTFIRE, "fire giant", 160, 'H', MT_FLESH); + addrace(R_GIANTFIRE, "fire giant", 160, 'H', C_RED, 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); @@ -4814,8 +5021,9 @@ void initrace(void) { addflag(lastrace->flags, F_STARTATT, A_DEX, DX_AVERAGE, 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_HUMANOID, B_TRUE, NA, NA, NULL); - addrace(R_GIANTFIREFC, "fire giant forgecaller", 160, 'H', MT_FLESH); + addrace(R_GIANTFIREFC, "fire giant forgecaller", 160, 'H', C_RED, 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); @@ -4848,8 +5056,9 @@ void initrace(void) { addflag(lastrace->flags, F_CANCAST, OT_S_FLAMEPILLAR, NA, NA, NULL); addflag(lastrace->flags, F_CANWILL, OT_S_FLAMEBURST, 4, 4, "pw:4;"); addflag(lastrace->flags, F_HASSKILL, SK_SPELLCASTING, PR_ADEPT, NA, NULL); + addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addrace(R_GIANTFIRETITAN, "fire titan", 160, 'H', MT_FLESH); + addrace(R_GIANTFIRETITAN, "fire titan", 160, 'H', C_RED, 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); @@ -4866,7 +5075,7 @@ void initrace(void) { 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_STARTATT, A_STR, ST_MIGHTY, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_STR, ST_TITANIC, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_AVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_DEX, DX_SWIFT, NA, NULL); addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, NA, NA, "bellows^a bellow"); @@ -4875,11 +5084,12 @@ void initrace(void) { addflag(lastrace->flags, F_HEAVYBLOW, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_CANWILL, OT_S_BURNINGWAVE, 3, 3, "pw:6;"); addflag(lastrace->flags, F_DTRESIST, DT_FIRE, NA, NA, NULL); + addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); // TODO: storm giant // TODO: storm titan - addrace(R_GNOLL, "gnoll", 130, 'h', MT_FLESH); + addrace(R_GNOLL, "gnoll", 130, 'h', C_BROWN, 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, ""); @@ -4900,8 +5110,9 @@ void initrace(void) { 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"); + addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addrace(R_GNOLLHM, "gnoll huntmaster", 130, 'h', MT_FLESH); + addrace(R_GNOLLHM, "gnoll huntmaster", 130, 'h', C_BROWN, 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); @@ -4924,8 +5135,9 @@ void initrace(void) { 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"); + addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addrace(R_GNOLLMR, "gnoll marauder", 130, 'h', MT_FLESH); + addrace(R_GNOLLMR, "gnoll marauder", 130, 'h', C_BROWN, 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); @@ -4947,8 +5159,9 @@ void initrace(void) { 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"); + addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addrace(R_GOBLIN, "goblin", 20, 'g', MT_FLESH); + addrace(R_GOBLIN, "goblin", 20, 'g', C_BROWN, MT_FLESH); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 85, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL); @@ -4960,6 +5173,7 @@ void initrace(void) { addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_DOPEY, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, ST_AVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_DEX, DX_DEXTROUS, NA, NULL); + addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "1-25 gold coins"); 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); @@ -4969,9 +5183,10 @@ void initrace(void) { //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"); + addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addrace(R_GOBLINWAR, "goblin warrior", 30, 'g', MT_FLESH); + addrace(R_GOBLINWAR, "goblin warrior", 30, 'g', C_BROWN, 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); @@ -4988,12 +5203,14 @@ void initrace(void) { 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_STARTOB, 50, NA, NA, "1-50 gold coins"); 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"); + addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addrace(R_GOBLINSHOOTER, "goblin sharpshooter", 20, 'g', MT_FLESH); + addrace(R_GOBLINSHOOTER, "goblin sharpshooter", 20, 'g', C_BROWN, 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); @@ -5011,14 +5228,16 @@ void initrace(void) { 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_STARTOB, 50, NA, NA, "1-25 gold coins"); 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) + addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addrace(R_GOBLINHEXER, "goblin hexer", 20, 'g', MT_FLESH); + addrace(R_GOBLINHEXER, "goblin hexer", 20, 'g', C_BROWN, 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); @@ -5043,8 +5262,9 @@ void initrace(void) { addflag(lastrace->flags, F_CANCAST, OT_S_BLINDNESS, NA, NA, NULL); addflag(lastrace->flags, F_CANCAST, OT_S_PAIN, NA, NA, NULL); addflag(lastrace->flags, F_HASSKILL, SK_SPELLCASTING, PR_ADEPT, NA, NULL); + addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addrace(R_HOBGOBLIN, "hobgoblin", 90, 'g', MT_FLESH); + addrace(R_HOBGOBLIN, "hobgoblin", 90, 'g', C_GREEN, MT_FLESH); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); addflag(lastrace->flags, F_NUMAPPEAR, 1, 2, NA, NULL); @@ -5061,6 +5281,7 @@ void initrace(void) { 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_STARTOB, 50, NA, NA, "1-50 gold coins"); 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); @@ -5068,8 +5289,9 @@ void initrace(void) { 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"); + addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addrace(R_HOBGOBLINWAR, "hobgoblin warrior", 90, 'g', MT_FLESH); + addrace(R_HOBGOBLINWAR, "hobgoblin warrior", 90, 'g', C_GREEN, 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); @@ -5085,6 +5307,7 @@ void initrace(void) { addflag(lastrace->flags, F_STARTATT, A_STR, ST_MIGHTY, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_DEX, DX_DEXTROUS, NA, NULL); addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "flail"); + addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "1-75 gold coins"); 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); @@ -5095,11 +5318,12 @@ void initrace(void) { 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); + addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); // TODO: hobgoblin archer // TODO: hobgoblin warcaster - addrace(R_KOBOLD, "kobold", 18, 'k', MT_FLESH); + addrace(R_KOBOLD, "kobold", 18, 'k', C_BROWN, 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_POISONOUS, B_TRUE, NA, NA, NULL); @@ -5119,16 +5343,18 @@ void initrace(void) { 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_STARTOB, 50, NA, NA, "1-10 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_HUMANOID, B_TRUE, NA, NA, NULL); - addrace(R_TROGLODYTE, "troglodyte", 20, 'z', MT_FLESH); + addrace(R_TROGLODYTE, "troglodyte", 20, 'z', C_GREY, MT_FLESH); addflag(lastrace->flags, F_COLDBLOOD, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_POISONOUS, 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_RARITY, H_DUNGEON, 85, 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); @@ -5141,18 +5367,19 @@ void initrace(void) { 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_STARTOB, 50, NA, NA, "1-10 gold coins"); 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, 3, 3, NA, NULL); + addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addrace(R_LIZARDMAN, "lizardman", 100, 'z', MT_FLESH); + addrace(R_LIZARDMAN, "lizardman", 100, 'z', C_GREEN, 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, 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_STARTATT, A_STR, ST_MIGHTY, NA, NULL); @@ -5160,12 +5387,17 @@ void initrace(void) { addflag(lastrace->flags, F_STARTATT, A_DEX, DX_DEXTROUS, 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, "1-50 gold coins"); addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "spear"); + addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "1-2 javelins"); 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_HUMANOID, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_SPELLCASTTEXT, NA, NA, NA, "spits"); + addflag(lastrace->flags, F_CANWILL, OT_S_POISONBOLT, 5, 5, "pw:5;"); - addrace(R_LURKINGHORROR, "lurking horror", 100, 'U', MT_FLESH); + addrace(R_LURKINGHORROR, "lurking horror", 100, 'U', C_MAGENTA, MT_FLESH); addflag(lastrace->flags, F_NOCORPSE, 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); @@ -5189,7 +5421,7 @@ void initrace(void) { addflag(lastrace->flags, F_INDUCEFEAR, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL); - addrace(R_OGRE, "ogre", 160, 'O', MT_FLESH); + addrace(R_OGRE, "ogre", 160, 'O', C_BROWN, 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, 65, NA, NULL); @@ -5210,8 +5442,10 @@ void initrace(void) { 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"); + addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "1-70 gold coins"); + addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addrace(R_OGRESAVAGE, "ogre savage", 160, 'O', MT_FLESH); + addrace(R_OGRESAVAGE, "ogre savage", 160, 'O', C_BROWN, 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); @@ -5233,8 +5467,10 @@ void initrace(void) { 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"); + addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "1-70 gold coins"); + addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addrace(R_OGREWARHULK, "ogre warhulk", 160, 'O', MT_FLESH); + addrace(R_OGREWARHULK, "ogre warhulk", 160, 'O', C_BROWN, 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); @@ -5256,9 +5492,11 @@ void initrace(void) { 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_STARTOB, 50, NA, NA, "1-100 gold coins"); addflag(lastrace->flags, F_HEAVYBLOW, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addrace(R_ORC, "orc", 90, 'o', MT_FLESH); + addrace(R_ORC, "orc", 90, 'o', C_BROWN, MT_FLESH); 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); @@ -5284,8 +5522,9 @@ void initrace(void) { 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, 5, 5, NULL); + addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addrace(R_ORCWARRIOR, "orc warrior", 90, 'o', MT_FLESH); + addrace(R_ORCWARRIOR, "orc warrior", 90, 'o', C_BROWN, 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); @@ -5313,8 +5552,9 @@ void initrace(void) { 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); + addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addrace(R_ORK, "ork", 90, 'o', MT_FLESH); + addrace(R_ORK, "ork", 90, 'o', C_BROWN, 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); @@ -5339,8 +5579,9 @@ void initrace(void) { addflag(lastrace->flags, F_WANTSBETTERWEP, B_TRUE, 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_HUMANOID, B_TRUE, NA, NA, NULL); - addrace(R_POLTERGEIST, "poltergeist", 50, 'p', MT_FLESH); + addrace(R_POLTERGEIST, "poltergeist", 50, 'p', C_GREEN, MT_FLESH); addflag(lastrace->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_AVERAGE, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -5364,9 +5605,9 @@ void initrace(void) { addflag(lastrace->flags, F_NOPACK, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SEEINDARK, UNLIMITED, NA, NA, NULL); addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL); - addflag(lastrace->flags, F_HASSKILL, SK_SPELLCASTING, PR_EXPERT, NA, NULL); + addflag(lastrace->flags, F_HASSKILL, SK_SS_MENTAL, PR_EXPERT, NA, NULL); - addrace(R_SHADOWCAT, "shadowcat", 5, 'f', MT_FLESH); + addrace(R_SHADOWCAT, "shadowcat", 5, 'f', C_BLUE, MT_FLESH); 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); @@ -5380,7 +5621,7 @@ 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_OOZEGREY, "grey ooze", 10, 'j', MT_SLIME); + addrace(R_OOZEGREY, "grey ooze", 10, 'j', C_GREY, 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); @@ -5400,6 +5641,7 @@ void initrace(void) { 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_NOPACK, B_TRUE, NA, NA, NULL); 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); @@ -5407,8 +5649,9 @@ void initrace(void) { addflag(lastrace->flags, F_DTIMMUNE, DT_ACID, B_TRUE, NA, NULL); addflag(lastrace->flags, F_AUTOCREATEOB, 0, NA, NA, "puddle of acid"); - addrace(R_SPRITEFIRE, "fire sprite", 5, 'n', MT_FIRE); + addrace(R_SPRITEFIRE, "fire sprite", 5, 'n', C_RED, MT_FIRE); addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "small fire"); + addflag(lastrace->flags, F_STARTATT, A_STR, ST_VWEAK, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_AVERAGE, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); @@ -5428,9 +5671,10 @@ void initrace(void) { addflag(lastrace->flags, F_NOISETEXT, N_WALK, NA, NA, "^crackling flames."); addflag(lastrace->flags, F_HASSKILL, SK_SPELLCASTING, PR_NOVICE, NA, NULL); addflag(lastrace->flags, F_HASSKILL, SK_SS_FIRE, PR_BEGINNER, NA, NULL); + addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addrace(R_TROLL, "troll", 100, 't', MT_FLESH); + addrace(R_TROLL, "troll", 100, 't', C_GREEN, 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, 65, NA, NULL); @@ -5443,9 +5687,10 @@ void initrace(void) { addflag(lastrace->flags, F_HASATTACK, 1, 6, 0, "claws"); addflag(lastrace->flags, F_REGENERATES, 2, NA, NA, NULL); addflag(lastrace->flags, F_SEEINDARK, 5, NA, NA, NULL); + addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addrace(R_XAT, "xat", 2, 'x', MT_FLESH); + addrace(R_XAT, "xat", 2, 'x', C_BROWN, MT_FLESH); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_TINY, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 90, NA, NULL); @@ -5454,12 +5699,15 @@ void initrace(void) { addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_DIMWITTED, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, ST_WEAK, 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_HANDS, NA, NA, NULL); addflag(lastrace->flags, F_HASATTACK, 1, 3, 0, "teeth"); // end monsters // animals - addrace(R_BAT, "giant bat", 3, 'B', MT_FLESH); + addrace(R_BAT, "giant bat", 3, 'B', C_BROWN, MT_FLESH); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 90, NA, ""); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_ANIMAL, B_TRUE, NA, NA, NULL); @@ -5481,7 +5729,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SEEINDARK, UNLIMITED, NA, NA, NULL); addflag(lastrace->flags, F_NOISETEXT, N_FLY, NA, NA, "^flapping wings"); - addrace(R_ANT, "giant worker ant", 4, 'a', MT_FLESH); + addrace(R_ANT, "giant worker ant", 4, 'a', C_BROWN, MT_FLESH); lastrace->baseid = R_ANT; addflag(lastrace->flags, F_RARITY, H_DUNGEON, 85, NA, NULL); addflag(lastrace->flags, F_ANIMAL, B_TRUE, NA, NA, NULL); @@ -5501,7 +5749,7 @@ void initrace(void) { addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, NA, NA, NULL); addflag(lastrace->flags, F_HASATTACK, 0, 1, 4, "teeth"); addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL); - addrace(R_ANTS, "giant soldier ant", 5, 'a', MT_FLESH); + addrace(R_ANTS, "giant soldier ant", 5, 'a', C_BROWN, MT_FLESH); lastrace->baseid = R_ANT; addflag(lastrace->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); addflag(lastrace->flags, F_ANIMAL, B_TRUE, NA, NA, NULL); @@ -5522,19 +5770,17 @@ void initrace(void) { addflag(lastrace->flags, F_CANWILL, OT_A_GRAB, NA, NA, "dam:1d8+3;"); addflag(lastrace->flags, F_CANWILL, OT_A_STINGACID, NA, NA, "dam:1d6+3;needgrab:1;"); addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL); -/* - addrace(R_HAWK, "blood hawk", 1, 'A', MT_FLESH); // 'A' for Avian + addrace(R_HAWKBLOOD, "blood hawk", 1, 'A', C_RED, MT_FLESH); // 'A' for Avian addflag(lastrace->flags, F_RARITY, H_DUNGEON, 80, NA, ""); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_ANIMAL, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); - addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL); + addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_FLYING, B_TRUE, NA, NA, ""); addflag(lastrace->flags, F_HITDICE, 3, 4, NA, ""); addflag(lastrace->flags, F_HASATTACK, 1, 6, 5, "claws"); -oooooooo addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_WEAPON, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_SECWEAPON, NA, NA, NULL); @@ -5542,10 +5788,32 @@ oooooooo 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); - FLYBY ability -ooooooooo -*/ - addrace(R_NEWT, "giant newt", 4, ':', MT_FLESH); + addflag(lastrace->flags, F_CANWILL, OT_A_SWOOP, 3, 3, NULL); + addflag(lastrace->flags, F_SWOOPRANGE, 5, NA, NA, NULL); + addrace(R_HAWKFROST, "frost hawk", 1, 'A', C_CYAN, MT_FLESH); // 'A' for Avian + addflag(lastrace->flags, F_RARITY, H_DUNGEON, 75, NA, ""); + addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_ANIMAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); + addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); + addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, ""); + addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); + addflag(lastrace->flags, F_FLYING, B_TRUE, NA, NA, ""); + addflag(lastrace->flags, F_HITDICE, 10, NA, NA, ""); + addflag(lastrace->flags, F_HASATTACK, 1, 6, 5, "claws"); + addflag(lastrace->flags, F_EXTRADAM, DT_COLD, NA, NA, "1d6"); + addflag(lastrace->flags, F_EVASION, 10, 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_CANWILL, OT_A_SWOOP, 3, 3, NULL); + addflag(lastrace->flags, F_SWOOPRANGE, 8, NA, NA, NULL); + addflag(lastrace->flags, F_CANWILL, OT_S_COLDBURST, 2, 2, "pw:2;"); + addflag(lastrace->flags, F_SPELLCASTTEXT, NA, NA, NA, "screeches"); + addrace(R_NEWT, "giant newt", 4, ':', C_BROWN, MT_FLESH); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 100, NA, NULL); addflag(lastrace->flags, F_COLDBLOOD, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -5562,7 +5830,7 @@ ooooooooo addflag(lastrace->flags, F_NOPACK, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_DTRESIST, DT_FIRE, B_TRUE, NA, NULL); - addrace(R_RAT, "giant rat", 3, 'r', MT_FLESH); + addrace(R_RAT, "giant rat", 3, 'r', C_BROWN, MT_FLESH); addflag(lastrace->flags, F_ANIMAL, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, ST_VWEAK, NA, NULL); @@ -5584,7 +5852,7 @@ ooooooooo addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, B_COVETS, NA, NULL); addflag(lastrace->flags, F_SEEINDARK, 4, NA, NA, NULL); addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL); - addrace(R_SNAKE, "brown snake", 3, 's', MT_FLESH); + addrace(R_SNAKE, "brown snake", 3, 's', C_BROWN, MT_FLESH); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 85, NA, ""); addflag(lastrace->flags, F_ANIMAL, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_COLDBLOOD, B_TRUE, NA, NA, NULL); @@ -5606,7 +5874,7 @@ ooooooooo addflag(lastrace->flags, F_SEEINDARK, 4, NA, NA, NULL); addflag(lastrace->flags, F_DTVULN, DT_COLD, NA, NA, NULL); addflag(lastrace->flags, F_NOISETEXT, N_FLY, NA, NA, "^hissing"); - addrace(R_WOLF, "wolf", 10, 'd', MT_FLESH); + addrace(R_WOLF, "wolf", 10, 'd', C_BROWN, MT_FLESH); addflag(lastrace->flags, F_ANIMAL, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_FAST, NA, NA, ""); @@ -5628,7 +5896,7 @@ ooooooooo addflag(lastrace->flags, F_CANWILL, OT_A_SPRINT, 5, 5, NULL); // insects - addrace(R_BUTTERFLY, "butterfly", 0.01, 'i', MT_FLESH); + addrace(R_BUTTERFLY, "butterfly", 0.01, 'i', C_GREEN, MT_FLESH); addflag(lastrace->flags, F_INSECT, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_VERYFAST, NA, NA, ""); @@ -5646,7 +5914,7 @@ ooooooooo addflag(lastrace->flags, F_SILENTMOVE, 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); + addrace(R_GIANTFLY, "giant fly", 1, 'i', C_GREY, MT_FLESH); lastrace->baseid = R_GIANTFLY; addflag(lastrace->flags, F_INSECT, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); @@ -5668,7 +5936,7 @@ ooooooooo addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, NA, NA, "buzzes angrily^an angry buzzing"); addflag(lastrace->flags, F_NOISETEXT, N_FLY, NA, NA, "^buzzing"); addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL); - addrace(R_GIANTBLOWFLY, "giant blowfly", 2, 'i', MT_FLESH); + addrace(R_GIANTBLOWFLY, "giant blowfly", 2, 'i', C_WHITE, MT_FLESH); lastrace->baseid = R_GIANTFLY; addflag(lastrace->flags, F_INSECT, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); @@ -5693,7 +5961,7 @@ ooooooooo addflag(lastrace->flags, F_NOISETEXT, N_FLY, NA, NA, "^buzzing"); addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL); - addrace(R_GLOWBUG, "glowbug", 1, 'i', MT_FLESH); + addrace(R_GLOWBUG, "glowbug", 1, 'i', C_WHITE, MT_FLESH); addflag(lastrace->flags, F_INSECT, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_VERYFAST, NA, NA, ""); @@ -5715,7 +5983,7 @@ ooooooooo addflag(lastrace->flags, F_NOISETEXT, N_FLY, NA, NA, "^buzzing"); // undead - addrace(R_ZOMBIE, "zombie", 50, 'Z', MT_FLESH); + addrace(R_ZOMBIE, "zombie", 50, 'Z', C_BLUE, MT_FLESH); addflag(lastrace->flags, F_UNDEAD, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_MINDLESS, NA, NULL); addflag(lastrace->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL); @@ -5735,9 +6003,11 @@ ooooooooo 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); + addflag(lastrace->flags, F_DTIMMUNE, DT_NECROTIC, NA, NA, NULL); addflag(lastrace->flags, F_DTVULN, DT_HOLY, NA, NA, NULL); addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL); - addrace(R_SKELETON, "skeleton", 20, 'Z', MT_BONE); + + addrace(R_SKELETON, "skeleton", 20, 'Z', C_GREY, MT_BONE); addflag(lastrace->flags, F_UNDEAD, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_MINDLESS, NA, NULL); addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "5-20 bones"); @@ -5754,12 +6024,14 @@ ooooooooo 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); + addflag(lastrace->flags, F_DTIMMUNE, DT_NECROTIC, NA, NA, NULL); addflag(lastrace->flags, F_DTRESIST, DT_SLASH, NA, NA, NULL); addflag(lastrace->flags, F_DTVULN, DT_BASH, NA, NA, NULL); addflag(lastrace->flags, F_DTVULN, DT_HOLY, NA, NA, NULL); + addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addrace(R_GHAST, "ghast", 50, 'Z', MT_FLESH); + addrace(R_GHAST, "ghast", 50, 'Z', C_MAGENTA, MT_FLESH); addflag(lastrace->flags, F_UNDEAD, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_SMART, NA, NULL); addflag(lastrace->flags, F_BLOODOB, NA, NA, NA, NULL); @@ -5775,11 +6047,12 @@ ooooooooo 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); + addflag(lastrace->flags, F_DTIMMUNE, DT_NECROTIC, NA, NA, NULL); addflag(lastrace->flags, F_DTVULN, DT_HOLY, NA, NA, NULL); addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, NA, NA, NULL); addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL); - addrace(R_GHOUL, "ghoul", 50, 'Z', MT_FLESH); + addrace(R_GHOUL, "ghoul", 50, 'Z', C_BLUE, MT_FLESH); addflag(lastrace->flags, F_UNDEAD, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_MINDLESS, NA, NULL); addflag(lastrace->flags, F_BLOODOB, NA, NA, NA, NULL); @@ -5796,12 +6069,13 @@ ooooooooo 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); + addflag(lastrace->flags, F_DTIMMUNE, DT_NECROTIC, NA, NA, NULL); addflag(lastrace->flags, F_DTVULN, DT_HOLY, NA, NA, NULL); addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, B_COVETS, NA, NULL); addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL); // special monsters - addrace(R_GASCLOUD, "cloud of gas", 0.1, '}', MT_GAS); + addrace(R_GASCLOUD, "cloud of gas", 0.1, '}', C_GREY, MT_GAS); addflag(lastrace->flags, F_MOVESPEED, SP_ULTRAFAST, NA, NA, ""); addflag(lastrace->flags, F_BLOODOB, NA, NA, NA, NULL); addflag(lastrace->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL); @@ -5826,7 +6100,7 @@ ooooooooo addflag(lastrace->flags, F_DTIMMUNE, DT_ALL, NA, NA, NULL); addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL); - addrace(R_DANCINGWEAPON, "dancing weapon", 0, ')', MT_METAL); + addrace(R_DANCINGWEAPON, "dancing weapon", 0, ')', C_GREY, MT_METAL); addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL); addflag(lastrace->flags, F_FLYING, B_TRUE, NA, NA, ""); addflag(lastrace->flags, F_HITDICE, 2, NA, NA, ""); @@ -6085,6 +6359,10 @@ flag_t *isresistantto(flagpile_t *fp, enum DAMTYPE dt) { if (f) return f; f = hasflagval(fp, F_DTRESIST, DT_ALL, NA, NA, NULL); if (f) return f; + if (dt == DT_FIRE) { + f = hasflag(fp, F_WET); + if (f) return f; + } return NULL; } @@ -6175,8 +6453,10 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml interrupt(lf); // occasionally drop blood - if (rnd(1,3) == 1) { - bleed(lf); + if ((damtype != DT_POISON) && (damtype != DT_POISONGAS)) { + if (rnd(1,3) == 1) { + bleed(lf); + } } if (hasflag(lf->flags, F_DEBUG)) { @@ -6345,7 +6625,9 @@ void mayusespellschool(flagpile_t *fp, enum SPELLSCHOOL ss, enum FLAG how) { for (ot = objecttype ; ot ; ot = ot->next) { //if (ot->obclass->id == OC_SPELL) { if (hasflagval(ot->flags, F_SPELLSCHOOL, ss, NA, NA, NULL)) { - addflag(fp, how, ot->id, NA, NA, NULL); + if (!hasflagval(fp, how, ot->id, NA, NA, NULL)) { + addflag(fp, how, ot->id, NA, NA, NULL); + } } //} } @@ -6468,7 +6750,10 @@ void modhunger(lifeform_t *lf, int amt) { needfeeling ? "feeling " : "", buf, (needexclam) ? '!' : '.'); - stopresting(lf); + + if ((posthlev >= H_PECKISH) && (amt > 0)) { + stopresting(lf); + } } } } @@ -6572,6 +6857,9 @@ int pickup(lifeform_t *lf, object_t *what, int howmany, int fromground) { // tell the player why! if (lf->controller == C_PLAYER) { switch (reason) { + case E_INSUBSTANTIAL: + msg("Your hand passes straight through %s.",obname); + break; case E_NOSPACE: msg("Your pack is too full to fit any more objects."); break; @@ -6662,7 +6950,25 @@ int pickup(lifeform_t *lf, object_t *what, int howmany, int fromground) { return B_FALSE; } +void practice(lifeform_t *lf, enum SKILL skid) { + flag_t *f; + // already got the skill? + if (getskill(lf, skid)) { + return; + } + // practice a little bit... + f = lfhasflagval(lf, F_PRACTICINGSKILL, skid, NA, NA, NULL); + if (f) { + f->val[1]++; + if (f->val[1] >= PRACTICETIME) { + // learnt it! + giveskill(lf, skid); + } + } else { + addflag(lf->flags, F_PRACTICINGSKILL, skid, 1, NA, NULL); + } +} void precalclos(lifeform_t *lf) { int x,y; @@ -7398,6 +7704,7 @@ int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *r int othermod = 0; int db = B_FALSE; int roll; + int luckmod = 0; char mbuf[BUFLEN]; if (lfhasflag(lf, F_DEBUG)) { @@ -7481,6 +7788,11 @@ int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *r levmod *= 2; } + + // luck + sumflags(lf->flags, F_EXTRALUCK, &luckmod, NULL, NULL); + othermod += luckmod; + roll = rolldie(1, 20); if (db) { sprintf(mbuf, "%s skillcheck - need %d, got %d(rll)+%d(attr)+%d(lvm)+%d(othmod)+%d(mod)=",lf->race->name, diff, roll, attrib,levmod, othermod,mod); @@ -7490,7 +7802,7 @@ int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *r roll += levmod; roll += othermod; if (db) { - msg("%s%d.",mbuf,roll); + //msg("%s%d.",mbuf,roll); } if (result) { @@ -7531,6 +7843,7 @@ int skillcheckvs(lifeform_t *lf1, enum CHECKTYPE ct1, int mod1, lifeform_t *lf2, int slipon(lifeform_t *lf, object_t *o) { char obname[BUFLEN]; char lfname[BUFLEN]; + flag_t *f; getlfname(lf,lfname); getobname(o, obname, 1); // slip! @@ -7554,7 +7867,10 @@ int slipon(lifeform_t *lf, object_t *o) { } } // stop sprinting - killflagsofid(lf->flags, F_SPRINTING); + f = lfhasflag(lf, F_SPRINTING); + if (f && f->val[0]) { + killflag(f); + } // boost spells end stopallspells(lf); return B_FALSE; @@ -7824,6 +8140,11 @@ void taketime(lifeform_t *lf, long howlong) { } int throwat(lifeform_t *thrower, object_t *o, cell_t *where) { + + if (!hasbp(thrower, BP_HANDS)) { + if (isplayer(thrower)) msg("You have no hands to throw with!"); + return B_TRUE; + } taketime(thrower, SPEED_THROW); return fireat(thrower, o, 1, where, getthrowspeed(getattr(thrower, A_STR)), NULL); } @@ -7842,12 +8163,27 @@ void timeeffectslf(lifeform_t *lf) { // chance of losing hp if (rnd(0,3)) { char buf[BUFLEN]; + flag_t *sf; if (isplayer(lf)) { msg("You vomit violently."); + } else if (cansee(player, lf)) { + char lfname[BUFLEN]; + getlfname(lf, lfname); + msg("%s vomits violently.", lfname); } sprintf(buf, "poisoning^from %s",f->text); losehp(lf, 2, DT_DIRECT, NULL, buf); taketime(lf,5); + + addob(lf->cell->obpile, "pool of vomit"); + + // stop sprinting + sf = lfhasflag(lf, F_SPRINTING); + if (sf && sf->val[0]) { + killflag(sf); + } + // boost spells end + stopallspells(lf); } } } @@ -8089,6 +8425,23 @@ void turneffectslf(lifeform_t *lf) { } } } + + // some things get your boots too! + if (!isdead(lf)) { + object_t *boots; + boots = getequippedob(lf->pack, BP_FEET); + if (boots) { + switch (f->val[0]) { + case DT_ACID: + case DT_FIRE: + case DT_WATER: + takedamage(boots, dam, f->val[0]); + break; + default: + break; + } + } + } } } if (isdead(lf)) return; @@ -8492,9 +8845,14 @@ int validateraces(void) { } } else if ((f->id == F_CANCAST) || (f->id == F_CANWILL)) { objecttype_t *sp; + enum SPELLSCHOOL school; sp = findot(f->val[0]); + school = getspellschool(f->val[0]); if (sp->obclass->id == OC_SPELL) { - if ((f->id == F_CANWILL) || hasflagval(r->flags, F_HASSKILL, SK_SPELLCASTING, NA, NA, NULL)) { + if ((f->id == F_CANWILL) || + hasflagval(r->flags, F_HASSKILL, SK_SPELLCASTING, NA, NA, NULL) || + (school == SS_ALLOMANCY) || (school == SS_MENTAL) + ) { int power; lifeform_t *lf; // add a fake lf @@ -8518,6 +8876,13 @@ int validateraces(void) { printf("ERROR in race '%s' - F_CANCAST %s (l%d) but no spellcasting skill\n", r->name, sp->name, getspelllevel(sp->id)); goterror = B_TRUE; } + } else { // ie. ability + if (f->val[0] == OT_A_SWOOP) { + if (!hasflag(r->flags, F_SWOOPRANGE)) { + printf("ERROR in race '%s' - has SWOOP ability but no F_SWOOPRANGE.\n", r->name); + goterror = B_TRUE; + } + } } } } @@ -8602,15 +8967,6 @@ int rest(lifeform_t *lf, int onpurpose) { 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); @@ -8710,28 +9066,8 @@ int wear(lifeform_t *lf, object_t *o) { return B_TRUE; } else if (nparts == 1) { bp = possbp[0]; - } else { + } else { // multiple possible locations int i; - /* - if (gamestarted && isplayer(lf)) { - int i; - // ask where - sprintf(buf, "Wear %s on which body part?", obname); - initprompt(&prompt, buf); - for (i = 0; i < nparts; i++) { - if (!hasobwithflagval(lf->pack, F_EQUIPPED, possbp[i], NA, NA, NULL)) { - addchoice(&prompt, i, getbodypartname(possbp[i]), NULL); - } - } - addchoice(&prompt, '^', "Cancel", NULL); - i = getchoicestr(&prompt); - if (i == '^') { - return B_TRUE; - } else { - bp = possbp[i]; - } - } else { // autoequip - */ // go in first possible place bp = BP_NONE; for (i = 0; i < nparts; i++) { @@ -8740,7 +9076,12 @@ int wear(lifeform_t *lf, object_t *o) { break; } } - if (bp == BP_NONE) return B_TRUE; + if (bp == BP_NONE) { + if (isplayer(lf)) { + msg("You have no room to wear that."); + } + return B_TRUE; + } //} } @@ -8891,6 +9232,18 @@ int weild(lifeform_t *lf, object_t *o) { case E_NOHANDS: msg("You are not capable of weilding a weapon!"); break; + case E_LOWCON: + msg("You are not healthy enough to use this weapon."); + break; + case E_LOWDEX: + msg("You are not dextrous enough to use this weapon."); + break; + case E_LOWIQ: + msg("You are not smart enough to use this weapon."); + break; + case E_LOWSTR: + msg("You are not strong enough to use this weapon."); + break; default: msg("For some reason, you weild this!"); break; diff --git a/lf.h b/lf.h index 5ab3beb..b850255 100644 --- a/lf.h +++ b/lf.h @@ -3,7 +3,7 @@ lifeform_t *addlf(cell_t *cell, enum RACE rid, int level); lifeform_t *real_addlf(cell_t *cell, enum RACE rid, int level, int controller); job_t *addjob(enum JOB id, char *name); -race_t *addrace(enum RACE id, char *name, float weight, char glyph, enum MATERIAL mat); +race_t *addrace(enum RACE id, char *name, float weight, char glyph, int glyphcolour, enum MATERIAL mat); skill_t *addskill(enum SKILL id, char *name, char *desc); void adjustdamlf(lifeform_t *lf, int *amt, enum DAMTYPE damtype); int areallies(lifeform_t *lf1, lifeform_t *lf2); @@ -55,6 +55,7 @@ enum ALLEGIENCE getallegiance(lifeform_t *lf); object_t *getarmour(lifeform_t *lf, enum BODYPART bp); int getarmourrating(lifeform_t *lf); int getattackspeed(lifeform_t *lf); +int getattpoints(lifeform_t *lf); int getattr(lifeform_t *lf, enum ATTRIB attr); int getevasion(lifeform_t *lf); object_t *getbestthrowmissile(lifeform_t *lf); @@ -79,7 +80,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); +glyph_t *getlfglyph(lifeform_t *lf); enum MATERIAL getlfmaterial(lifeform_t *lf); float getmaxcarryweight(lifeform_t *lf); float getmaxliftweight(lifeform_t *lf); @@ -100,6 +101,7 @@ float getlfweight(lifeform_t *lf, int withobs); int getspellspeed(lifeform_t *lf); char *getplayername(char *buf); char *getplayernamefull(char *buf); +int getracerarity(enum RACE rid); object_t *getrandomarmour(lifeform_t *lf); //int getrandommonlevel(int depth); race_t *getrandomrace(map_t *map); @@ -173,6 +175,7 @@ float modifybystat(float num, lifeform_t *lf, enum ATTRIB att); void noise(cell_t *c, lifeform_t *noisemaker, char *text, char *seetext); void outfitlf(lifeform_t *lf); int pickup(lifeform_t *lf, object_t *what, int howmany, int fromground); +void practice(lifeform_t *lf, enum SKILL skid); void precalclos(lifeform_t *lf); int push(lifeform_t *lf, object_t *o, int dir); void relinklf(lifeform_t *src, map_t *dst); diff --git a/log.txt b/log.txt index 6dc257c..bf33f56 100644 --- a/log.txt +++ b/log.txt @@ -7,9 +7,13 @@ xxx xxx xxx xxx +xxx +xxx +xxx finding random lf with rarity val 85-100 -> possibility: goblin, rarity=85 +-> possibility: troglodyte, rarity=85 -> possibility: xat, rarity=90 -> possibility: giant bat, rarity=90 -> possibility: giant worker ant, rarity=85 @@ -18,10 +22,11 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 -got 9 possibilities. +got 10 possibilities. finding random lf with rarity val 85-100 -> possibility: goblin, rarity=85 +-> possibility: troglodyte, rarity=85 -> possibility: xat, rarity=90 -> possibility: giant bat, rarity=90 -> possibility: giant worker ant, rarity=85 @@ -30,10 +35,11 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 -got 9 possibilities. +got 10 possibilities. finding random lf with rarity val 85-100 -> possibility: goblin, rarity=85 +-> possibility: troglodyte, rarity=85 -> possibility: xat, rarity=90 -> possibility: giant bat, rarity=90 -> possibility: giant worker ant, rarity=85 @@ -42,10 +48,11 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 -got 9 possibilities. +got 10 possibilities. finding random lf with rarity val 85-100 -> possibility: goblin, rarity=85 +-> possibility: troglodyte, rarity=85 -> possibility: xat, rarity=90 -> possibility: giant bat, rarity=90 -> possibility: giant worker ant, rarity=85 @@ -54,10 +61,11 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 -got 9 possibilities. +got 10 possibilities. finding random lf with rarity val 85-100 -> possibility: goblin, rarity=85 +-> possibility: troglodyte, rarity=85 -> possibility: xat, rarity=90 -> possibility: giant bat, rarity=90 -> possibility: giant worker ant, rarity=85 @@ -66,10 +74,11 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 -got 9 possibilities. +got 10 possibilities. finding random lf with rarity val 85-100 -> possibility: goblin, rarity=85 +-> possibility: troglodyte, rarity=85 -> possibility: xat, rarity=90 -> possibility: giant bat, rarity=90 -> possibility: giant worker ant, rarity=85 @@ -78,10 +87,11 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 -got 9 possibilities. +got 10 possibilities. finding random lf with rarity val 85-100 -> possibility: goblin, rarity=85 +-> possibility: troglodyte, rarity=85 -> possibility: xat, rarity=90 -> possibility: giant bat, rarity=90 -> possibility: giant worker ant, rarity=85 @@ -90,10 +100,11 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 -got 9 possibilities. +got 10 possibilities. finding random lf with rarity val 85-100 -> possibility: goblin, rarity=85 +-> possibility: troglodyte, rarity=85 -> possibility: xat, rarity=90 -> possibility: giant bat, rarity=90 -> possibility: giant worker ant, rarity=85 @@ -102,10 +113,11 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 -got 9 possibilities. +got 10 possibilities. finding random lf with rarity val 85-100 -> possibility: goblin, rarity=85 +-> possibility: troglodyte, rarity=85 -> possibility: xat, rarity=90 -> possibility: giant bat, rarity=90 -> possibility: giant worker ant, rarity=85 @@ -114,10 +126,11 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 -got 9 possibilities. +got 10 possibilities. finding random lf with rarity val 85-100 -> possibility: goblin, rarity=85 +-> possibility: troglodyte, rarity=85 -> possibility: xat, rarity=90 -> possibility: giant bat, rarity=90 -> possibility: giant worker ant, rarity=85 @@ -126,10 +139,11 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 -got 9 possibilities. +got 10 possibilities. finding random lf with rarity val 85-100 -> possibility: goblin, rarity=85 +-> possibility: troglodyte, rarity=85 -> possibility: xat, rarity=90 -> possibility: giant bat, rarity=90 -> possibility: giant worker ant, rarity=85 @@ -138,10 +152,11 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 -got 9 possibilities. +got 10 possibilities. finding random lf with rarity val 85-100 -> possibility: goblin, rarity=85 +-> possibility: troglodyte, rarity=85 -> possibility: xat, rarity=90 -> possibility: giant bat, rarity=90 -> possibility: giant worker ant, rarity=85 @@ -150,10 +165,11 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 -got 9 possibilities. +got 10 possibilities. finding random lf with rarity val 85-100 -> possibility: goblin, rarity=85 +-> possibility: troglodyte, rarity=85 -> possibility: xat, rarity=90 -> possibility: giant bat, rarity=90 -> possibility: giant worker ant, rarity=85 @@ -162,10 +178,11 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 -got 9 possibilities. +got 10 possibilities. finding random lf with rarity val 85-100 -> possibility: goblin, rarity=85 +-> possibility: troglodyte, rarity=85 -> possibility: xat, rarity=90 -> possibility: giant bat, rarity=90 -> possibility: giant worker ant, rarity=85 @@ -174,124 +191,436 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 -got 9 possibilities. +got 10 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: troglodyte, rarity=85 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +got 10 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: troglodyte, rarity=85 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +got 10 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: troglodyte, rarity=85 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +got 10 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: troglodyte, rarity=85 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +got 10 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: troglodyte, rarity=85 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +got 10 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: troglodyte, rarity=85 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +got 10 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: troglodyte, rarity=85 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +got 10 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: troglodyte, rarity=85 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +got 10 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: troglodyte, rarity=85 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +got 10 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: troglodyte, rarity=85 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +got 10 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: troglodyte, rarity=85 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +got 10 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: troglodyte, rarity=85 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +got 10 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: troglodyte, rarity=85 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +got 10 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: troglodyte, rarity=85 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +got 10 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: troglodyte, rarity=85 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +got 10 possibilities. rollhitdice() - rolling 2d4 + 2 rollhitdice() - mod is +-5% -rollhitdice() ---- die 1/2 == 5 -rollhitdice() ---- die 2/2 == 6 -TOTAL: 11 - -> modified to: 11 +rollhitdice() ---- die 1/2 == 4 +rollhitdice() ---- die 2/2 == 4 +TOTAL: 8 + -> modified to: 8 givejob() starting. -processing normal flag: 186 -processing normal flag: 145 -processing normal flag: 145 -processing normal flag: 145 -processing normal flag: 145 -processing normal flag: 145 -processing normal flag: 145 -processing normal flag: 145 -processing normal flag: 145 -processing normal flag: 145 -processing normal flag: 145 -processing normal flag: 145 -processing normal flag: 145 -processing normal flag: 146 -processing normal flag: 146 -processing normal flag: 146 -processing normal flag: 146 -processing normal flag: 146 -processing normal flag: 213 -processing normal flag: 213 -processing normal flag: 213 -processing normal flag: 213 -processing normal flag: 213 -processing normal flag: 213 -processing normal flag: 213 -processing normal flag: 213 -processing normal flag: 213 -processing normal flag: 213 -processing normal flag: 213 -processing normal flag: 213 -processing normal flag: 213 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -processing normal flag: 212 -fireat(): dam = throwdam(2) * speed(2) = 4 -AIMOVE: something -.oO { looking for covetted objects... } -.oO { no targetcell, so looking for remote objects } -.oO { didn't find any obs i want } -.oO { i have a target... } -.oO { my target is lfid 31 (human). } -.oO { i cannot see my target. moving to last known loc 12/15 } -.oO { something going to targecell: 12, 15 } -.oO { walking from 12,17 towards f_targetcell (12,15) ... } -.oO { successfully walked towards f_targetcell. } -AIMOVE: something -.oO { looking for covetted objects... } -.oO { didn't find any obs i want } -.oO { walking from 11,18 towards f_targetcell (12,15) ... } -.oO { successfully walked towards f_targetcell. } +processing normal flag: 191 +processing normal flag: 149 +processing normal flag: 149 +processing normal flag: 149 +processing normal flag: 149 +processing normal flag: 149 +processing normal flag: 149 +processing normal flag: 149 +processing normal flag: 149 +processing normal flag: 149 +processing normal flag: 149 +processing normal flag: 149 +processing normal flag: 149 +processing normal flag: 150 +processing normal flag: 150 +processing normal flag: 150 +processing normal flag: 150 +processing normal flag: 150 +processing normal flag: 150 +processing normal flag: 219 +processing normal flag: 219 +processing normal flag: 219 +processing normal flag: 219 +processing normal flag: 219 +processing normal flag: 219 +processing normal flag: 219 +processing normal flag: 219 +processing normal flag: 219 +processing normal flag: 219 +processing normal flag: 219 +processing normal flag: 219 +processing normal flag: 219 +processing normal flag: 219 +processing normal flag: 219 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +processing normal flag: 218 +nclasses is 0 +nclasses is 0 +nclasses is 0 +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] = 0 +initial dam[0] = 1 +adjusted for lf to dam[0] = 1 +reduced by armour to dam[0] = 0 +initial dam[0] = 26 +heavy blow makes dam[0] = 39 +adjusted for lf to dam[0] = 39 +reduced by armour to dam[0] = 39 +initial dam[1] = 10 +heavy blow makes dam[1] = 15 +adjusted for lf to dam[1] = 15 +reduced by armour to dam[1] = 15 +nclasses is 0 +nclasses is 0 +initial dam[0] = 19 +heavy blow makes dam[0] = 28 +adjusted for lf to dam[0] = 28 +reduced by armour to dam[0] = 23 +initial dam[1] = 6 +heavy blow makes dam[1] = 9 +adjusted for lf to dam[1] = 4 +reduced by armour to dam[1] = 3 +nclasses is 0 +nclasses is 0 +initial dam[0] = 2 +adjusted for lf to dam[0] = 2 +reduced by armour to dam[0] = 1 +initial dam[0] = 0 +adjusted for lf to dam[0] = 0 +reduced by armour to dam[0] = 0 +initial dam[0] = 2 +adjusted for lf to dam[0] = 2 +reduced by armour to dam[0] = 1 +initial dam[0] = 4 +adjusted for lf to dam[0] = 4 +reduced by armour to dam[0] = 2 +initial dam[0] = 1 +adjusted for lf to dam[0] = 1 +reduced by armour to dam[0] = 0 +initial dam[0] = 2 +adjusted for lf to dam[0] = 2 +reduced by armour to dam[0] = 1 +initial dam[0] = 2 +adjusted for lf to dam[0] = 2 +reduced by armour to dam[0] = 1 +initial dam[0] = 30 +heavy blow makes dam[0] = 45 +adjusted for lf to dam[0] = 45 +reduced by armour to dam[0] = 45 +initial dam[1] = 3 +heavy blow makes dam[1] = 4 +adjusted for lf to dam[1] = 4 +reduced by armour to dam[1] = 4 +rollhitdice() - rolling 49d4 + 0 +rollhitdice() - mod is +22% +rollhitdice() ---- die 1/49 == 1 +rollhitdice() ---- die 2/49 == 1 +rollhitdice() ---- die 3/49 == 2 +rollhitdice() ---- die 4/49 == 2 +rollhitdice() ---- die 5/49 == 4 +rollhitdice() ---- die 6/49 == 2 +rollhitdice() ---- die 7/49 == 3 +rollhitdice() ---- die 8/49 == 4 +rollhitdice() ---- die 9/49 == 4 +rollhitdice() ---- die 10/49 == 2 +rollhitdice() ---- die 11/49 == 1 +rollhitdice() ---- die 12/49 == 3 +rollhitdice() ---- die 13/49 == 1 +rollhitdice() ---- die 14/49 == 1 +rollhitdice() ---- die 15/49 == 4 +rollhitdice() ---- die 16/49 == 1 +rollhitdice() ---- die 17/49 == 3 +rollhitdice() ---- die 18/49 == 3 +rollhitdice() ---- die 19/49 == 4 +rollhitdice() ---- die 20/49 == 4 +rollhitdice() ---- die 21/49 == 1 +rollhitdice() ---- die 22/49 == 4 +rollhitdice() ---- die 23/49 == 1 +rollhitdice() ---- die 24/49 == 3 +rollhitdice() ---- die 25/49 == 3 +rollhitdice() ---- die 26/49 == 1 +rollhitdice() ---- die 27/49 == 2 +rollhitdice() ---- die 28/49 == 2 +rollhitdice() ---- die 29/49 == 4 +rollhitdice() ---- die 30/49 == 1 +rollhitdice() ---- die 31/49 == 1 +rollhitdice() ---- die 32/49 == 1 +rollhitdice() ---- die 33/49 == 3 +rollhitdice() ---- die 34/49 == 1 +rollhitdice() ---- die 35/49 == 4 +rollhitdice() ---- die 36/49 == 3 +rollhitdice() ---- die 37/49 == 2 +rollhitdice() ---- die 38/49 == 3 +rollhitdice() ---- die 39/49 == 3 +rollhitdice() ---- die 40/49 == 3 +rollhitdice() ---- die 41/49 == 4 +rollhitdice() ---- die 42/49 == 1 +rollhitdice() ---- die 43/49 == 2 +rollhitdice() ---- die 44/49 == 2 +rollhitdice() ---- die 45/49 == 1 +rollhitdice() ---- die 46/49 == 3 +rollhitdice() ---- die 47/49 == 3 +rollhitdice() ---- die 48/49 == 1 +rollhitdice() ---- die 49/49 == 2 +TOTAL: 115 + -> modified to: 140 +initial dam[0] = 0 +adjusted for lf to dam[0] = 0 +reduced by armour to dam[0] = 0 +initial dam[0] = 19 +heavy blow makes dam[0] = 28 +adjusted for lf to dam[0] = 28 +reduced by armour to dam[0] = 28 +initial dam[1] = 11 +heavy blow makes dam[1] = 16 +adjusted for lf to dam[1] = 16 +reduced by armour to dam[1] = 16 +nclasses is 1 diff --git a/map.c b/map.c index 0bd95b8..eb930be 100644 --- a/map.c +++ b/map.c @@ -17,6 +17,8 @@ extern map_t *firstmap,*lastmap; extern int viewx,viewy,vieww,viewh; extern lifeform_t *player; +extern glyph_t tempglyph; + extern enum OBCLASS sortorder[]; cell_t *addcell(map_t *m, int x, int y) { @@ -1493,7 +1495,7 @@ printf("dump of map '%s' (%d x %d):\n",map->name, map->w, map->h); for (y = 0; y < map->h; y++) { for (x = 0; x < map->w; x++) { cell = getcellat(map, x, y); - printf("%c",cell->type->glyph); + printf("%c",cell->type->glyph.ch); } printf("\n"); } @@ -1501,7 +1503,8 @@ printf("dump of map '%s' (%d x %d):\n",map->name, map->w, map->h); void explodecells(cell_t *c, int dam, int killwalls, object_t *o, int range, int wantannounce) { int x,y; - animradial(c, range, '}'); + + animradial(c, range, '}', C_RED); if (haslos(player, c)) { if (wantannounce) { @@ -1529,7 +1532,7 @@ void explodecells(cell_t *c, int dam, int killwalls, object_t *o, int range, int if (cc && (getcelldist(c, cc) <= (range+1))) { if (cc->lf && !isdead(cc->lf)) { // move away from centre of explosion - knockback(cc->lf, getdiraway(cc, c, B_FALSE, DT_COMPASS), 2, NULL); + knockback(cc->lf, getdiraway(cc, c, NULL, B_FALSE, DT_COMPASS), 2, NULL); } } } @@ -1974,7 +1977,7 @@ int isempty(cell_t *c) { } //returns TT_ based on what you can scan there -int isinscanrange(cell_t *c, void **thing, char *desc, char *glyph) { +int isinscanrange(cell_t *c, void **thing, char *desc, glyph_t *glyph) { flag_t *f; // handle scanner f = lfhasflag(player, F_DETECTLIFE); @@ -1989,7 +1992,8 @@ int isinscanrange(cell_t *c, void **thing, char *desc, char *glyph) { } if (glyph) { // select glyph based on size - *glyph = '0' + ((int) getlfsize(c->lf)); + glyph->ch = '0' + ((int) getlfsize(c->lf)); + glyph->colour = C_GREY; } return TT_MONSTER; } @@ -2000,7 +2004,10 @@ int isinscanrange(cell_t *c, void **thing, char *desc, char *glyph) { if (getcelldistorth(player->cell, c) <= f->val[0]) { if (c->lf && ismetal(c->lf->race->material->id) ) { *thing = c->lf; - if (glyph) *glyph = '*'; + if (glyph) { + glyph->ch = '*'; + glyph->colour = C_GREY; + } if (desc) sprintf(desc, "something metallic"); return TT_MONSTER; } else { @@ -2008,7 +2015,10 @@ int isinscanrange(cell_t *c, void **thing, char *desc, char *glyph) { for (o = c->obpile->first ; o ; o = o->next) { if (ismetal(o->material->id)) { *thing = o; - if (glyph) *glyph = '*'; + if (glyph) { + glyph->ch = '*'; + glyph->colour = C_GREY; + } if (desc) sprintf(desc, "something metallic"); return TT_OBJECT; } @@ -2023,7 +2033,10 @@ int isinscanrange(cell_t *c, void **thing, char *desc, char *glyph) { for (o = c->obpile->first ; o ; o = o->next) { if (!hasflag(o->flags, F_NOPICKUP) && !hasflag(o->flags, F_DOOR)) { *thing = o; - if (glyph) *glyph = '*'; + if (glyph) { + glyph->ch = '*'; + glyph->colour = C_GREY; + } if (desc) sprintf(desc, "an object"); return TT_OBJECT; } @@ -2139,6 +2152,11 @@ void makelit(cell_t *c, enum LIGHTLEV how, int howlong) { if (how == L_TEMP) { //if ((c->lit == L_PERMLIGHT) || (c->lit == L_PERMDARK)) { if (c->lit == L_PERMLIGHT) { + // light sources can't override permenant light + return; + } + if (c->lit == L_PERMDARK) { + // light sources can't override darkness spell return; } } diff --git a/map.h b/map.h index 6cbbd95..c4ea096 100644 --- a/map.h +++ b/map.h @@ -43,7 +43,7 @@ int isadjacent(cell_t *src, cell_t *dst); int isdiggable(cell_t *c); int isdoor(object_t *o, int *isopen); int isempty(cell_t *c); -int isinscanrange(cell_t *c, void **thing, char *desc, char *glyph); +int isinscanrange(cell_t *c, void **thing, char *desc, glyph_t *glyph); int islit(cell_t *c); int isloopdirok(cell_t *cell, int dir); int isnewcellok(cell_t *cell, char *err); diff --git a/move.c b/move.c index 49ffe34..caa5603 100644 --- a/move.c +++ b/move.c @@ -46,11 +46,6 @@ int canmove(lifeform_t *lf, int dir, enum ERROR *error) { rdata = NULL; } - if (lfhasflag(lf, F_GRAVBOOSTED)) { - if (error) *error = E_GRAVBOOSTED; - return B_FALSE; - } - if (isburdened(lf) >= BR_OVERLOADED) { if (error) *error = E_TOOHEAVY; return B_FALSE; @@ -122,7 +117,7 @@ int celldangerous(lifeform_t *lf, cell_t *cell, int onlyifknown, enum ERROR *err } // obvious things that you can see - if (!onlyifknown || haslos(lf, cell)) { + if (!onlyifknown || (haslos(lf, cell) && !lfhasflag(lf, F_UNDEAD))) { for (o = cell->obpile->first ; o ; o = o->next) { f = hasflag(o->flags, F_WALKDAM); if (f) { @@ -144,7 +139,9 @@ int celldangerous(lifeform_t *lf, cell_t *cell, int onlyifknown, enum ERROR *err } else { iq = getiqname(getattr(lf, A_IQ), NULL); if ((iq >= IQ_AVERAGE) && haslos(lf, cell)) { - include_nonobvious = B_TRUE; + if (!lfhasflag(lf, F_UNDEAD)) { + include_nonobvious = B_TRUE; + } } } if (include_nonobvious) { @@ -201,12 +198,24 @@ int cellwalkable(lifeform_t *lf, cell_t *cell, enum ERROR *error) { // ok } else { rdata = o; - if (error) *error = E_OBINWAY; + if (error) { + if (isdoor(o, NULL)) { + *error = E_DOORINWAY; + } else { + *error = E_OBINWAY; + } + } return B_FALSE; } } else { rdata = o; - if (error) *error = E_OBINWAY; + if (error) { + if (isdoor(o, NULL)) { + *error = E_DOORINWAY; + } else { + *error = E_OBINWAY; + } + } return B_FALSE; } } @@ -297,13 +306,14 @@ void dorandommove(lifeform_t *lf, int badmovesok) { // src is where something is // dst is what we are going away from // wantcheck is whether to check for dangerous things before considering a direction valid -int getdiraway(cell_t *src, cell_t *dst, int wantcheck, int dirtype) { +int getdiraway(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, int dirtype) { int d; cell_t *c; int maxdist=-1,bestdir=D_NONE; int dist[MAXDIR_COMPASS]; int poss[MAXDIR_COMPASS]; int nposs; + enum ERROR error; for (d = DC_N; d <= DC_NW; d++) { dist[d - DC_N] = -1; @@ -318,19 +328,30 @@ int getdiraway(cell_t *src, cell_t *dst, int wantcheck, int dirtype) { // destination is the thing we're fleeing from! thisdist = 0; } else { + + if (wantcheck) { - if (src->lf && canandwillmove(src->lf, d, NULL)) { - ok = B_TRUE; - } else if (!src->lf) { + if (srclf) { + if (canandwillmove(srclf, d, &error)) { + ok = B_TRUE; + } else if (error == E_DOORINWAY) { + ok = B_TRUE; + } + } else { ok = B_TRUE; } } else { - if (src->lf && cellwalkable(src->lf, c, NULL)) { - ok = B_TRUE; - } else if (!src->lf) { + if (srclf) { + if (cellwalkable(srclf, c, &error)) { + ok = B_TRUE; + } else if (error == E_DOORINWAY) { + ok = B_TRUE; + } + } else { ok = B_TRUE; } } + if (ok) { if (dirtype == DT_ORTH) { thisdist = getcelldistorth(c, dst); @@ -376,6 +397,7 @@ int getdirtowards(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, in int dist[MAXDIR_COMPASS]; int poss[MAXDIR_COMPASS]; int nposs; + enum ERROR error; for (d = DC_N; d <= DC_NW; d++) { dist[d - DC_N] = -1; @@ -393,15 +415,23 @@ int getdirtowards(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, in } if (wantcheck) { - if (srclf && canandwillmove(srclf, d, NULL)) { - ok = B_TRUE; - } else if (!srclf) { + if (srclf) { + if (canandwillmove(srclf, d, &error)) { + ok = B_TRUE; + } else if (error == E_DOORINWAY) { + ok = B_TRUE; + } + } else { ok = B_TRUE; } } else { - if (srclf && cellwalkable(srclf, c, NULL)) { - ok = B_TRUE; - } else if (!srclf) { + if (srclf) { + if (cellwalkable(srclf, c, &error)) { + ok = B_TRUE; + } else if (error == E_DOORINWAY) { + ok = B_TRUE; + } + } else { ok = B_TRUE; } } @@ -487,7 +517,8 @@ int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher) { return B_FALSE; } -int moveawayfrom(lifeform_t *lf, cell_t *dst ) { +// see 'movetowards' for description of dirtype +int moveawayfrom(lifeform_t *lf, cell_t *dst, int dirtype ) { int dir; int rv = B_TRUE; @@ -497,7 +528,7 @@ int moveawayfrom(lifeform_t *lf, cell_t *dst ) { } // move away from them - dir = getdiraway(lf->cell, dst, B_TRUE, DT_COMPASS); + dir = getdiraway(lf->cell, dst, lf, B_TRUE, dirtype); if (dir == D_NONE) { rv = B_TRUE; } else { @@ -589,7 +620,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) { for (o = newcell->obpile->first ; o ; o = nexto ) { nexto = o->next; f = hasflag(o->flags, F_SHARP); - if (f) { + if (f && hasbp(lf, BP_FEET)) { object_t *boots; // has boots on? boots = getequippedob(lf->pack, BP_FEET); @@ -798,7 +829,17 @@ int moveto(lifeform_t *lf, cell_t *newcell, int onpurpose) { return B_FALSE; } -int movetowards(lifeform_t *lf, cell_t *dst) { +// dirtype etermines whether to use compass or orthogonal direction to +// measure distance when determining which way is "towards" +// +// in general: +// use orthogonal for voluntary movement (eg. monster moving +// towards player), compass +// +// use compass for involuntary movement (eg. being knocked back by +// an explosion) +// +int movetowards(lifeform_t *lf, cell_t *dst, int dirtype) { int dir; int rv = B_TRUE; @@ -808,7 +849,7 @@ int movetowards(lifeform_t *lf, cell_t *dst) { } // move towards them - dir = getdirtowards(lf->cell, dst, lf, B_TRUE, DT_COMPASS); + dir = getdirtowards(lf->cell, dst, lf, B_TRUE, dirtype); if (dir != D_NONE) { rv = trymove(lf, dir, B_TRUE); } @@ -909,7 +950,14 @@ int opendoor(lifeform_t *lf, object_t *o) { } where = getoblocation(o); - noise(where, lf, "a door opening", NULL); + if (!haslos(player, where)) { + // don't anonuce this is we can see it. + // normally 'noise()' takes case of this by + // checking if we have LOS to the lifeform making + // sound, but in this case it's the door making + // the sound, not the lf. + noise(where, NULL, "a door opening.", NULL); + } if (player && haslos(player, where)) { needredraw = B_TRUE; drawscreen(); @@ -1154,6 +1202,24 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) { } } + + // gravboosted + if (lfhasflag(lf, F_GRAVBOOSTED)) { + // make a saving throw to move + if (!skillcheck(lf, SC_STR, 25, 0)) { + if (isplayer(lf)) { + msg("You try to move but are unable to lift your feet!"); + } else if (cansee(player, lf)) { + char lfname[BUFLEN]; + getlfname(lf, lfname); + msg("%s tries to move but is unable to lift its feet!",lfname); + } + reason = E_OK; + taketime(lf, getmovespeed(lf)); + return B_FALSE; + } + } + // move to new cell reason = E_OK; moveto(lf, cell, onpurpose); @@ -1188,7 +1254,7 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) { } } break; - case E_OBINWAY: + case E_DOORINWAY: inway = (object_t *)rdata; door = isdoor(inway, &dooropen); if (door && !dooropen) { @@ -1221,36 +1287,38 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) { reason = E_OK; } } - } else { - // can we push this? - if (ispushable(inway)) { - if (canpush(lf, inway, dir)) { - // push it! - push(lf, inway, dir); - } else { - if (lf->controller == C_PLAYER) { - char obname[BUFLEN]; - getobname(inway, obname, 1); - switch (reason) { - case E_TOOHEAVY: - msg("The %s is too heavy to move.",strchr(obname, ' ')+1); - break; - case E_INSUBSTANTIAL: - msg("You cannot push %s without a physical body!",strchr(obname, ' ')+1); - break; - default: - msg("The %s won't move for some reason.",strchr(obname, ' ')+1); - break; - } - } - } - } else { // object is in the way + } + break; + case E_OBINWAY: + inway = (object_t *)rdata; + // can we push this? + if (ispushable(inway)) { + if (canpush(lf, inway, dir)) { + // push it! + push(lf, inway, dir); + } else { if (lf->controller == C_PLAYER) { char obname[BUFLEN]; getobname(inway, obname, 1); - msg("There is %s in your way.",obname); + switch (reason) { + case E_TOOHEAVY: + msg("The %s is too heavy to move.",strchr(obname, ' ')+1); + break; + case E_INSUBSTANTIAL: + msg("You cannot push %s without a physical body!",strchr(obname, ' ')+1); + break; + default: + msg("The %s won't move for some reason.",strchr(obname, ' ')+1); + break; + } } } + } else { // object is in the way + if (lf->controller == C_PLAYER) { + char obname[BUFLEN]; + getobname(inway, obname, 1); + msg("There is %s in your way.",obname); + } } break; case E_LFINWAY: @@ -1285,16 +1353,6 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) { return attacklf(lf, cell->lf); } break; - case E_GRAVBOOSTED: - if (isplayer(lf)) { - msg("You try to move but are unable to lift your feet!"); - } else if (cansee(player, lf)) { - 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!"); @@ -1347,7 +1405,9 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) { int willmove(lifeform_t *lf, int dir, enum ERROR *error) { cell_t *cell; + enum IQBRACKET iq; //object_t *o; + iq = getiqname(getattr(lf, A_IQ), NULL); // default if (error) { @@ -1361,22 +1421,24 @@ int willmove(lifeform_t *lf, int dir, enum ERROR *error) { } // don't attack other monsters - if (cell->lf) { + if (cell->lf) { // if someone is in the way if (!isplayer(lf)) { // if we are a monster - // friendly monsters: don't hit other friendlies + // if the person in the way isn't our enemy... if (!areenemies(lf, cell->lf)) { - // TODO: swap places instead! - return B_FALSE; - } - /* - } else if (ispeaceful(lf)) { // peaceful mosnters: don't hit anyone - return B_FALSE; - } else { // hostile/nonfriendly monsters - don't hit other monsters - if (!isplayer(cell->lf) && !isfriendly(cell->lf)) { - return B_FALSE; + // if they are an ally... + if (canswapwith(lf, cell->lf)) { + return B_TRUE; } + return B_FALSE; } - */ + } + } + + // for intelligent things... + if (iq >= IQ_AVERAGE) { + // don't move if in pain + if (lfhasflag(lf, F_PAIN)) { + return B_FALSE; } } return B_TRUE; diff --git a/move.h b/move.h index 1c054a8..8888f1d 100644 --- a/move.h +++ b/move.h @@ -9,14 +9,14 @@ 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 dirtype); +int getdiraway(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, int dirtype); int getdirtowards(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, int dirtype); int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher); -int moveawayfrom(lifeform_t *lf, cell_t *dst); +int moveawayfrom(lifeform_t *lf, cell_t *dst, int dirtype); void moveeffects(lifeform_t *lf); int movelf(lifeform_t *lf, cell_t *newcell); int moveto(lifeform_t *lf, cell_t *newcell, int onpurpose); -int movetowards(lifeform_t *lf, cell_t *dst); +int movetowards(lifeform_t *lf, cell_t *dst, int dirtype); int opendoorat(lifeform_t *lf, cell_t *c); int opendoor(lifeform_t *lf, object_t *o); int pullnextto(lifeform_t *lf, cell_t *c); diff --git a/nexus.c b/nexus.c index dd7e3ef..b680b90 100644 --- a/nexus.c +++ b/nexus.c @@ -31,6 +31,8 @@ map_t *firstmap = NULL,*lastmap = NULL; knowledge_t *knowledge = NULL, *lastknowledge = NULL; hiddenname_t *firsthiddenname = NULL, *lasthiddenname = NULL; +glyph_t playerglyph,tempglyph; + // maintains unique lifeform ID numbers long nextlfid = 0; @@ -263,7 +265,7 @@ int main(int argc, char **argv) { return B_FALSE; } -celltype_t *addcelltype(int id, char *name, char glyph, int solid, int transparent, enum MATERIAL mat) { +celltype_t *addcelltype(int id, char *name, char glyph, int colour, int solid, int transparent, enum MATERIAL mat) { celltype_t *a; // add to the end of the list @@ -284,7 +286,8 @@ celltype_t *addcelltype(int id, char *name, char glyph, int solid, int transpare // set props a->id = id; a->name = strdup(name); - a->glyph = glyph; + a->glyph.ch = glyph; + a->glyph.colour = colour; a->solid = solid; a->transparent = transparent; a->material = findmaterial(mat); @@ -537,6 +540,11 @@ int init(void) { gamemode = GM_INIT; + + playerglyph.ch = '@'; + playerglyph.colour = C_GREY; + tempglyph.ch = '@'; + tempglyph.colour = C_GREY; initcommands(); initobjects(); @@ -545,13 +553,11 @@ int init(void) { initrace(); // cell types - addcelltype(CT_WALL, "rock wall", '#', B_SOLID, B_OPAQUE, MT_STONE); - addcelltype(CT_ROOMWALL, "rock wall", '#', B_SOLID, B_OPAQUE, MT_STONE); - addcelltype(CT_CORRIDOR, "rock floor", '.', B_EMPTY, B_TRANS, MT_STONE); - addcelltype(CT_LOOPCORRIDOR, "rock floor", 'L', B_EMPTY, B_TRANS, MT_STONE); - addcelltype(CT_ROOM, "rock floor", '.', B_EMPTY, B_TRANS, MT_STONE); - //addcelltype(CT_DOOROPEN, "wooden door", '-', B_EMPTY, B_TRANS, MT_WOOD); - //addcelltype(CT_DOORCLOSED, "wooden door", '+', B_SOLID, B_OPAQUE, MT_WOOD); + addcelltype(CT_WALL, "rock wall", '#', C_GREY, B_SOLID, B_OPAQUE, MT_STONE); + addcelltype(CT_ROOMWALL, "rock wall", '#', C_GREY, B_SOLID, B_OPAQUE, MT_STONE); + addcelltype(CT_CORRIDOR, "rock floor", '.', C_GREY, B_EMPTY, B_TRANS, MT_STONE); + addcelltype(CT_LOOPCORRIDOR, "rock floor", 'L', C_GREY, B_EMPTY, B_TRANS, MT_STONE); + addcelltype(CT_ROOM, "rock floor", '.', C_GREY, B_EMPTY, B_TRANS, MT_STONE); gamemode = GM_VALIDATION; if (validateobs()) { diff --git a/nexus.h b/nexus.h index 5d83c01..2a97ffa 100644 --- a/nexus.h +++ b/nexus.h @@ -1,6 +1,6 @@ #include "defs.h" -celltype_t *addcelltype(int id, char *name, char glyph, int solid, int transparent, enum MATERIAL mat); +celltype_t *addcelltype(int id, char *name, char glyph, int colour, int solid, int transparent, enum MATERIAL mat); command_t *addcommand(enum COMMAND id, char c, char *desc); void checkdeath(void); void checkendgame(void); diff --git a/objects.c b/objects.c index 5a5d50b..e48c81b 100644 --- a/objects.c +++ b/objects.c @@ -29,6 +29,8 @@ extern object_t *retobs[MAXPILEOBS+1]; extern int retobscount[MAXPILEOBS+1]; extern int nretobs; +extern glyph_t tempglyph; + extern map_t *firstmap; extern enum GAMEMODE gamemode; @@ -140,24 +142,50 @@ char *potadjective[] = { "", }; -char *colour[] = { - "aqua", - "azure", - "black", - "blue", - "brown", - "cyan", - "green", - "indigo", - "magenta", - "night-black", - "orange", - "pink", - "rainbow-coloured", - "red", - "violet", - "yellow", - "", +typedef struct hiddennamewithcol_s { + char *name; + enum COLOUR col; +} hiddennamewithcol_t; + +hiddennamewithcol_t colour[] = { + { "aqua", C_CYAN, }, + { "azure",C_BOLDBLUE }, + { "black",C_BLUE }, + { "blue",C_BLUE }, + { "brown",C_BROWN }, + { "cyan",C_CYAN }, + { "green",C_GREEN }, + { "indigo",C_MAGENTA }, + { "magenta",C_BOLDMAGENTA }, + { "night-black",C_BLUE }, + { "orange",C_ORANGE }, + { "pink",C_MAGENTA }, + { "rainbow-coloured",C_ORANGE }, + { "red",C_RED }, + { "violet",C_MAGENTA }, + { "yellow",C_YELLOW }, + { "",C_GREY }, +}; + +hiddennamewithcol_t gemtype[] = { + { "agate", C_MAGENTA, }, + { "bronze",C_BROWN }, + { "copper",C_BROWN }, + { "diamond",C_BOLDCYAN }, + { "emerald",C_GREEN }, + { "flourite",C_GREY }, + { "garnet",C_ORANGE }, + { "gold",C_YELLOW }, + { "jade",C_GREEN }, + { "lapis lazuli",C_BOLDBLUE }, + { "malachite",C_BOLDCYAN }, + { "onyx",C_BLUE }, + { "opal",C_CYAN }, + { "pearl",C_WHITE }, + { "quartz",C_GREY }, + { "ruby",C_RED }, + { "sapphire",C_CYAN }, + { "",C_GREY }, }; @@ -311,7 +339,7 @@ material_t *addmaterial(enum MATERIAL id, char *name, float weightrating) { return a; } -objectclass_t *addoc(enum OBCLASS id, char *name, char *desc, char glyph) { +objectclass_t *addoc(enum OBCLASS id, char *name, char *desc, char glyph, int glyphcolour) { objectclass_t *a; // add to the end of the list @@ -333,7 +361,8 @@ objectclass_t *addoc(enum OBCLASS id, char *name, char *desc, char glyph) { a->id = id; a->name = strdup(name); a->desc = strdup(desc); - a->glyph = glyph; + a->glyph.ch = glyph; + a->glyph.colour = glyphcolour; a->flags = addflagpile(NULL, NULL); return a; @@ -1365,7 +1394,7 @@ void brightflash(cell_t *centre, int range, lifeform_t *immunelf) { int x,y; cell_t *c; - animradial(centre, range, '}'); + animradial(centre, range, '}', C_GREY); // announce if (haslos(player, centre) && !isblind(player)) { @@ -1595,6 +1624,25 @@ objecttype_t *checkobnames(char *haystack, char *needle) { } +void colourmatchob(object_t *o, lifeform_t *lf) { + flag_t *f; + glyph_t *lfglyph; + lfglyph = getlfglyph(lf); + + f = hasflag(o->flags, F_GLYPH); + if (f) { + + f->val[0] = lfglyph->colour; + } else { + glyph_t *obglyph; + char buf[2]; + + obglyph = getglyph(o); + buf[0] = obglyph->ch; + buf[1] = '\0'; + addflag(o->flags, F_GLYPH, lfglyph->colour, NA, NA, buf); + } +} void copyobprops(object_t *dst, object_t *src) { dst->material = src->material; @@ -1812,6 +1860,7 @@ objecttype_t *findotn(char *name) { modname = strrep(modname, "blocks ", "block ", NULL); modname = strrep(modname, "cans ", "can ", NULL); modname = strrep(modname, "chunks ", "chunk ", NULL); + modname = strrep(modname, "flasks ", "flask ", NULL); modname = strrep(modname, "gems ", "gem ", NULL); modname = strrep(modname, "loaves ", "load ", NULL); modname = strrep(modname, "lumps ", "lump ", NULL); @@ -1940,25 +1989,34 @@ int getfirearmspeed(object_t *o) { return firespeed; } -char getglyph(object_t *o) { +glyph_t *getglyph(object_t *o) { flag_t *f; int isopen; char g = ' '; // default + int col = C_GREY; if (isdoor(o, &isopen)) { if (isopen) { g = '-'; } else { g = '+'; } + col = getmaterialcolour(o->material->id); } else { f = hasflag(o->flags, F_GLYPH); if (f) { g = f->text[0]; + if (f->val[0] != NA) { + col = f->val[0]; + } } else { - g = o->type->obclass->glyph; + g = o->type->obclass->glyph.ch; + //col = o->type->obclass->glyph.colour; + col = getmaterialcolour(o->material->id); } } - return g; + tempglyph.ch = g; + tempglyph.colour = col; + return &tempglyph; } void fragments(cell_t *centre, char *what, int speed) { @@ -2002,6 +2060,7 @@ void genhiddennames(void) { for (ot = objecttype ; ot ; ot = ot->next) { f = hasflag(ot->flags, F_HASHIDDENNAME); if (f) { + int n; char *thisname; if (strlen(f->text)) { thisname = strdup(f->text); @@ -2017,6 +2076,38 @@ void genhiddennames(void) { } else if (strstr(thisname, "luminous")) { addflag(ot->flags, F_PRODUCESLIGHT, 1, NA, NA, NULL); } + + // set colour based on hiddenname + for (n = 0; strlen(colour[n].name); n++) { + if (strstr(thisname, colour[n].name)) { + flag_t *gf; + gf = hasflag(ot->flags, F_GLYPH); + if (gf) { + gf->val[0] = colour[n].col; + } else { + char buf[2]; + + buf[0] = ot->obclass->glyph.ch; + buf[1] = '\0'; + addflag(ot->flags, F_GLYPH, colour[n].col, NA, NA, buf); + } + } + } + for (n = 0; strlen(gemtype[n].name); n++) { + if (strstr(thisname, gemtype[n].name)) { + flag_t *gf; + gf = hasflag(ot->flags, F_GLYPH); + if (gf) { + gf->val[0] = gemtype[n].col; + } else { + char buf[2]; + + buf[0] = ot->obclass->glyph.ch; + buf[1] = '\0'; + addflag(ot->flags, F_GLYPH, gemtype[n].col, NA, NA, buf); + } + } + } free(thisname); } } @@ -2331,31 +2422,32 @@ char *getdamname(enum DAMTYPE damtype) { switch (damtype) { case DT_ALL: return "all damage"; case DT_ACID: return "acid"; - case DT_MELT: return "melting"; - case DT_PIERCE: return "piercing"; - case DT_SLASH: return "slashing"; + case DT_BASH: return "bludgeoning"; + case DT_BITE: return "bite"; + case DT_CHOP: return "chopping"; case DT_CLAW: return "claw"; + case DT_COLD: return "cold"; + case DT_CRUSH: return "crushing"; + case DT_DIRECT: return "direct"; + case DT_DECAY: return "decay"; case DT_ELECTRIC: return "electricity"; case DT_EXPLOSIVE: return "explosive"; + case DT_FALL: return "falling"; case DT_FIRE: return "fire"; - case DT_BITE: return "bite"; - case DT_BASH: return "bludgeoning"; - case DT_CHOP: return "chopping"; - case DT_COLD: return "cold"; - case DT_PETRIFY: return "petrification"; - case DT_POISONGAS: return "poison gas"; - case DT_POISON: return "poison"; - case DT_PROJECTILE: return "projectile"; case DT_HOLY: return "holy"; - case DT_DIRECT: return "direct"; - case DT_WATER: return "water"; - case DT_DECAY: return "decay"; + case DT_LIGHT: return "light"; case DT_MAGIC: return "magical"; + case DT_MELT: return "melting"; + case DT_NECROTIC: return "lifedrain"; + case DT_PETRIFY: return "petrification"; + case DT_PIERCE: return "piercing"; + case DT_POISON: return "poison"; + case DT_POISONGAS: return "poison gas"; + case DT_PROJECTILE: return "projectile"; + case DT_SLASH: return "slashing"; case DT_TOUCH: return "touch"; case DT_UNARMED: return "unarmed"; - case DT_LIGHT: return "light"; - case DT_CRUSH: return "crushing"; - case DT_FALL: return "falling"; + case DT_WATER: return "water"; default: return "unknown"; } return "unknown"; @@ -2385,6 +2477,7 @@ char *getdamnamenoun(enum DAMTYPE damtype) { case DT_DECAY: return "decay damage"; case DT_WATER: return "water"; case DT_MAGIC: return "magical damage"; + case DT_NECROTIC: return "lifedrain damage"; case DT_TOUCH: return "touch effects"; case DT_UNARMED: return "unarmed damage"; case DT_LIGHT: return "light damage"; @@ -2898,7 +2991,7 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan flag_t *omf; int found = B_FALSE; for (omf = om->flags->first ; omf ; omf = omf->next){ - if (hasflag(o->flags, omf->id)) { + if (hasflagval(o->flags, omf->id, omf->val[0], omf->val[1], omf->val[2], NULL)) { found = B_TRUE; } } @@ -3134,6 +3227,7 @@ float getobweight(object_t *o) { float getobunitweight(object_t *o) { float weight; + flag_t *f; weight = o->weight; @@ -3147,6 +3241,23 @@ float getobunitweight(object_t *o) { weight *= ratio; } + f = hasflag(o->flags, F_WET); + if (f) { + switch (f->val[0]) { + case W_DAMP: + weight *= 1.05; + break; + case W_WET: + weight *= 1.25; + break; + case W_SOAKED: + weight *= 1.5; + break; + default: + break; + } + } + return weight; } @@ -3840,14 +3951,14 @@ void initobjects(void) { objecttype_t *ot; // generate hidden names - for (n = 0; strlen(colour[n]); n++) { + for (n = 0; strlen(colour[n].name); n++) { char buf[BUFLEN]; // add it without an adjective - sprintf(buf, "%s book", colour[n]); + sprintf(buf, "%s book", colour[n].name); addhiddenname(OC_BOOK, buf); // add it with all known adjectives for (i = 0; strlen(bookadjective[i]) ; i++) { - sprintf(buf, "%s %s book",bookadjective[i], colour[n]); + sprintf(buf, "%s %s book",bookadjective[i], colour[n].name); addhiddenname(OC_BOOK, buf); } } @@ -3876,14 +3987,14 @@ void initobjects(void) { addhiddenname(OC_POTION, "clear potion"); - for (n = 0; strlen(colour[n]); n++) { + for (n = 0; strlen(colour[n].name); n++) { char buf[BUFLEN]; // add it without an adjective - sprintf(buf, "%s potion", colour[n]); + sprintf(buf, "%s potion", colour[n].name); addhiddenname(OC_POTION, buf); // add it with all known adjectives for (i = 0; strlen(potadjective[i]) ; i++) { - sprintf(buf, "%s %s potion",potadjective[i], colour[n]); + sprintf(buf, "%s %s potion",potadjective[i], colour[n].name); addhiddenname(OC_POTION, buf); } } @@ -3903,22 +4014,12 @@ void initobjects(void) { addhiddenname(OC_WAND, "sapphire wand"); addhiddenname(OC_WAND, "wooden wand"); - addhiddenname(OC_RING, "agate ring"); - addhiddenname(OC_RING, "bronze ring"); - addhiddenname(OC_RING, "copper ring"); - addhiddenname(OC_RING, "diamond ring"); - addhiddenname(OC_RING, "emerald ring"); - addhiddenname(OC_RING, "flourite ring"); - addhiddenname(OC_RING, "garnet ring"); - addhiddenname(OC_RING, "gold ring"); - addhiddenname(OC_RING, "jade ring"); - addhiddenname(OC_RING, "polished ring"); - addhiddenname(OC_RING, "quartz ring"); - addhiddenname(OC_RING, "ruby ring"); - addhiddenname(OC_RING, "sapphire ring"); - addhiddenname(OC_RING, "silver ring"); - - + for (n = 0; strlen(gemtype[n].name); n++) { + char buf[BUFLEN]; + // add it without an adjective + sprintf(buf, "%s ring", gemtype[n].name); + addhiddenname(OC_RING, buf); + } for (n = 0; strlen(technoun[n]); n++) { // add it without an adjective @@ -3947,6 +4048,18 @@ void initobjects(void) { addflag_real(lastobmod->flags, F_SHODDY, B_TRUE, NA, NA, NULL, PERMENANT, B_KNOWN, -1); addobmod(OM_POISONED,"poisoned"); addflag_real(lastobmod->flags, F_HITCONFER, F_POISONED, SC_POISON, 25, "2-8", PERMENANT, B_KNOWN, -1); + addobmod(OM_WET1,"damp"); + addflag_real(lastobmod->flags, F_WET, W_DAMP, NA, NA, NULL, PERMENANT, B_KNOWN, -1); + addobmod(OM_WET2,"wet"); + addflag_real(lastobmod->flags, F_WET, W_WET, NA, NA, NULL, PERMENANT, B_KNOWN, -1); + addobmod(OM_WET3,"soaked"); + addflag_real(lastobmod->flags, F_WET, W_SOAKED, NA, NA, NULL, PERMENANT, B_KNOWN, -1); + addobmod(OM_RUSTY1,"rusty"); + addflag_real(lastobmod->flags, F_RUSTED, R_RUSTY, NA, NA, NULL, PERMENANT, B_KNOWN, -1); + addobmod(OM_RUSTY2,"very rusty"); + addflag_real(lastobmod->flags, F_RUSTED, R_VRUSTY, NA, NA, NULL, PERMENANT, B_KNOWN, -1); + addobmod(OM_RUSTY3,"thoroughly rusty"); + addflag_real(lastobmod->flags, F_RUSTED, R_TRUSTY, NA, NA, NULL, PERMENANT, B_KNOWN, -1); // brands modifiers - flags should be UNKNOWN! // also don't double up with names of scrolls etc. @@ -3970,15 +4083,15 @@ void initobjects(void) { addbrand(BR_SLOTH, "of sloth", BP_FEET); addflag_real(lastbrand->flags, F_EQUIPCONFER, F_SLOWMOVE, 5, NA, NULL, PERMENANT, B_UNKNOWN, -1); - addbrand(BR_STRENGTH, "of strength", BP_HANDS); + addbrand(BR_POWER, "of power", BP_HANDS); addflag_real(lastbrand->flags, F_EQUIPCONFER, F_ATTRMOD, A_STR, 3, NULL, PERMENANT, B_UNKNOWN, -1); addbrand(BR_WEAKNESS, "of feebleness", BP_HANDS); addflag_real(lastbrand->flags, F_EQUIPCONFER, F_ATTRMOD, A_STR, -3, NULL, PERMENANT, B_UNKNOWN, -1); - addbrand(BR_DEXTERITY, "of dexterity", BP_HANDS); + addbrand(BR_NIMBLENESS, "of nimbleness", BP_HANDS); addflag_real(lastbrand->flags, F_EQUIPCONFER, F_ATTRMOD, A_DEX, 3, NULL, PERMENANT, B_UNKNOWN, -1); addbrand(BR_IMPACT, "of impact", BP_WEAPON); // TODO: make thisonly go ont obashing weapons addflag_real(lastbrand->flags, F_HEAVYBLOW, B_TRUE, NA, NA, NULL, PERMENANT, B_UNKNOWN, -1); - addbrand(BR_INTELLIGENCE, "of intelligence", BP_HEAD); + addbrand(BR_THINKING, "of thinking", BP_HEAD); addflag_real(lastbrand->flags, F_EQUIPCONFER, F_ATTRMOD, A_IQ, 3, NULL, PERMENANT, B_UNKNOWN, -1); addbrand(BR_KNOWLEDGE, "of knowledge", BP_HEAD); addflag_real(lastbrand->flags, F_EQUIPCONFER, F_DETECTAURAS, B_TRUE, NA, NULL, PERMENANT, B_UNKNOWN, -1); @@ -3999,6 +4112,8 @@ void initobjects(void) { addflag_real(lastbrand->flags, F_EQUIPCONFER, F_INVISIBLE, B_TRUE, NA, NULL, PERMENANT, B_UNKNOWN, -1); addbrand(BR_ANTIMAG, "of antimagic", BP_SHOULDERS); addflag_real(lastbrand->flags, F_EQUIPCONFER, F_RESISTMAG, 10, NA, NULL, PERMENANT, B_UNKNOWN, -1); + addbrand(BR_HEALTH, "of health", BP_BODY); + addflag_real(lastbrand->flags, F_EQUIPCONFER, F_ATTRMOD, A_CON, 3, NULL, PERMENANT, B_UNKNOWN, -1); // materials addmaterial(MT_NOTHING, "nothing", 0); @@ -4014,6 +4129,7 @@ void initobjects(void) { addmaterial(MT_WETPAPER, "wet paper", 3); addmaterial(MT_CLOTH, "cloth", 3); addflag(lastmaterial->flags, F_FLAMMABLE, B_TRUE, NA, NA, NULL); + addflag(lastmaterial->flags, F_CANGETWET, B_TRUE, NA, NA, NULL); addmaterial(MT_FOOD, "food", 3); addmaterial(MT_PLASTIC, "plastic", 3); addflag(lastmaterial->flags, F_HARD, B_TRUE, NA, NA, NULL); @@ -4023,6 +4139,7 @@ void initobjects(void) { addflag(lastmaterial->flags, F_MATCONVERTTEXTPL, MT_FIRE, NA, NA, "melt"); addmaterial(MT_RUBBER, "rubber", 4); addmaterial(MT_LEATHER, "leather", 4); + addflag(lastmaterial->flags, F_CANGETWET, B_TRUE, NA, NA, NULL); addmaterial(MT_BONE, "bone", 5); addflag(lastmaterial->flags, F_HARD, B_TRUE, NA, NA, NULL); addmaterial(MT_ICE, "ice",6); @@ -4030,6 +4147,7 @@ void initobjects(void) { addmaterial(MT_WOOD, "wood", 6); addflag(lastmaterial->flags, F_HARD, B_TRUE, NA, NA, NULL); addflag(lastmaterial->flags, F_FLAMMABLE, B_TRUE, NA, NA, NULL); + addflag(lastmaterial->flags, F_CANGETWET, B_TRUE, NA, NA, NULL); addmaterial(MT_ACID, "acid", 7); addmaterial(MT_WATER, "water", 7); addmaterial(MT_BLOOD, "blood", 7); @@ -4045,9 +4163,9 @@ void initobjects(void) { //addmaterial(MT_GOLD, "gold", 16); // object classes - addoc(OC_DFEATURE, "Dungeon Features", "Doors, etc.", '\\'); - addoc(OC_MONEY, "Money", "The standard currency of Nexus.", '$'); - addoc(OC_SCROLL, "Scrolls", "An arcane roll of parchment, inscribed with many magical glyphs.", '?'); + addoc(OC_DFEATURE, "Dungeon Features", "Doors, etc.", '\\', C_GREY); + addoc(OC_MONEY, "Money", "The standard currency of Nexus.", '$', C_GREY); + addoc(OC_SCROLL, "Scrolls", "An arcane roll of parchment, inscribed with many magical glyphs.", '?', C_GREY); addflag(lastobjectclass->flags, F_HASHIDDENNAME, 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); @@ -4056,56 +4174,56 @@ void initobjects(void) { //addflag(lastobjectclass->flags, F_MATCONVERTTEXT, MT_WATER, NA, NA, "goes soggy"); //addflag(lastobjectclass->flags, F_MATCONVERTTEXTPL, MT_WATER, NA, NA, "go soggy"); - addoc(OC_WAND, "Wands", "A limited-use magical wand which casts the imbued spell.", '/'); + addoc(OC_WAND, "Wands", "A limited-use magical wand which casts the imbued spell.", '/', C_GREY); addflag(lastobjectclass->flags, F_DTIMMUNE, DT_FIRE, NA, NA, NULL); addflag(lastobjectclass->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL); addflag(lastobjectclass->flags, F_OPERABLE, B_TRUE, NA, NA, NULL); addflag(lastobjectclass->flags, F_OPERUSECHARGE, B_TRUE, NA, NA, NULL); addflag(lastobjectclass->flags, F_RNDCHARGES, 2, 12, NA, NULL); - addoc(OC_POTION, "Potions", "A strange concoction contained within a small flask.", '!'); + addoc(OC_POTION, "Potions", "A strange concoction contained within a small flask.", '!', C_GREY); addflag(lastobjectclass->flags, F_HASHIDDENNAME, 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_POURABLE, B_TRUE, NA, NA, NULL); - addoc(OC_RING, "Rings", "A circular band, worn on the finger.", '='); + addoc(OC_RING, "Rings", "A circular band, worn on the finger.", '=', C_GREY); addflag(lastobjectclass->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL); addflag(lastobjectclass->flags, F_GOESON, BP_RIGHTHAND, NA, NA, NULL); addflag(lastobjectclass->flags, F_GOESON, BP_LEFTHAND, NA, NA, NULL); - addoc(OC_WEAPON, "Weapons", "An instrument used for the purpose of causing harm or death.", ')'); + addoc(OC_WEAPON, "Weapons", "An instrument used for the purpose of causing harm or death.", ')', C_GREY); addflag(lastobjectclass->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(lastobjectclass->flags, F_ENCHANTABLE, B_TRUE, NA, NA, NULL); - addoc(OC_ARMOUR, "Armour/Clothing", "Protective gear.", ']'); + addoc(OC_ARMOUR, "Armour/Clothing", "Protective gear.", ']', C_GREY); 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.", ';'); + addoc(OC_MISSILE, "Missiles/Ammunition", "An instrument used for the purpose of causing harm or death.", ';', C_GREY); 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); - addoc(OC_ROCK, "Rocks/Gems", "Boring (or not so boring) rocks.", '*'); - addoc(OC_FOOD, "Food", "Yum!", '%'); + addoc(OC_ROCK, "Rocks/Gems", "Boring (or not so boring) rocks.", '*', C_GREY); + addoc(OC_FOOD, "Food", "Yum!", '%', C_GREY); addflag(lastobjectclass->flags, F_STACKABLE, B_TRUE, NA, NA, ""); addflag(lastobjectclass->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); - addoc(OC_CORPSE, "Corpses", "Dead flesh which was once living.", '%'); + addoc(OC_CORPSE, "Corpses", "Dead flesh which was once living.", '%', C_GREY); addflag(lastobjectclass->flags, F_STACKABLE, B_TRUE, NA, NA, ""); addflag(lastobjectclass->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastobjectclass->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(lastobjectclass->flags, F_OBHP, 50, 50, NA, NULL); addflag(lastobjectclass->flags, F_OBHPDRAIN, 1, DT_DECAY, NA, NULL); // ie. corpses last for 50 turns - addoc(OC_TECH, "Technology", "A strange piece of futuristic technology.", '~'); + addoc(OC_TECH, "Technology", "A strange piece of futuristic technology.", '~', C_GREY); addflag(lastobjectclass->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(lastobjectclass->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); - addoc(OC_TOOLS, "Tools", "Useful items, from the common to the obscure.", '['); + addoc(OC_TOOLS, "Tools", "Useful items, from the common to the obscure.", '[', C_GREY); addflag(lastobjectclass->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(lastobjectclass->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); - addoc(OC_MISC, "Miscellaneous", "This could be anything.", '\\'); - addoc(OC_EFFECT, "Environmental Effects", "Smoke, fire, etc.", '}'); + addoc(OC_MISC, "Miscellaneous", "This could be anything.", '\\', C_GREY); + addoc(OC_EFFECT, "Environmental Effects", "Smoke, fire, etc.", '}', C_GREY); addflag(lastobjectclass->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); - addoc(OC_BOOK, "Books", "Spellbooks, tomes or manuals.", '+'); + addoc(OC_BOOK, "Books", "Spellbooks, tomes or manuals.", '+', C_GREY); addflag(lastobjectclass->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL); addflag(lastobjectclass->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); - addoc(OC_SPELL, "Spells", "A magical spell", '&'); // this is a "virtual" object class - addoc(OC_ABILITY, "Abilities", "A special ability", '&'); // this is a "virtual" object class + addoc(OC_SPELL, "Spells", "A magical spell", '&', C_GREY); // this is a "virtual" object class + addoc(OC_ABILITY, "Abilities", "A special ability", '&', C_GREY); // this is a "virtual" object class // object types @@ -4126,7 +4244,7 @@ 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_GLYPH, C_BROWN, NA, NA, "\\"); 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); @@ -4178,13 +4296,13 @@ void initobjects(void) { addot(OT_VENDINGMACHINE, "vending machine", "A gold-operated vending machine.", MT_METAL, 500, OC_DFEATURE); addflag(lastot->flags, F_RARITY, H_ALL, 70, NA, ""); - addflag(lastot->flags, F_GLYPH, NA, NA, NA, "_"); + addflag(lastot->flags, F_GLYPH, C_WHITE, NA, NA, "_"); addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addot(OT_PORTAL, "magic portal", "A magical portal to a different place...", MT_MAGIC, 0, OC_DFEATURE); - addflag(lastot->flags, F_GLYPH, NA, NA, NA, "&"); - addflag(lastot->flags, F_CLIMBABLE, D_IN, NA, NA, "&"); + addflag(lastot->flags, F_GLYPH, C_BOLDGREEN, NA, NA, "&"); + addflag(lastot->flags, F_CLIMBABLE, D_IN, NA, NA, NULL); addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); @@ -4202,7 +4320,7 @@ void initobjects(void) { addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_THROWMISSILE, 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, ","); + 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_NOBLESS, B_TRUE, NA, NA, NULL); @@ -4211,27 +4329,33 @@ void initobjects(void) { addflag(lastot->flags, F_HOLDCONFER, F_XRAYVIS, 2, NA, NULL); addflag(lastot->flags, F_HOLDCONFER, F_DETECTAURAS, B_TRUE, NA, NULL); addflag(lastot->flags, F_HOLDCONFER, F_DETECTMAGIC, B_TRUE, NA, NULL); + addflag(lastot->flags, F_VALUE, 1000, NA, NA, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); // food addot(OT_BERRY, "berry", "Juicy, brightly coloured berries.", MT_FOOD, 0.1, OC_FOOD); + addflag(lastot->flags, F_GLYPH, C_ORANGE, NA, NA, "%"); addflag(lastot->flags, F_EDIBLE, B_TRUE, 8, NA, ""); addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL); addflag(lastot->flags, F_NUMAPPEAR, 1, 15, NA, ""); addot(OT_NUT, "peanut", "A species in the legume family.", MT_FOOD, 0.1, OC_FOOD); + addflag(lastot->flags, F_GLYPH, C_BROWN, NA, NA, "%"); 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.3, OC_FOOD); + addflag(lastot->flags, F_GLYPH, C_YELLOW, NA, NA, "%"); 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_GLYPH, C_YELLOW, NA, NA, "%"); 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_GLYPH, C_GREEN, NA, NA, "%"); addflag(lastot->flags, F_EDIBLE, B_TRUE, 50, NA, ""); addflag(lastot->flags, F_RARITY, H_DUNGEON, 85, NA, NULL); addot(OT_MUSHROOM, "mushroom", "A large brown mushroom.", MT_FOOD, 0.2, OC_FOOD); @@ -4239,52 +4363,32 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL); addflag(lastot->flags, F_NUMAPPEAR, 1, 3, NA, ""); addot(OT_BREADSTALE, "loaf of stale bread", "A small loaf of old, stale bread.", MT_FOOD, 0.5, OC_FOOD); + addflag(lastot->flags, F_GLYPH, C_BROWN, NA, NA, "%"); addflag(lastot->flags, F_EDIBLE, B_TRUE, 80, NA, ""); addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); addot(OT_CHEESE, "chunk of cheese", "A chunk of hard cheese.", MT_FOOD, 0.5, OC_FOOD); + addflag(lastot->flags, F_GLYPH, C_YELLOW, NA, NA, "%"); addflag(lastot->flags, F_EDIBLE, B_TRUE, 85, NA, ""); addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); addot(OT_ROASTMEAT, "chunk of roast meat", "A chunk of flame-roasted flesh.", MT_FOOD, 1, OC_FOOD); // weight normally comes from corpse type + addflag(lastot->flags, F_GLYPH, C_BROWN, NA, NA, "%"); addflag(lastot->flags, F_EDIBLE, B_TRUE, 100, NA, ""); addflag(lastot->flags, F_RARITY, H_DUNGEON, 65, NA, NULL); addot(OT_BREADFRESH, "loaf of fresh bread", "A freshly-baked loaf of bread.", MT_FOOD, 0.5, OC_FOOD); + addflag(lastot->flags, F_GLYPH, C_BROWN, NA, NA, "%"); addflag(lastot->flags, F_EDIBLE, B_TRUE, 100, NA, ""); addflag(lastot->flags, F_RARITY, H_DUNGEON, 65, NA, NULL); addot(OT_CHOCOLATE, "block of chocolate", "An entire block of chocolate.", MT_FOOD, 0.5, OC_FOOD); + addflag(lastot->flags, F_GLYPH, C_BROWN, NA, NA, "%"); addflag(lastot->flags, F_EDIBLE, B_TRUE, 110, NA, ""); addflag(lastot->flags, F_RARITY, H_DUNGEON, 40, NA, NULL); // corpses - /* - addot(OT_CORPSEEYEBAT, "eyebat corpse", "The dead body of an eyebat.", MT_FLESH, 5, OC_CORPSE); - addflag(lastot->flags, F_EDIBLE, B_TRUE, 10, NA, ""); - addot(OT_CORPSEBAT, "bat corpse", "The dead body of a bat.", MT_FLESH, 5, OC_CORPSE); - addflag(lastot->flags, F_EDIBLE, B_TRUE, 10, NA, ""); - addot(OT_CORPSEFLY, "fly corpse", "The dead body of a giant flying insect.", MT_FLESH, 5, OC_CORPSE); - addflag(lastot->flags, F_EDIBLE, B_TRUE, 10, NA, ""); - addot(OT_CORPSEGLOWBUG, "glowbug corpse", "The dead body of a glowbug.", MT_FLESH, 1, OC_CORPSE); - addflag(lastot->flags, F_EDIBLE, B_TRUE, 10, NA, ""); - addot(OT_CORPSEGOBLIN, "goblin corpse", "The dead body of a goblin.", MT_FLESH, 20, OC_CORPSE); - addflag(lastot->flags, F_EDIBLE, B_TRUE, 25, NA, ""); - addot(OT_CORPSEHUMAN, "human corpse", "The dead body of a human.", MT_FLESH, 50, OC_CORPSE); - addflag(lastot->flags, F_EDIBLE, B_TRUE, 50, NA, ""); - addot(OT_CORPSEORK, "orc corpse", "The dead body of an orc.", MT_FLESH, 90, OC_CORPSE); - addflag(lastot->flags, F_EDIBLE, B_TRUE, 50, NA, ""); - addot(OT_CORPSERODENT, "rodent corpse", "The dead body of some kind of rodent.", MT_FLESH, 5, OC_CORPSE); - addflag(lastot->flags, F_EDIBLE, B_TRUE, 20, NA, ""); - addot(OT_CORPSETROLL, "troll corpse", "The dead body of a troll.", MT_FLESH, 90, OC_CORPSE); - addflag(lastot->flags, F_EDIBLE, B_TRUE, 50, NA, ""); - addot(OT_CORPSEOGRE, "ogre corpse", "The dead body of an ogre.", MT_FLESH, 100, OC_CORPSE); - addflag(lastot->flags, F_EDIBLE, B_TRUE, 90, NA, ""); - addot(OT_CORPSELIZARD, "lizard corpse", "The dead body of a lizard.", MT_FLESH, 1, OC_CORPSE); - addflag(lastot->flags, F_EDIBLE, B_TRUE, 20, NA, ""); - */ - addot(OT_CORPSE, "corpse", "xxx", MT_FLESH, 1, OC_CORPSE); addflag(lastot->flags, F_EDIBLE, B_TRUE, 1, NA, NULL); addot(OT_HEAD, "head", "xxx", MT_FLESH, 1, OC_CORPSE); addflag(lastot->flags, F_EDIBLE, B_TRUE, 1, NA, NULL); - addot(OT_FLESHCHUNK, "chunk of flesh", "A chunk of flesh from something.", MT_FLESH, 1, OC_FOOD); + addflag(lastot->flags, F_GLYPH, C_BROWN, NA, NA, "%"); addflag(lastot->flags, F_EDIBLE, B_TRUE, 5, NA, ""); @@ -4295,10 +4399,10 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL); addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "small puddle of water"); 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_RARITY, H_DUNGEON, 100, 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_RARITY, H_DUNGEON, 90, 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); @@ -4361,6 +4465,14 @@ void initobjects(void) { // scrolls + + 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, 100, NA, NULL); + + addot(OT_SCR_IDENTIFY, "scroll of identify", "Completely identifies any one item.", MT_PAPER, 0.5, OC_SCROLL); + addflag(lastot->flags, F_LINKSPELL, OT_S_IDENTIFY, NA, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, NULL); + addot(OT_SCR_NOTHING, "scroll of nothing", "Looks like a magic scroll, but doesn't do anything.", MT_PAPER, 0.5, OC_SCROLL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL); @@ -4370,7 +4482,7 @@ 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_LINKSPELL, OT_S_CREATEMONSTER, 4, 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); @@ -4409,10 +4521,6 @@ void initobjects(void) { addflag(lastot->flags, F_LINKSPELL, OT_S_FREEZEOB, NA, NA, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); - addot(OT_SCR_IDENTIFY, "scroll of identify", "Completely identifies any one item.", MT_PAPER, 0.5, OC_SCROLL); - addflag(lastot->flags, F_LINKSPELL, OT_S_IDENTIFY, NA, NA, NULL); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 85, NA, NULL); - addot(OT_SCR_KNOCK, "scroll of knock", "Magically opens a barrier.", MT_PAPER, 0.5, OC_SCROLL); addflag(lastot->flags, F_LINKSPELL, OT_S_KNOCK, NA, NA, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); @@ -4423,21 +4531,21 @@ void initobjects(void) { 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); + addflag(lastot->flags, F_LINKSPELL, OT_S_MAPPING, 4, NA, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); addot(OT_SCR_MINDSCAN, "scroll of mind scan", "Reveals detailed information about the target.", MT_PAPER, 0.5, OC_SCROLL); addflag(lastot->flags, F_LINKSPELL, OT_S_MINDSCAN, NA, NA, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); + addot(OT_SCR_PERMENANCE, "scroll of permenance", "Makes all effects on an object last forever.", MT_PAPER, 0.5, OC_SCROLL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); + addot(OT_SCR_TELEPORT, "scroll of 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_TELEPORT, NA, NA, NULL); + addflag(lastot->flags, F_LINKSPELL, OT_S_TELEPORT, 4, 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, 100, NA, NULL); - addot(OT_SCR_TURNUNDEAD, "scroll of turn undead", "Instills fear in undead creatures.", MT_PAPER, 0.5, OC_SCROLL); addflag(lastot->flags, F_LINKSPELL, OT_S_TURNUNDEAD, NA, NA, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); @@ -4490,6 +4598,10 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); + addot(OT_S_POISONBOLT, "poison bolt", "Fires a glob of venom at 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_AICASTTOATTACK, ST_VICTIM, 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); @@ -4500,6 +4612,10 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); + addot(OT_S_DRAINLIFE, "drain life", "Draws life force from the victim in order to heal the caster.", 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_AICASTTOATTACK, ST_VICTIM, 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); @@ -4509,8 +4625,12 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); + // l7 + addot(OT_S_POSSESSION, "possession", "Completely possess an enemy, moving your consciousness into their body.", MT_NOTHING, 0, OC_SPELL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 7, NA, NA, NULL); // l8 - addot(OT_S_INFINITEDEATH, "infinite death", "Annihilates all life on the caster's level!", MT_NOTHING, 0, OC_SPELL); + addot(OT_S_INFINITEDEATH, "infinite death", "Annihilates all nearby life, including the caster!", MT_NOTHING, 0, OC_SPELL); addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 8, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL); @@ -4595,6 +4715,11 @@ void initobjects(void) { 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); + // l3 + addot(OT_S_COLDBURST, "cold burst", "Creates a radial blast of coldness out from the caster.", MT_NOTHING, 0, OC_SPELL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_ICE, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJSELF, NA, NA, NULL); /////////////////// // gravity /////////////////// @@ -4795,6 +4920,8 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addot(OT_A_LEARN, "learn", "Learn new skills.", MT_NOTHING, 0, OC_ABILITY); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); + addot(OT_A_LEVELUP, "levelup", "Bestow the given xp level.", MT_NOTHING, 0, OC_ABILITY); + addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addot(OT_S_WISH, "wish", "Grants the caster any item of their choice (with some limitations).", MT_NOTHING, 0, OC_SPELL); addflag(lastot->flags, F_SPELLLEVEL, 9, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINE, NA, NA, NULL); @@ -4802,6 +4929,9 @@ 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_SWOOP, "swoop", "You can attack an enemy while flying past them.", MT_NOTHING, 0, OC_ABILITY); + addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); 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_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL); @@ -4894,10 +5024,14 @@ void initobjects(void) { // 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_DRAINLIFE, "spellbook of drain life", "Teaches the spell 'drain life'.", MT_PAPER, 1.5, OC_BOOK); + addflag(lastot->flags, F_LINKSPELL, OT_S_DRAINLIFE, 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_PARALYZE, "spellbook of paralyze", "Teaches the spell 'paralyze'.", MT_PAPER, 1.5, OC_BOOK); addflag(lastot->flags, F_LINKSPELL, OT_S_PARALYZE, NA, NA, NULL); + addot(OT_SB_POISONBOLT, "spellbook of poison bolt", "Teaches the spell 'poison bolt'.", MT_PAPER, 1.5, OC_BOOK); + addflag(lastot->flags, F_LINKSPELL, OT_S_POISONBOLT, 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); @@ -5138,6 +5272,18 @@ void initobjects(void) { addflag(lastot->flags, F_FLAMMABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_POWDER, B_TRUE, NA, NA, NULL); + addot(OT_LAMPOIL, "oil lamp", "An oil-powered lamp which produces light.", MT_METAL, 1, OC_TOOLS); + addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); + addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_OPERONOFF, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_ACTIVATECONFER, F_PRODUCESLIGHT, 2, NA, NULL); + addflag(lastot->flags, F_PRODUCESLIGHT, 2, NA, IFACTIVE, NULL); + addflag(lastot->flags, F_RNDCHARGES, 50, 100, NA, NULL); + addflag(lastot->flags, F_REFILLWITH, OT_POT_OIL, NA, NA, NULL); + addflag(lastot->flags, F_LIGHTSOURCE, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_CHARGELOWMSG, B_TRUE, NA, NA, "flickers"); + addflag(lastot->flags, F_CHARGEOUTMSG, B_TRUE, NA, NA, "goes out"); addot(OT_LANTERNOIL, "oil lantern", "An oil-powered lantern which produces a lot of light.", MT_METAL, 1, OC_TOOLS); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); @@ -5217,6 +5363,7 @@ void initobjects(void) { addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OPERONOFF, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_ACTIVATECONFER, F_PRODUCESLIGHT, 2, NA, NULL); + addflag(lastot->flags, F_PRODUCESLIGHT, 2, NA, IFACTIVE, NULL); addflag(lastot->flags, F_TECHLEVEL, PR_NOVICE, NA, NA, NULL); addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL); @@ -5383,7 +5530,7 @@ void initobjects(void) { addot(OT_VOMITPOOL, "pool of vomit", "A disgusting pool of regurgitated food.", MT_WATER, 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_GLYPH, C_GREEN, NA, NA, ","); addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_SLIPPERY, 1, NA, NA, NULL); addflag(lastot->flags, F_DRINKABLE, B_TRUE, 0, NA, NULL); @@ -5425,6 +5572,20 @@ void initobjects(void) { addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_EDIBLE, B_TRUE, 2, NA, NULL); + // this isn't made out of water, so that it won't put out fire etc + addot(OT_SPLASHWATER, "splash of water", "A small splash of water.", MT_NOTHING, 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_DIETEXT, NA, NA, NA, "evaporates"); + addflag(lastot->flags, F_OBHP, 5, 5, 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_DTVULN, DT_FIRE, NA, NA, "0d1+100"); + addflag(lastot->flags, F_LINKOB, OT_POT_WATER, NA, NA, NULL); + addot(OT_PUDDLEWATER, "small puddle of water", "A small puddle of water.", MT_WATER, 0, OC_MISC); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); @@ -5435,6 +5596,7 @@ void initobjects(void) { addflag(lastot->flags, F_DTCONVERT, DT_FIRE, NA, NA, "puff of steam"); addflag(lastot->flags, F_DRINKABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_LINKOB, OT_POT_WATER, NA, NA, NULL); + addflag(lastot->flags, F_WALKDAM, DT_WATER, NA, NA, "0d1+1"); 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); @@ -5446,12 +5608,13 @@ void initobjects(void) { addflag(lastot->flags, F_DTCONVERT, DT_FIRE, NA, NA, "cloud of steam"); addflag(lastot->flags, F_DRINKABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_LINKOB, OT_POT_WATER, NA, NA, NULL); + addflag(lastot->flags, F_WALKDAM, DT_WATER, NA, NA, "0d1+2"); 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_RARITY, H_DUNGEON, 60, NA, NULL); addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); addot(OT_BLOODCSPLASH, "splash of cockatrice blood", "A small pool of cockatrice blood.", MT_BLOOD, 0, OC_MISC); @@ -5481,7 +5644,6 @@ void initobjects(void) { 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); - addflag(lastot->flags, F_DRINKABLE, B_TRUE, 0, NA, NULL); addflag(lastot->flags, F_LINKOB, OT_POT_BLOOD, NA, NA, NULL); @@ -5510,7 +5672,7 @@ void initobjects(void) { addflag(lastot->flags, F_NOPICKUP, 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, 3, 6, NA, NULL); + addflag(lastot->flags, F_OBHP, 6, 6, NA, NULL); addot(OT_WOODENSTOOL, "wooden footstool", "A small, wooden footstool.", MT_WOOD, 5, OC_MISC); addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, NULL); @@ -5528,7 +5690,7 @@ void initobjects(void) { // effects addot(OT_FIRELARGE, "large fire", "A large, roaring inferno.", MT_FIRE, 0, OC_EFFECT); - addflag(lastot->flags, F_GLYPH, NA, NA, NA, "}"); + addflag(lastot->flags, F_GLYPH, C_ORANGE, NA, NA, "}"); addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DIECONVERTTEXT, NA, NA, NA, "dies down a little"); addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "medium fire"); @@ -5539,7 +5701,7 @@ void initobjects(void) { addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_PRODUCESLIGHT, 3, NA, NA, NULL); addot(OT_FIREMED, "medium fire", "A medium-sized roaring fire.", MT_FIRE, 0, OC_EFFECT); - addflag(lastot->flags, F_GLYPH, NA, NA, NA, "}"); + addflag(lastot->flags, F_GLYPH, C_RED, NA, NA, "}"); addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "small fire"); addflag(lastot->flags, F_DIECONVERTTEXT, NA, NA, NA, "dies down a little"); @@ -5550,7 +5712,7 @@ void initobjects(void) { addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_PRODUCESLIGHT, 2, NA, NA, NULL); addot(OT_FIRESMALL, "small fire", "A small blaze.", MT_FIRE, 0, OC_EFFECT); - addflag(lastot->flags, F_GLYPH, NA, NA, NA, "}"); + addflag(lastot->flags, F_GLYPH, C_RED, NA, NA, "}"); addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DIETEXT, B_TRUE, NA, NA, "goes out"); addflag(lastot->flags, F_OBHP, 3, 3, NA, NULL); @@ -5878,12 +6040,27 @@ void initobjects(void) { addflag(lastot->flags, F_OBHP, 30, 30, NA, NULL); // rings + addot(OT_RING_SEEINVIS, "ring of sight", "Allows the caster to see the invisible, and in the dark.", MT_METAL, 0.1, OC_RING); + addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, ""); + addflag(lastot->flags, F_EQUIPCONFER, F_SEEINVIS, NA, NA, NULL); + addflag(lastot->flags, F_EQUIPCONFER, F_SEEINDARK, 5, NA, NULL); + addflag(lastot->flags, F_EQUIPCONFER, F_VISRANGEMOD, 1, NA, NULL); + addot(OT_RING_LUCK, "ring of luck", "Makes the wearer more lucky.", MT_METAL, 0.1, OC_RING); + addflag(lastot->flags, F_RARITY, H_ALL, 70, NA, ""); + addflag(lastot->flags, F_EQUIPCONFER, F_EXTRALUCK, 5, NA, NULL); + addot(OT_RING_MANA, "ring of mana", "Increases the wearer's MP pool.", MT_METAL, 0.1, OC_RING); + addflag(lastot->flags, F_RARITY, H_ALL, 65, NA, ""); + addflag(lastot->flags, F_EQUIPCONFER, F_EXTRAMP, 10, NA, NULL); + addot(OT_RING_WOUNDING, "ring of wounding", "Increases the damage output of the wearer.", MT_METAL, 0.1, OC_RING); + addflag(lastot->flags, F_RARITY, H_ALL, 65, NA, ""); + addflag(lastot->flags, F_EQUIPCONFER, F_EXTRADAM, NA, NA, "0d0+4"); + addflag(lastot->flags, F_ENCHANTABLE, B_TRUE, NA, NA, NULL); addot(OT_RING_INVIS, "ring of invisibility", "Renders the wearer invisible.", MT_METAL, 0.1, OC_RING); addflag(lastot->flags, F_RARITY, H_ALL, 60, NA, ""); addflag(lastot->flags, F_EQUIPCONFER, F_INVISIBLE, NA, NA, NULL); addot(OT_RING_INVULN, "ring of invulnerability", "Grants the caster complete immunity to physical harm.", MT_METAL, 0.1, OC_RING); addflag(lastot->flags, F_EQUIPCONFER, F_INVULNERABLE, NA, NA, NULL); - addot(OT_RING_MPREGEN, "ring of mana", "Slowly regenerates the wearer's mana.", MT_METAL, 0.1, OC_RING); + addot(OT_RING_MPREGEN, "ring of recharging", "Slowly regenerates the wearer's mana.", MT_METAL, 0.1, OC_RING); addflag(lastot->flags, F_RARITY, H_ALL, 50, NA, ""); addflag(lastot->flags, F_EQUIPCONFER, F_MPREGEN, 1, NA, NULL); addot(OT_RING_PROTFIRE, "ring of fire immunity", "Grants the caster complete immunity to fire.", MT_METAL, 0.1, OC_RING); @@ -5893,13 +6070,8 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_ALL, 50, NA, ""); addflag(lastot->flags, F_EQUIPCONFER, F_REGENERATES, 1, NA, NULL); addot(OT_RING_RESISTMAG, "ring of magic resistance", "Renders the wearer immune to most magical effects.", MT_METAL, 0.1, OC_RING); - addflag(lastot->flags, F_RARITY, H_ALL, 25, NA, ""); + addflag(lastot->flags, F_RARITY, H_ALL, 50, NA, ""); addflag(lastot->flags, F_EQUIPCONFER, F_RESISTMAG, 5, NA, NULL); - addot(OT_RING_SEEINVIS, "ring of sight", "Allows the caster to see the invisible, and in the dark.", MT_METAL, 0.1, OC_RING); - addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, ""); - addflag(lastot->flags, F_EQUIPCONFER, F_SEEINVIS, NA, NA, NULL); - addflag(lastot->flags, F_EQUIPCONFER, F_SEEINDARK, 5, NA, NULL); - addflag(lastot->flags, F_EQUIPCONFER, F_VISRANGEMOD, 1, NA, NULL); // unarmed weapons - note these damage/accuracys can be // overridded with the lifeform flag F_HASATTACK @@ -6002,7 +6174,7 @@ void initobjects(void) { 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_RARITY, H_DUNGEON, 85, 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); @@ -6012,7 +6184,7 @@ void initobjects(void) { 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_NUMAPPEAR, 1, 10, NA, ""); addflag(lastot->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_CANHAVEOBMOD, OM_POISONED, NA, NA, NULL); @@ -6061,12 +6233,14 @@ void initobjects(void) { addflag(lastot->flags, F_DAM, 1, 6, NA, NULL); addflag(lastot->flags, F_ACCURACY, 90, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_SHORTBLADES, NA, NA, NULL); + addflag(lastot->flags, F_ATTREQ, A_STR, ST_VWEAK, NA, NULL); addot(OT_RAPIER, "rapier", "A long, narrow French sword lacking a cutting edge. Made for stabbing.", MT_METAL, 2.5, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); addflag(lastot->flags, F_DAMTYPE, DT_PIERCE, NA, NA, NULL); addflag(lastot->flags, F_DAM, 1, 8, NA, NULL); addflag(lastot->flags, F_ACCURACY, 90, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_SHORTBLADES, NA, NA, NULL); + addflag(lastot->flags, F_ATTREQ, A_STR, ST_VWEAK, NA, NULL); addot(OT_TRIDENT, "trident", "A three-pronged stabbing weapon.", MT_METAL, 3, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 110, NA, NA, NULL); @@ -6074,6 +6248,7 @@ 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_USESSKILL, SK_POLEARMS, NA, NA, NULL); + addflag(lastot->flags, F_ATTREQ, A_STR, ST_WEAK, NA, NULL); addot(OT_QUICKBLADE, "quickblade", "A short blade of exceptional quality, which somehow allows its bearer to attack faster.", MT_METAL, 1, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 35, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 90, NA, NA, NULL); @@ -6097,9 +6272,10 @@ void initobjects(void) { 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_DAM, 1, 6, 1, NULL); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_AXES, NA, NA, NULL); + addflag(lastot->flags, F_ATTREQ, A_STR, ST_AVERAGE, NA, NULL); 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); @@ -6108,6 +6284,7 @@ void initobjects(void) { addflag(lastot->flags, F_ACCURACY, 85, NA, NA, NULL); addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_AXES, NA, NA, NULL); + addflag(lastot->flags, F_ATTREQ, A_STR, ST_WEAK, 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); @@ -6116,6 +6293,7 @@ void initobjects(void) { addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_AXES, NA, NA, NULL); + addflag(lastot->flags, F_ATTREQ, A_STR, ST_STRONG, NA, NULL); 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); @@ -6124,6 +6302,7 @@ void initobjects(void) { addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_ACCURACY, 70, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_AXES, NA, NA, NULL); + addflag(lastot->flags, F_ATTREQ, A_STR, ST_MIGHTY, NA, NULL); // slashing weapons addot(OT_KNIFE, "knife", "A moderately sharp stabbing tool.", MT_METAL, 1, OC_WEAPON); @@ -6152,6 +6331,7 @@ void initobjects(void) { addflag(lastot->flags, F_DAM, 2, 4, NA, NULL); addflag(lastot->flags, F_ACCURACY, 65, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_POLEARMS, NA, NA, NULL); + addflag(lastot->flags, F_ATTREQ, A_STR, ST_AVERAGE, NA, NULL); addot(OT_SICKLE, "sickle", "A hand-held agricultural tool with a curved blade.", MT_METAL, 0.5, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL); addflag(lastot->flags, F_DAMTYPE, DT_SLASH, NA, NA, NULL); @@ -6165,6 +6345,7 @@ void initobjects(void) { addflag(lastot->flags, F_DAM, 1, 8, 2, NULL); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_LONGBLADES, NA, NA, NULL); + addflag(lastot->flags, F_ATTREQ, A_STR, ST_WEAK, NA, NULL); addot(OT_LONGSWORD, "longsword", "Standard issue long slashing weapon.", MT_METAL, 3, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 130, NA, NA, NULL); @@ -6172,6 +6353,7 @@ void initobjects(void) { addflag(lastot->flags, F_DAM, 1, 8, 3, NULL); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_LONGBLADES, NA, NA, NULL); + addflag(lastot->flags, F_ATTREQ, A_STR, ST_AVERAGE, NA, NULL); addot(OT_ORNSWORD, "ornamental sword", "A gleaming (but quite blunt) blade.", MT_METAL, 2, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); addflag(lastot->flags, F_SHINY, B_TRUE, NA, NA, NULL); @@ -6188,6 +6370,7 @@ void initobjects(void) { addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_LONGBLADES, NA, NA, NULL); + addflag(lastot->flags, F_ATTREQ, A_STR, ST_STRONG, NA, NULL); // polearms addot(OT_QUARTERSTAFF, "quarterstaff", "A long, stout pole.", MT_WOOD, 2, OC_WEAPON); @@ -6198,6 +6381,7 @@ void initobjects(void) { addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_STAVES, NA, NA, NULL); + addflag(lastot->flags, F_ATTREQ, A_STR, ST_VWEAK, NA, NULL); addot(OT_SPEAR, "spear", "A long pole with a sharpened head.", MT_METAL, 4, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 140, NA, NA, NULL); @@ -6208,6 +6392,7 @@ void initobjects(void) { addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OBHP, 15, 15, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_POLEARMS, NA, NA, NULL); + addflag(lastot->flags, F_ATTREQ, A_STR, ST_WEAK, NA, NULL); // bashing weapons addot(OT_STICK, "stick", "A sturdy wooden stick.", MT_WOOD, 0.5, OC_WEAPON); @@ -6233,6 +6418,7 @@ void initobjects(void) { addflag(lastot->flags, F_DAM, 1, 6, NA, NULL); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_CLUBS, NA, NA, NULL); + addflag(lastot->flags, F_ATTREQ, A_STR, ST_WEAK, NA, NULL); addot(OT_MACE, "mace", "A weapon with a heavy head on a solid shaft used to bludgeon opponents.", MT_METAL, 3, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 140, NA, NA, NULL); @@ -6240,6 +6426,7 @@ void initobjects(void) { addflag(lastot->flags, F_DAM, 1, 8, NA, NULL); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_CLUBS, NA, NA, NULL); + addflag(lastot->flags, F_ATTREQ, A_STR, ST_AVERAGE, 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); @@ -6247,6 +6434,7 @@ void initobjects(void) { addflag(lastot->flags, F_DAM, 2, 4, NA, NULL); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_CLUBS, NA, NA, NULL); + addflag(lastot->flags, F_ATTREQ, A_STR, ST_AVERAGE, 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); @@ -6254,6 +6442,7 @@ void initobjects(void) { addflag(lastot->flags, F_DAM, 2, 6, NA, NULL); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_CLUBS, NA, NA, NULL); + addflag(lastot->flags, F_ATTREQ, A_STR, ST_STRONG, 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); @@ -6262,6 +6451,7 @@ void initobjects(void) { addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_CLUBS, NA, NA, NULL); + addflag(lastot->flags, F_ATTREQ, A_STR, ST_STRONG, NA, NULL); 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); @@ -6270,6 +6460,7 @@ void initobjects(void) { addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_CLUBS, NA, NA, NULL); + addflag(lastot->flags, F_ATTREQ, A_STR, ST_MIGHTY, NA, NULL); // projectile weapons addot(OT_SLING, "sling", "Stretchy piece of rubber for launching projectiles.", MT_RUBBER, 0.5, OC_WEAPON); @@ -6289,6 +6480,7 @@ void initobjects(void) { 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); + addflag(lastot->flags, F_ATTREQ, A_STR, ST_AVERAGE, 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); @@ -6298,15 +6490,26 @@ void initobjects(void) { 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); + addflag(lastot->flags, F_ATTREQ, A_STR, ST_STRONG, 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); + addot(OT_CROSSBOWHAND, "hand crossbow", "A small one-handed crossbow. Lightweight, but less powerful 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, 75, NA, NA, NULL); + addflag(lastot->flags, F_RANGE, 10, NA, NA, NULL); + addflag(lastot->flags, F_AMMOOB, OT_BOLT, NA, NA, NULL); + + addot(OT_CROSSBOW, "crossbow", "A standard crossbow. Very powerful, but needs high strength to use.", MT_WOOD, 5, 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, 9, 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); + addflag(lastot->flags, F_ATTREQ, A_STR, ST_STRONG, 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); @@ -6542,6 +6745,9 @@ int isfirearm(object_t *o) { } int isflammable(object_t *o) { + if (hasflag(o->flags, F_WET)) { + return B_FALSE; + } if (hasflag(o->flags, F_FLAMMABLE)) { return B_TRUE; } @@ -7012,6 +7218,74 @@ void makeknown(enum OBTYPE otid) { } } +void makewet(object_t *o, int amt) { + cell_t *loc; + lifeform_t *owner; + char ownername[BUFLEN]; + char obname[BUFLEN]; + char obnamefull[BUFLEN]; + flag_t *f; + + loc = getoblocation(o); + owner = o->pile->owner; + if (owner) { + getlfname(owner, ownername); + } + getobname(o,obname,o->amt); + + if (owner) { + sprintf(obnamefull, "%s%s %s",ownername, getpossessive(ownername), noprefix(obname)); + } else { + strcpy(obnamefull, obname); + } + + if (o->material->id == MT_METAL) { + if (amt < R_RUSTY) amt = R_RUSTY; + if (amt > R_TRUSTY) amt = R_TRUSTY; + f = hasflag(o->flags, F_RUSTED); + if (f) { + if (f->val[0] < R_TRUSTY) { + // make more rusty + f->val[0] += amt; + } + } else { + // rust + if (haslos(player, loc)) { + msg("%s rust%s.",obnamefull, (o->amt == 1) ? "s" : ""); + } + f = addflag(o->flags, F_RUSTED, amt, NA, NA, NULL); + } + } else { + if (hasflag(o->flags, F_CANGETWET)) { + if (amt < W_DAMP) amt = W_DAMP; + if (amt > W_SOAKED) amt = W_SOAKED; + f = hasflag(o->flags, F_WET); + if (f) { + if (f->val[0] < W_SOAKED) { + // make wetter + /* + if (haslos(player, loc)) { + msg("%s get%s wetter.",obnamefull, (o->amt == 1) ? "s" : ""); + } + */ + f->val[0] += amt; + f->val[1] = WETTIME; + } else { + // jsut reset wettime + f->val[1] = WETTIME; + } + } else { + + // get wet + if (haslos(player, loc)) { + msg("%s get%s wet.",obnamefull, (o->amt == 1) ? "s" : ""); + } + f = addflag(o->flags, F_WET, amt, WETTIME, NA, NULL); + } + } + } +} + object_t *moveob(object_t *src, obpile_t *dst, int howmany) { object_t *o, *existob; int i; @@ -7418,6 +7692,11 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { flag_t *f; int willid = B_FALSE; + if (!lfhasflag(lf, F_HUMANOID) || !hasbp(lf, BP_HANDS)) { + // only humanoids can zap things + return B_TRUE; + } + getobname(o, obname, 1); if ((lf->controller == C_PLAYER) || cansee(player, lf)) { @@ -7576,23 +7855,28 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { f = hasflag(o->flags, F_LINKSPELL); if (f) { - int isblessed; + enum OBTYPE spelltocast; int power; - isblessed = o->blessed; + + spelltocast = f->val[0]; power = f->val[1]; + if (power == NA) power = 1; - if (isblessed) power += 4; + if (isblessed(o)) power += 4; // certain wands always used the blessed version of spells + // certain wands have different effects when cursed switch (o->type->id) { case OT_WAND_LIGHT: - isblessed = B_TRUE; + if (iscursed(o)) { + spelltocast = OT_S_DARKNESS; + } break; default: break; } - dospelleffects(lf, f->val[0], power, where ? where->lf : NULL, NULL, where, isblessed, &willid); + dospelleffects(lf, spelltocast, power, where ? where->lf : NULL, NULL, where, isblessed(o), &willid); // special wands } else if (o->type->id == OT_WAND_WONDER) { int power; @@ -7636,8 +7920,11 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { if (isplayer(lf) || cansee(player, lf)) { // tell player makeknown(o->type->id); + if (iscursed(o)) { + o->blessknown = B_TRUE; + } if (isplayer(lf)) { - getobname(o, obname, 1); + real_getobname(o, obname, 1, B_FALSE, B_TRUE, B_FALSE, B_FALSE); // don't adjust for blindness msg("This is %s!",obname); } } @@ -7692,8 +7979,13 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { int dippable = B_FALSE; nextoo = oo->next; switch (oo->type->id) { - case OT_BLOODPOOL: case OT_BLOODSPLASH: + case OT_SPLASHWATER: + if (oo->amt >= 5) { + dippable = B_TRUE; + } + break; + case OT_BLOODPOOL: case OT_PUDDLEWATER: case OT_PUDDLEWATERL: dippable = B_TRUE; @@ -7734,8 +8026,11 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { } // kill the ground object? switch (oo->id) { - case OT_PUDDLEWATER: + case OT_SPLASHWATER: case OT_BLOODSPLASH: + removeob(oo, 5); + break; + case OT_PUDDLEWATER: removeob(oo, 1); break; } @@ -8326,7 +8621,7 @@ void quaff(lifeform_t *lf, object_t *o) { } -void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE isblessed, int *seen) { +void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE potblessed, int *seen) { char buf[BUFLEN]; unsigned int dam; int i; @@ -8369,7 +8664,7 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE isblessed, in } // how long for? - i = geteffecttime(5,10, isblessed); + i = geteffecttime(5,10, potblessed); if (lfhasflagval(lf, F_CANWILL, OT_A_JUMP, NA, NA, NULL)) { nothinghappens(); @@ -8404,17 +8699,17 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE isblessed, in failed = B_TRUE; if (getmr(lf) && skillcheck(lf, SC_RESISTMAG, 30, 0)) { if (isplayer(lf)) { - msg("You feel momentarily %s.", (isblessed == B_CURSED) ? "incompetent" : "more competent"); + msg("You feel momentarily %s.", (potblessed == B_CURSED) ? "incompetent" : "more competent"); } break; } - if (isblessed == B_CURSED) { + if (potblessed == B_CURSED) { amt = -1; } else { amt = 1; } // select a random attribute - if (isblessed == B_BLESSED) { + if (potblessed == B_BLESSED) { // modify all attributes if (!modattr(lf, A_STR, amt)) failed = B_FALSE; if (!modattr(lf, A_DEX, amt)) failed = B_FALSE; @@ -8451,7 +8746,7 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE isblessed, in break; } // how long for? - i = geteffecttime(15,25,isblessed); + i = geteffecttime(15,25,potblessed); if (!lfhasflagval(lf, F_DTRESIST, DT_FIRE, NA, NA, NULL)) { addtempflag(lf->flags, F_DTRESIST, DT_FIRE, NA, NA, NULL, i); @@ -8468,7 +8763,7 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE isblessed, in break; } // how long for? - i = geteffecttime(15,25,isblessed); + i = geteffecttime(15,25,potblessed); if (!isimmuneto(lf->flags, DT_FIRE)) { addtempflag(lf->flags, F_DTIMMUNE, DT_FIRE, NA, NA, NULL, i); @@ -8478,7 +8773,7 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE isblessed, in } break; case OT_POT_ETHEREALNESS: - dospelleffects(lf, OT_S_PASSWALL, (isblessed) ? 5 : 1, lf, NULL, NULL, isblessed, seen); + dospelleffects(lf, OT_S_PASSWALL, (potblessed) ? 5 : 1, lf, NULL, NULL, potblessed, seen); break; case OT_POT_EXPERIENCE: // gain xp! @@ -8494,16 +8789,16 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE isblessed, in gainxp(lf, getxpforlev(lf->level+1) - lf->xp); break; case OT_POT_GASEOUSFORM: - dospelleffects(lf, OT_S_GASEOUSFORM, (isblessed) ? 5 : 1, lf, NULL, NULL, isblessed, seen); + dospelleffects(lf, OT_S_GASEOUSFORM, (potblessed) ? 5 : 1, lf, NULL, NULL, potblessed, seen); break; case OT_POT_HEALING: - dospelleffects(lf, OT_S_HEALING,isblessed ? 5 : 1, lf, NULL, NULL, isblessed, seen); + dospelleffects(lf, OT_S_HEALING,potblessed ? 5 : 1, lf, NULL, NULL, potblessed, seen); break; case OT_POT_HEALINGMIN: - dospelleffects(lf, OT_S_HEALINGMIN,isblessed ? 5 : 1, lf, NULL, NULL, isblessed, seen); + dospelleffects(lf, OT_S_HEALINGMIN,potblessed ? 5 : 1, lf, NULL, NULL, potblessed, seen); break; case OT_POT_INVIS: - dospelleffects(lf, OT_S_INVISIBILITY,isblessed ? 6 : 3, lf, NULL, NULL, isblessed, seen); + dospelleffects(lf, OT_S_INVISIBILITY,potblessed ? 6 : 3, lf, NULL, NULL, potblessed, seen); break; case OT_POT_INVULN: if (getmr(lf) && skillcheck(lf, SC_RESISTMAG, 30, 0)) { @@ -8512,7 +8807,7 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE isblessed, in } break; } - i = geteffecttime(5,15,isblessed); + i = geteffecttime(5,15,potblessed); if (!lfhasflagval(lf, F_INVULNERABLE, B_TRUE, NA, NA, NULL)) { addtempflag(lf->flags, F_INVULNERABLE, B_TRUE, NA, NA, NULL, i); @@ -8549,12 +8844,12 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE isblessed, in } break; case OT_POT_POLYMORPH: - if (isblessed == B_BLESSED) { + if (potblessed == B_BLESSED) { // controlled polymorph - dospelleffects(lf, OT_S_POLYMORPH, 5, lf, NULL, NULL, isblessed, NULL); + dospelleffects(lf, OT_S_POLYMORPH, 5, lf, NULL, NULL, potblessed, NULL); } else { // random polymorph - dospelleffects(lf, OT_S_POLYMORPH, 1, lf, NULL, NULL, isblessed, NULL); + dospelleffects(lf, OT_S_POLYMORPH, 1, lf, NULL, NULL, potblessed, NULL); } break; case OT_POT_RESTORATION: @@ -8615,9 +8910,9 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE isblessed, in } break; case OT_POT_SPEED: - if (isblessed == B_BLESSED) { + if (potblessed == B_BLESSED) { dospelleffects(lf, OT_S_HASTE, 1, lf, NULL, lf->cell, B_BLESSED, NULL); - } else if (isblessed == B_CURSED) { + } else if (potblessed == B_CURSED) { dospelleffects(lf, OT_S_SLOW, 1, lf, NULL, lf->cell, B_UNCURSED, NULL); } else { // uncursed dospelleffects(lf, OT_S_HASTE, 1, lf, NULL, lf->cell, B_UNCURSED, NULL); @@ -8626,7 +8921,7 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE isblessed, in break; case OT_POT_WATER: - switch (isblessed) { + switch (potblessed) { case B_BLESSED: if (hasflag(lf->flags, F_UNDEAD)) { if (isplayer(lf)) { @@ -8667,7 +8962,7 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE isblessed, in break; case OT_POT_JUICE: if (isplayer(lf)) { - switch (isblessed) { + switch (potblessed) { case B_BLESSED: msg("Mmm, fruit juice!"); break; @@ -8680,7 +8975,7 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE isblessed, in } if (seen) *seen = B_TRUE; } - if (isblessed != B_CURSED) { + if (potblessed != B_CURSED) { modhunger(lf, -pctof(10, (float)HUNGERCONST)); } break; @@ -8839,6 +9134,29 @@ int readsomething(lifeform_t *lf, object_t *o) { } // removeob one of the object removeob(o, 1); + } else if (o->type->id == OT_SCR_PERMENANCE) { + if (isplayer(lf)) { + targob = askobject(lf->pack, "Target which object", NULL, AO_NONE); + } + + if (targob) { + flag_t *f; + for (f = targob->flags->first ; f ; f = f->next) { + f->lifetime = PERMENANT; + } + if (isplayer(lf)) { + char obname[BUFLEN]; + getobname(targob, obname, targob->amt); + msg("Your %s emit%s a blinding burst of power!",noprefix(obname), (targob->amt == 1) ? "s" : ""); + } + } + + if (isplayer(lf)) { + msg("The scroll crumbles to dust."); + } + // removeob one of the object + removeob(o, 1); + } else if (o->type->id == OT_SCR_REMOVECURSE) { int seen = B_FALSE; object_t *oo; @@ -9131,6 +9449,7 @@ int takedamage(object_t *o, unsigned int howmuch, int damtype) { // water puts out fire if (damtype == DT_WATER) { extinguish(o); + makewet(o, howmuch); } // catches on fire? @@ -9503,7 +9822,9 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed, // do throw animation if (seen) { - anim(srcloc, where, getglyph(o)); + glyph_t *gl; + gl = getglyph(o); + anim(srcloc, where, gl->ch, gl->colour); } // find out your chances of hitting @@ -9780,7 +10101,7 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed, // heavy ob? if (youhit && target) { - if (getobweight(o) >= getlfweight(target, B_NOOBS)) { + if ((getobunitweight(o)*amt) >= getlfweight(target, B_NOOBS)) { int dir; dir = getdirtowards(srcloc, target->cell, target, B_FALSE, DT_COMPASS); knockback(target, dir, 1, thrower); @@ -10049,8 +10370,6 @@ void timeeffectsob(object_t *o) { if (hasflag(o->flags, F_DEAD)) return; } - - // will current object convert other obs to something else? if ((f->id == F_MATCONVERT) && !hasflag(o->flags, F_NOMATCONVERT)) { enum MATERIAL mat; @@ -10111,6 +10430,15 @@ void timeeffectsob(object_t *o) { } } + if (f->id == F_WET) { + if (isequipped(o) || !o->pile->owner) { + cell_t *ourcell; + object_t *splash; + ourcell = getoblocation(o); + // drip + splash = addob(ourcell->obpile, "splash of water"); + } + } } // end for each object flag } @@ -10246,6 +10574,15 @@ int validateobs(void) { int goterror = B_FALSE; flag_t *f; for (ot = objecttype ; ot ; ot = ot->next) { + + // fix up glyphs + f = hasflag(ot->flags, F_GLYPH); + if (f) { + if (f->val[0] == NA) { + f->val[0] = getmaterialcolour(ot->material->id); + } + } + if ((ot->obclass->id == OC_SPELL) || (ot->obclass->id == OC_ABILITY)) { if (!foundspells) foundspells = B_TRUE; if (!hasflag(ot->flags, F_SPELLSCHOOL)) { @@ -10357,6 +10694,40 @@ objecttype_t *getlinkspell(object_t *o) { return spelltype; } +enum COLOUR getmaterialcolour(enum MATERIAL mat) { + enum COLOUR col; + switch (mat) { + case MT_WOOD: + case MT_LEATHER: + col = C_BROWN; + break; + case MT_FIRE: + case MT_BLOOD: + col = C_RED; + break; + case MT_GLASS: + case MT_MAGIC: + col = C_CYAN; + break; + case MT_ICE: + col = C_WHITE; + break; + case MT_GOLD: + col = C_YELLOW; + break; + case MT_WATER: + col = C_BLUE; + break; + case MT_SLIME: + case MT_ACID: + col = C_GREEN; + break; + default: + col = C_GREY; + } + return col; +} + // is the given material solid or liquid? enum MATSTATE getmaterialstate(enum MATERIAL mat) { switch (mat) { diff --git a/objects.h b/objects.h index b17d84a..5cb98c1 100644 --- a/objects.h +++ b/objects.h @@ -7,7 +7,7 @@ object_t *addemptyob(obpile_t *where, object_t *o); hiddenname_t *addhiddenname(enum OBCLASS obclass, char *text); knowledge_t *addknowledge(enum OBCLASS id, char *hiddenname, int known); material_t *addmaterial(enum MATERIAL id, char *name, float weightrating); -objectclass_t *addoc(enum OBCLASS id, char *name, char *desc, char glyph); +objectclass_t *addoc(enum OBCLASS id, char *name, char *desc, char glyph, int glyphcolour); 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, lifeform_t *fromlf); @@ -26,6 +26,7 @@ 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 colourmatchob(object_t *o, lifeform_t *lf); void copyobprops(object_t *dst, object_t *src); int countnames(char **list); int countobs(obpile_t *op); @@ -47,6 +48,7 @@ void genhiddennames(void); int getcharges(object_t *o); int geteffecttime(int min, int max, enum BLESSTYPE isblessed); objecttype_t *getlinkspell(object_t *o); +enum COLOUR getmaterialcolour(enum MATERIAL mat ); enum MATSTATE getmaterialstate(enum MATERIAL mat); int getmissileaccuracy(lifeform_t *thrower, cell_t *where, object_t *missile, object_t *firearm, enum ATTRIB whichatt); int getobaccuracy(object_t *wep, lifeform_t *weilder); @@ -62,7 +64,7 @@ char *getdamnamenoun(enum DAMTYPE damtype); char *getfillingname(int nutrition); int getfirearmrange(object_t *o); int getfirearmspeed(object_t *o); -char getglyph(object_t *o); +glyph_t *getglyph(object_t *o); char *genhiddenname(enum OBCLASS id); char *gethiddenname(object_t *o); int getobattackdelay(object_t *o); @@ -146,6 +148,7 @@ int knockbackob(object_t *o, int dir, int howfar, int power, lifeform_t *pusher) lifeform_t *makeanimated(lifeform_t *lf, object_t *o, int level); void makeduller(object_t *o, int howmuch); void makeknown(enum OBTYPE otid); +void makewet(object_t *o, int amt); object_t *moveob(object_t *src, obpile_t *dst, int howmany); void modbonus(object_t *o, int amt); //object_t *newobeffects(object_t *o); @@ -161,7 +164,7 @@ int obpropsmatch(object_t *a, object_t *b); int obotpropsmatch(object_t *a, objecttype_t *b); int operate(lifeform_t *lf, object_t *o, cell_t *where); int pilehasletter(obpile_t *op, char let); -void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE isblessed, int *seen); +void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE potlessed, int *seen); int pour(lifeform_t *lf, object_t *o); void quaff(lifeform_t *lf, object_t *o); int readsomething(lifeform_t *lf, object_t *o); diff --git a/spell.c b/spell.c index cf78890..670d840 100644 --- a/spell.c +++ b/spell.c @@ -73,7 +73,104 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef } - if (abilid == OT_A_GRAB) { + if (abilid == OT_A_SWOOP) { + cell_t *adjcell = NULL,*origcell; + char targetname[BUFLEN]; + int i; + cell_t *retcell[MAXRETCELLS]; + int nretcell; + int srange = 5; + flag_t *srflag; + + // get max range + srflag = lfhasflag(user, F_SWOOPRANGE); + if (srflag) { + srange = srflag->val[0]; + } + + if (isimmobile(user)) { + if (isplayer(user)) msg("You can't move!"); + return B_TRUE; + } else if (!lfhasflag(user, F_FLYING)) { + if (isplayer(user)) msg("You are not flying, therefore cannot swoop."); + return B_TRUE; + } + + if (!targcell) { + if (isplayer(user)) { + sprintf(buf, "Flyby who (max range %d)?",srange); + // TODO: ask for direction + targcell = askcoords("Flyby who?", TT_MONSTER); + if (!targcell) { + msg("Cancelled."); + return TRUE; + } + } else { + return B_FALSE; + } + + } + if (getcelldist(user->cell, targcell) > srange) { + if (isplayer(user)) msg("You can't swoop that far!"); + return B_TRUE; + } + + // make sure we have LOF to there + target = targcell->lf; + if (!target) { + if (isplayer(user)) msg("There is nobody there!"); + return TRUE; + } else if (!haslof(user, targcell, LOF_NEED, NULL)) { + if (isplayer(user)) msg("Your path there is blocked!"); + return TRUE; + } + + getlfname(target, targetname); + + // find cell on the way... + calcbresnham(user->cell->map, user->cell->x, user->cell->y, targcell->x, targcell->y, retcell, &nretcell); + for (i = 1; i < nretcell; i++) { + if (retcell[i] == targcell) { + adjcell = retcell[i-1]; + break; + } + } + if (!adjcell) { + if (isplayer(user)) { + msg("There is no space nearby for you to attack!"); + } + return B_TRUE; + } + + // take some time + taketime(user, getactspeed(user)); + + // remember orig cell + origcell = user->cell; + + // teleport next to them + movelf(user, adjcell); + if (haslos(player, adjcell)) { + msg("%s swoop%s towards %s!",username,isplayer(user) ? "" : "s",targetname); + needredraw = B_TRUE; + drawlevelfor(player); + redraw(); + + //if (!isplayer(user)) { + more(); + //} + } + + // attack + attackcell(user, targcell); + + + // teleport back to initial pos + movelf(user, origcell); + if (haslos(player, origcell)) { + redraw(); + } + } else if (abilid == OT_A_GRAB) { char dirch; flag_t *f; @@ -286,17 +383,28 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef } else if (abilid == OT_A_SPRINT) { int howlong; int slev; + flag_t *f; + + f = lfhasflag(user, F_SPRINTING); + if (f) { + if (f->val[0]) { + if (isplayer(user)) { + msg("You are already sprinting!"); + } + } else { + if (isplayer(user)) { + msg("You are too tired to sprint right now."); + } + } + return B_TRUE; + } if (lfhasflag(user, F_TIRED)) { if (isplayer(user)) { 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; } + howlong = 5; // +2 for each athletics skill level slev = getskill(user, SK_ATHLETICS); @@ -306,7 +414,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef // modify for constitution howlong = modifybystat(howlong, user, A_CON); - if (howlong <= 1) { + if (howlong <= 0) { if (isplayer(user)) { msg("You are too unfit to sprint."); } @@ -357,6 +465,20 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef msg("Cancelled."); } return B_FALSE; + } else if (abilid == OT_A_LEVELUP) { + char buf[BUFLEN]; + int lev; + + askstring("Which xp level will you attain", '?', buf, BUFLEN, NULL); + lev = atoi(buf); + if (lev <= user->level) { + msg("Cancelled."); + } else { + while (user->level < lev) { + gainlevel(user); + } + } + return B_FALSE; } else if (abilid == OT_A_DEBUG) { cell_t *where; where = askcoords("Debug who?", TT_MONSTER); @@ -595,17 +717,6 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ // reverse some spells if cursed - - if (blessed == B_CURSED) { - switch (spellid) { - case OT_S_LIGHT: - spellid = OT_S_DARKNESS; - break; - default: - break; - } - } - if (hasflag(sp->flags, F_ONGOING)) { if (lfhasflagval(caster, F_BOOSTSPELL, spellid, NA, NA, NULL)) { // cancel it. @@ -938,12 +1049,41 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ addtempflag(target->flags, F_CHARMEDBY, caster->id, NA, NA, NULL, howlong); } + } else if (spellid == OT_S_COLDBURST) { + int range = 1; + int x,y; + + range = 1 + (power / 5); + + // announce + if (isplayer(caster) || cansee(player, caster)) { + msg("%s emit%s a blast of icy cold!",castername,isplayer(caster) ? "" : "s"); + if (seenbyplayer) *seenbyplayer = B_TRUE; + } + + animradialorth(caster->cell, range, '}', C_GREY); + + 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, B_FALSE, NULL)) { + char lfname[BUFLEN]; + // automatic hit + getlfname(targcell->lf, lfname); + if (haslos(caster, targcell)) { + msg("%s %s chilled!",lfname,isplayer(targcell->lf) ? "are" : "is"); + } + losehp(targcell->lf, rolldie(1,8)+3, DT_COLD, caster, "a burst of coldness"); + } + } + } + } } else if (spellid == OT_S_CONECOLD) { char lfname[BUFLEN]; - int acc; if (!validatespellcell(caster, &targcell, TT_MONSTER, B_FALSE, LOF_NEED, spellid, power)) return B_TRUE; // animation - anim(caster->cell, targcell, '}'); + anim(caster->cell, targcell, '}', C_GREY); if (isplayer(caster) || cansee(player, caster)) { msg("%s shoot%s a blast of coldness.",castername,isplayer(caster) ? "" : "s"); if (seenbyplayer) *seenbyplayer = B_TRUE; @@ -953,20 +1093,20 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (target) { getlfname(target, lfname); // target takes magical damage - // check if it hits - acc = getmissileaccuracy(caster, target->cell, NULL, NULL, A_IQ); - if (rnd(1,100) <= acc) { + + if (skillcheck(target, SC_DODGE, 20 + (power*2), 0)) { + // miss + if (cansee(caster, target)) { + msg("A blast of coldness misses %s.",lfname); + } + } else { // hit if (cansee(caster, target)) { msg("A blast of coldness ray hits %s.",lfname); } losehp(target, rnd(2,6), DT_COLD, caster, "a blast of coldness"); - } else { - // miss - if (cansee(caster, target)) { - msg("A blast of coldness misses %s.",lfname); - } } + } else { object_t *o, *nexto; for (o = targcell->obpile->first; o ; o = nexto) { @@ -975,14 +1115,33 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } } else if (spellid == OT_S_CREATEMONSTER) { - cell_t *where; lifeform_t *newlf; job_t *forcejob = NULL; race_t *r = NULL; int randomjobsok = B_TRUE; - // create a monster nearby - if (blessed || (power >= 5)) { + if (!targcell) { + if (power >= 5) { + // control location + if (!validatespellcell(caster, &targcell, TT_NONE, B_TRUE, LOF_DONTNEED, spellid, power)) return B_TRUE; + // make sure it's empty + if (!cellwalkable(NULL, targcell, NULL)) { + targcell = NULL; + } + } else { + // get random adjacent cell + targcell = getrandomadjcell(caster->cell, WE_EMPTY); + } + } + + + if (!targcell) { + fizzle(caster); + return B_TRUE; + } + + // determine type of mosnter + if (power >= 7) { // ask what kind of monster askstring("Create what kind of monster", '?', buf, BUFLEN, NULL); r = findracebyname(buf); @@ -1008,39 +1167,29 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } if (!r) { - if (caster->controller == C_PLAYER) { - nothinghappens(); - } + fizzle(caster); return B_TRUE; } + } else { + // random one + r = getreallyrandomrace(); } - // get random adjacent cell - where = getrandomadjcell(caster->cell, WE_EMPTY); - if (!where) { - if (caster->controller == C_PLAYER) { - nothinghappens(); - } - return B_TRUE; - } - // create random monster in cell if (forcejob) { randomjobsok = B_FALSE; } else { randomjobsok = B_TRUE; } - if (!blessed) { - r = getreallyrandomrace(); - } - newlf = addmonster(where, r->id, randomjobsok, 1); + // add the monster + newlf = addmonster(targcell, r->id, randomjobsok, 1); if (newlf) { // assign job if required if (forcejob) { givejob(newlf, forcejob->id); } - if (haslos(player, where)) { + if (haslos(player, targcell)) { char *newbuf; getlfname(newlf, buf); newbuf = strdup(buf); @@ -1223,7 +1372,21 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ target = targcell->lf; if (targcell->lf) { - if (skillcheck(targcell->lf, SC_RESISTMAG, 20 + power, 0)) { + int resisted = B_FALSE; + // if you cast this at yourself, only check for magic resistance if you have the + // flag. + // other people get a check anyway. + if (targcell->lf == caster) { + if (getmr(targcell->lf) && skillcheck(targcell->lf, SC_RESISTMAG, 20 + power, 0)) { + resisted = B_TRUE; + } + } else { + if (skillcheck(targcell->lf, SC_RESISTMAG, 20 + power, 0)) { + resisted = B_TRUE; + } + } + + if (resisted) { if (isplayer(targcell->lf)) { msg("You flicker."); if (seenbyplayer) *seenbyplayer = B_TRUE; @@ -1272,6 +1435,46 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ nothinghappens(); } rv = B_FALSE; + } else if (spellid == OT_S_DRAINLIFE) { + char lfname[BUFLEN]; + if (!validatespellcell(caster, &targcell,TT_MONSTER, B_FALSE, LOF_NEED, spellid, power)) return B_TRUE; + + target = haslf(targcell); + if (target) { + getlfname(target, lfname); + } else { + fizzle(caster); + return B_FALSE; + } + + if (!isimmuneto(target->flags, DT_NECROTIC)) { + // animation (opposite dir) + anim(targcell, caster->cell, '%', C_MAGENTA); + } + if (isplayer(caster) || cansee(player, caster)) { + if (isimmuneto(target->flags, DT_NECROTIC)) { + msg("%s suck%s death from %s!",castername,isplayer(caster) ? "" : "s", lfname); + } else { + msg("%s suck%s life from %s!",castername,isplayer(caster) ? "" : "s", lfname); + } + if (seenbyplayer) *seenbyplayer = B_TRUE; + } + + if (target) { + int amt; + if (isimmuneto(target->flags, DT_NECROTIC)) { + // target gains hp + amt = rnd(1,6) + power; + gainhp(target, amt); + // caster loses it + amt = losehp(caster, rnd(1,6) + power, DT_NECROTIC, caster, "lifeforce drain"); + } else { + // target loses hp + amt = losehp(target, rnd(1,6) + power, DT_NECROTIC, caster, "lifeforce drain"); + // caster gains it + gainhp(caster, amt); + } + } } else if (spellid == OT_S_ENERGYBLAST) { int range; int x,y; @@ -1283,7 +1486,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ range = 2 + (power / 4); - animradial(caster->cell, range, '}'); + animradial(caster->cell, range, '}', C_CYAN); for (y = caster->cell->y - range ; y <= caster->cell->y + range; y++) { for (x = caster->cell->x - range ; x <= caster->cell->x + range; x++) { @@ -1313,7 +1516,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ numtotext(power, numbuf); if (!validatespellcell(caster, &targcell, TT_MONSTER, B_FALSE, LOF_NEED, spellid, power)) return B_TRUE; // animation - anim(caster->cell, targcell, '}'); + anim(caster->cell, targcell, '}', C_CYAN); if (isplayer(caster) || cansee(player, caster)) { if (power == 1) { msg("%s fire%s a bolt of energy.",castername,isplayer(caster) ? "" : "s"); @@ -1357,7 +1560,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ msg("An enormous ball of fire explodes!"); } - anim(caster->cell, targcell, '^'); + anim(caster->cell, targcell, '^', C_RED); // add fires as follows (3 = large, 2 = medium, 1 = smell) // @@ -1416,10 +1619,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } else if (spellid == OT_S_FIREDART) { char lfname[BUFLEN]; - int acc; if (!validatespellcell(caster, &targcell,TT_MONSTER, B_FALSE, LOF_NEED, spellid, power)) return B_TRUE; // animation - anim(caster->cell, targcell, '}'); + anim(caster->cell, targcell, '}', C_RED); if (isplayer(caster) || cansee(player, caster)) { msg("%s shoot%s a dart of flame.",castername,isplayer(caster) ? "" : "s"); if (seenbyplayer) *seenbyplayer = B_TRUE; @@ -1430,18 +1632,15 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ getlfname(target, lfname); // target takes magical damage // check if it hits - acc = getmissileaccuracy(caster, target->cell, NULL, NULL, A_IQ); - if (rnd(1,100) <= acc) { + if (skillcheck(target, SC_DODGE, 20 + (power*2), 0)) { + // miss + msg("A dart of flame misses %s.",lfname); + } else { // hit if (cansee(caster, target)) { msg("A dart of flame hits %s.",lfname); } losehp(target, rnd(2,6) + power, DT_FIRE, caster, "a dart of flame"); - } else { - // miss - if (cansee(caster, target)) { - msg("A dart of flame misses %s.",lfname); - } } } else { object_t *o, *nexto; @@ -1462,7 +1661,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (seenbyplayer) *seenbyplayer = B_TRUE; } - animradialorth(caster->cell, range, '}'); + animradialorth(caster->cell, range, '}', C_RED); for (y = caster->cell->y - range ; y <= caster->cell->y + range; y++) { for (x = caster->cell->x - range ; x <= caster->cell->x + range; x++) { @@ -1475,7 +1674,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ 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"); + losehp(targcell->lf, rolldie(2,8)+3, DT_FIRE, caster, "a burst of fire"); } } } @@ -1837,8 +2036,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } for (l = caster->cell->map->lf ; l ; l = l->next) { if (l != caster) { - - if (skillcheck(l, SC_RESISTMAG, 20 + power, 0)) { + if (isimmuneto(l->flags, DT_NECROTIC) || skillcheck(l, SC_RESISTMAG, 20 + power, 0)) { if (isplayer(l)) { msg("Luckily, the evil doesn't seem to harm you."); if (seenbyplayer) *seenbyplayer = B_TRUE; @@ -1848,10 +2046,24 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ char cname[BUFLEN]; real_getlfname(caster, cname, B_FALSE); sprintf(dambuf, "%s%s infinite death spell", cname, getpossessive(cname)); - losehp(l, 9999, DT_DIRECT, NULL, dambuf); + losehp(l, 500, DT_NECROTIC, NULL, dambuf); } } } + + // now hit the caster! + if (isimmuneto(caster->flags, DT_NECROTIC) || skillcheck(caster, SC_RESISTMAG, 20 + power, 0)) { + if (isplayer(caster)) { + msg("Luckily, the evil doesn't seem to harm you."); + if (seenbyplayer) *seenbyplayer = B_TRUE; + } + } else { + char dambuf[BUFLEN]; + char cname[BUFLEN]; + real_getlfname(caster, cname, B_FALSE); + sprintf(dambuf, "%s%s infinite death spell", cname, getpossessive(cname)); + losehp(caster, 500, DT_NECROTIC, NULL, dambuf); + } } else if (spellid == OT_S_MANASPIKE) { char lfname[BUFLEN]; char numbuf[BUFLEN]; @@ -1859,7 +2071,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ numtotext(power, numbuf); if (!validatespellcell(caster, &targcell,TT_MONSTER, B_FALSE, LOF_NEED, spellid, power)) return B_TRUE; // animation - anim(caster->cell, targcell, '}'); + anim(caster->cell, targcell, '}', C_CYAN); if (isplayer(caster) || cansee(player, caster)) { if (power == 1) { msg("%s fire%s a spike of mana.",castername,isplayer(caster) ? "" : "s"); @@ -2164,6 +2376,97 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (seenbyplayer) *seenbyplayer = B_TRUE; } addflag(target->flags, F_BEINGSTONED, 2, NA, NA, NULL); + } else if (spellid == OT_S_POISONBOLT) { + char lfname[BUFLEN]; + if (!validatespellcell(caster, &targcell,TT_MONSTER, B_FALSE, LOF_NEED, spellid, power)) return B_TRUE; + // animation + anim(caster->cell, targcell, '}', C_GREEN); + + target = haslf(targcell); + if (target) { + getlfname(target, lfname); + // target gets saving throw to avoid... + if (skillcheck(target, SC_DODGE, 20 + (power*2), 0)) { + // miss + if (cansee(caster, target)) { + msg("A glob of venom misses %s.",lfname); + } + } else { + // hit + if (cansee(caster, target)) { + msg("A glob of venom hits %s.",lfname); + } + losehp(target, rnd(1,4), DT_POISON, caster, "a glob of poison"); + if (!isimmuneto(target->flags, DT_POISON)) { + addtempflag(target->flags, F_POISONED, NA, NA, NA, castername, power*3); + } + } + } 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_POSSESSION) { + char targname[BUFLEN]; + if (!validatespellcell(caster, &targcell,TT_MONSTER, B_TRUE, LOF_DONTNEED, spellid, power)) return B_TRUE; + + target = targcell->lf; + if (!target) { + fizzle(caster); + return B_FALSE; + } + getlfname(target, targname); + + // saving throw.... + if (skillcheck(target, SC_RESISTMAG, 20 + power*2, 0)) { + if (isplayer(caster) && cansee(player, target)) { + msg("%s%s mind fights off your intrusion!", targname, getpossessive(targname)); + } + return B_FALSE; + } + + // announce + if (cansee(player,target)) { + if (isplayer(caster)) { + msg("You take possession of %s%s mind!", targname, getpossessive(targname)); + } else { + msg("%s takes possession of %s%s mind!",cansee(player, caster) ? castername : "Something", + targname, getpossessive(targname)); + } + } + + // possess! + if (isplayer(caster)) { + // player name + copyflag(target->flags, caster->flags, F_NAME); + + // level + target->level = player->level; + + player->controller = C_AI; + player = target; + target->controller = C_PLAYER; + + } else { + switch (getallegiance(caster)) { + case AL_HOSTILE: + killflagsofid(target->flags, F_FRIENDLY); + addflag(target->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); + break; + case AL_PEACEFUL: + killflagsofid(target->flags, F_FRIENDLY); + killflagsofid(target->flags, F_HOSTILE); + break; + case AL_FRIENDLY: + makefriendly(target, PERMENANT); + break; + } + } + + // now kill the caster! + die(caster); } else if (spellid == OT_S_PSYARMOUR) { flag_t *f; // always targetted at caster @@ -2787,6 +3090,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ // target is always the caster target = caster; + if (skillcheck(target, SC_RESISTMAG, 20 + power, 0)) { if (isplayer(target)) { @@ -2800,14 +3104,14 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ return B_FALSE; } + if ((power < 5) || !isplayer(caster)) { + // random while (!c || c->type->solid || haslf(c)) { c = getrandomcell(target->cell->map); } - if (isplayer(target) || haslos(player, target->cell)) { - if (seenbyplayer) *seenbyplayer = B_TRUE; - } - } else { + } else if (power >= 8) { + // controlled sprintf(buf, "Where will you teleport to?"); while (!c) { int ch; @@ -2822,12 +3126,112 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (ch != 'y') c = NULL; } } - } + } else { // ie. if (power >= 5) + int dir; + char dirch; + cell_t *poss[MAX_MAPW * MAX_MAPH]; + int nposs; + int x,y; + int xmin,ymin; + int xmax,ymax; + // semicontrolled + // ask for dir + dirch = askchar("Teleport in which direction (- to cancel)", "yuhjklbn.-","-", B_FALSE); + if ((dirch == '.') || (dir == '-')) { + fizzle(caster); + return B_TRUE; + } else { + dir = chartodir(dirch); + } + + // make a list of all valid cells in that dir + nposs = 0; + switch (dir) { + case D_N: + case DC_N: + ymin = 0; + ymax = target->cell->y - 1; + + xmin = target->cell->x - 5; + xmax = target->cell->x + 5; + break; + case DC_NE: + xmin = target->cell->x + 1; + ymin = 0; + xmax = target->cell->map->w - 1; + ymax = target->cell->y - 1; + break; + case D_E: + case DC_E: + xmin = target->cell->x + 1; + xmax = target->cell->map->w - 1; + ymin = target->cell->y - 5;; + ymax = target->cell->y + 5;; + break; + case DC_SE: + xmin = target->cell->x + 1; + ymin = target->cell->y + 1; + xmax = target->cell->map->w - 1; + ymax = target->cell->map->h - 1; + break; + case D_S: + case DC_S: + ymin = target->cell->y + 1; + ymax = target->cell->map->h - 1; + xmin = target->cell->x - 5; + xmax = target->cell->x + 5; + break; + case DC_SW: + xmin = 0; + ymin = target->cell->y + 1; + xmax = target->cell->x - 1; + ymax = target->cell->map->h - 1; + break; + case D_W: + case DC_W: + xmin = 0; + xmax = target->cell->x - 1; + ymin = target->cell->y - 5; + ymax = target->cell->y + 5; + break; + case DC_NW: + xmin = 0; + ymin = 0; + xmax = target->cell->x - 1; + ymax = target->cell->y - 1; + break; + } + + if (xmin < 0) xmin = 0; + if (ymin < 0) ymin = 0; + if (xmax > target->cell->map->w-1) xmax = target->cell->map->w-1; + if (ymax > target->cell->map->h-1) ymax = target->cell->map->h-1; + + for (y = ymin; y <= ymax ; y++) { + for (x = xmin; x <= xmax ; x++) { + c = getcellat(target->cell->map, x,y); + if (c && cellwalkable(target, c, NULL)) { + poss[nposs] = c; + nposs++; + } + } + } + + if (nposs <= 0) { + fizzle(caster); + return B_FALSE; + } + + + c = poss[rnd(0,nposs-1)]; + } // end if (semicontrolled | controlled | random ) + + targcell = c; if (isplayer(target) || haslos(player, target->cell)) { if (seenbyplayer) *seenbyplayer = B_TRUE; } - teleportto(target, c, B_TRUE); + teleportto(target, targcell, B_TRUE); rv = B_FALSE; } else if (spellid == OT_S_TELEKINESIS) { cell_t *where; @@ -3151,28 +3555,33 @@ char *getspellname(enum OBTYPE spellid, lifeform_t *lf, char *buf) { capitalise(buf); power = getspellpower(lf, spellid); ss = getspellschool(spellid); + + if ((power > 1) && (ss != SS_ABILITY)) { + strcat(buf, " "); + strcat(buf, roman(power)); + } + if (spellid == OT_S_TELEPORT) { - if (power >= 5) { - strcat(buf, "(controlled)"); + if (power >= 8) { + strcat(buf, "(fullctrl)"); + } else if (power >= 5) { + strcat(buf, "(semictrl)"); } } else if (spellid == OT_S_POLYMORPH) { if (power >= 5) { - strcat(buf, "(controlled)"); + strcat(buf, "(ctrl)"); } } else if (spellid == OT_S_CREATEMONSTER) { - if (power >= 5) { - strcat(buf, "(controlled)"); + if (power >= 7) { + strcat(buf, "(fullctrl)"); + } else if (power >= 5) { + strcat(buf, "(semictrl)"); } } else if (spellid == OT_S_LIGHT) { if (power >= 8) { - strcat(buf, "(perm,controlled)"); + strcat(buf, "(perm,ctrl)"); } else if (power >= 3) { - strcat(buf, "(controlled)"); - } - } else { - if ((power > 1) && (ss != SS_ABILITY)) { - strcat(buf, " "); - strcat(buf, roman(power)); + strcat(buf, "(ctrl)"); } } return buf; @@ -3182,7 +3591,8 @@ int getspellpower(lifeform_t *lf, enum OBTYPE spellid) { int power = 0; int statmod; int spelllev; - int skill; + enum SKILLLEVEL spellskill,schoolskill; + enum SPELLSCHOOL school; int max = 10; flag_t *f; @@ -3206,25 +3616,52 @@ int getspellpower(lifeform_t *lf, enum OBTYPE spellid) { statmod = 0; } - skill = getskill(lf, SK_SPELLCASTING); - if (skill == PR_INEPT) { - return 0; + school = getspellschool(spellid); + spellskill = getskill(lf, SK_SPELLCASTING); + // dont need spellcasting skill for mental/allomancy + switch (school) { + case SS_ALLOMANCY: + case SS_MENTAL: + break; + default: + if (spellskill == PR_INEPT) { + return 0; + } + break; } // every 6 levels you get 1 more power // ie. at level 30 you get +5 power - power = (lf->level/6) + statmod + skill; + power = (lf->level/6) + statmod; + + switch (school) { + case SS_ALLOMANCY: + case SS_MENTAL: + break; + default: + power += spellskill; + break; + } spelllev = getspelllevel(spellid); if (spelllev > 0) { - power /= spelllev; + int divamt; + if ((school == SS_ALLOMANCY) || (school == SS_MENTAL)) { + divamt = (spelllev/2); + } else { + divamt = spelllev; + } + + if (divamt > 0) { + power /= divamt; + } } - // specialised spellcasting - apply this AFTER dividing by spell level? - skill = getskill(lf, getschoolskill(getspellschool(spellid))); - if (skill != PR_INEPT) { - power += skill; + // specialised school skill - apply this AFTER dividing by spell level + schoolskill = getskill(lf, getschoolskill(getspellschool(spellid))); + if (schoolskill != PR_INEPT) { + power += schoolskill; } // enforce maximum @@ -3274,8 +3711,11 @@ int getspellrange(enum OBTYPE spellid, int power) { void pullobto(object_t *o, lifeform_t *lf) { char obname[BUFLEN]; char lfname[BUFLEN]; + glyph_t *gl; - anim(getoblocation(o), lf->cell, getglyph(o)); + gl = getglyph(o); + + anim(getoblocation(o), lf->cell, gl->ch, gl->colour); getobname(o, obname, o->amt); getlfname(lf, lfname); @@ -3404,20 +3844,23 @@ cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, i if (where) { cell_t *newwhere = NULL; // validate it - if (where && needlos && !haslos(caster, where)) { + if (where && needlos && !haslos(caster, where) && (where != caster->cell)) { msg("You cannot see there!"); more(); where = NULL; } + // line of fire interrupted? if (where && needlof && !haslof(caster, where, needlof, &newwhere)) { if (newwhere) { - // warn! - int ch; - ch = askchar("Your have no clear line of fire - really target here?","yn","n", B_TRUE); - if (ch == 'y') { - where = newwhere; - } else { - where = NULL; + if (isplayer(caster)) { + // warn! + int ch; + ch = askchar("Your have no clear line of fire - really target here?","yn","n", B_TRUE); + if (ch == 'y') { + where = newwhere; + } else { + where = NULL; + } } } else { where = NULL; @@ -3467,8 +3910,8 @@ cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, i if (!where) { int ch; ch = askchar("Abandon your spell?","yn","n", B_TRUE); - if (ch != 'y') { - where = NULL; + if (ch == 'y') { + return NULL; } } } else { diff --git a/text.c b/text.c index e897a47..a5bbd6d 100644 --- a/text.c +++ b/text.c @@ -30,6 +30,49 @@ char *capitaliseall(char *text) { return text; } +char *dicetotext(int ndice, int nsides, int bonus, int *min, int *max, char *dicebuf, char *minmaxbuf) { + int localmin, localmax; + + if (ndice == NA) ndice = 0; + if (nsides == NA) nsides = 0; + if (bonus == NA) bonus = 0; + + // ie. rolled a 1 on all dice + localmin = (ndice * 1) + bonus; + // ie. rolled max on all dice + localmax = (ndice * nsides) + bonus; + + if (min) { + *min = localmin; + } + if (max) { + *max = localmax; + } + + if (dicebuf) { + if ((ndice == 0) || (nsides == 0)) { + sprintf(dicebuf, "%d", bonus); + } else { + if (bonus) { + sprintf(dicebuf, "%dd%d%c%d", ndice, nsides, + (bonus > 0) ? '+' : '-', + abs(bonus)); + } else { + sprintf(dicebuf, "%dd%d", ndice, nsides); + } + } + } + if (minmaxbuf) { + if (localmin == localmax) { + sprintf(minmaxbuf, "%d", localmin); + } else { + sprintf(minmaxbuf, "%d-%d", localmin, localmax); + } + } + return dicebuf; +} + + char *getattrname(enum ATTRIB att) { switch (att) { case A_NONE: @@ -171,6 +214,8 @@ char *makeplural(char *text) { if (rv) return newtext; newtext = strrep(newtext, "chunk ", "chunks ", &rv); if (rv) return newtext; + newtext = strrep(newtext, "flask ", "flasks ", &rv); + if (rv) return newtext; newtext = strrep(newtext, "gem ", "gems ", &rv); if (rv) return newtext; newtext = strrep(newtext, "loaf ", "loaves ", &rv); @@ -429,7 +474,7 @@ int strpixmatch(char *haystack, char *needle) { int texttodice(char *text, int *ndice, int *nsides, int *bonus) { char *dummy; char *localtext; - char *p; + char *p,*plusloc; localtext = strdup(text); // number of dice p = strtok_r(localtext, "d", &dummy); @@ -444,16 +489,32 @@ int texttodice(char *text, int *ndice, int *nsides, int *bonus) { if (!p) { return B_TRUE; } + + // strip out bonus + plusloc = strchr(p, '+'); + if (plusloc) *plusloc = '\0'; + plusloc = strchr(p, '-'); + if (plusloc) *plusloc = '\0'; + if (nsides) { *nsides = atoi(p); } + + + free(localtext); + localtext = strdup(text); // bonus/plus if (bonus) { - p = strtok_r(NULL, "+", &dummy); + p = strchr(localtext, '+'); if (p) { - *bonus = atoi(p); + *bonus = atoi(p+1); } else { - *bonus = 0; + p = strchr(localtext, '-'); + if (p) { + *bonus = -(atoi(p+1)); + } else { + *bonus = 0; + } } } diff --git a/text.h b/text.h index 358a19c..10593f7 100644 --- a/text.h +++ b/text.h @@ -2,6 +2,7 @@ char *capitalise(char *text); char *capitaliseall(char *text); +char *dicetotext(int ndice, int nsides, int bonus, int *min, int *max, char *dicebuf, char *minmaxbuf); char *getattrname(enum ATTRIB att); char *getpossessive(char *text); char *getsizetext(enum LFSIZE sz);