From 27d22df11de48ace71386356a2431855f651a978 Mon Sep 17 00:00:00 2001 From: Rob Pearce Date: Thu, 9 Jun 2011 08:58:35 +0000 Subject: [PATCH] - [+] implement getradiuscells() - [+] evaporate spell - turn water into steam - [+] monster generation bug? even on dlev10 i'm stil getting mostly kobolds - [+] ai infinint eloop again - frost hawk trying to open door - [+] another infinite loop - not falling through after spell failure. * [+] reduce attack delay for most weapons. - [+] letplayer see a tiny bit in the dark (1 cell ?) - [+] beginner tracking not working - fixed. - [+] only show "...but do no damage" if you have good knowledge about their race. - [+] make gold lighter * [+] footprints glyph shouldn't override pudles of water! - [+] only show eviscerate etc if you have good knowledge? - [+] don't start monsters on the stairs/magical barriers!!! - [+] stone should be immune to more damage types * [+] addexits adding way too many exits. - [+] blessed identify should ID everything - [+] blessed mending mends all - [+] don't make noise when slowmoving. - [+] eyebat dispersal big: The eyebat's strong scent leading north disappears! - [+] go over footprint+scent+corpse and pickup:"You can't pick up footprints!" * [+] doors can't do on top of each other!!! * [+] low ground - [+] make sure you can't have more than one "water" object in a cell. * [+] make val2 of rarity be "common/uncommon/rare" etc - [+] more monster types should appear in the forest. - [+] when i go down stairs into a dark area, "it is pitch black!" is being cleared. * [+] helm of the poltergeist - [+] flying creatures get penalties in webs etc - [+] blind things shoudln't follow up/donw stairs - [+] You shout a blood-curdling war cry! The sawgrass turns to flee from you! - [+] potions still worth too much. minor healing was 420!! - [+] AI should only go towards covetted object if it's closer or the same distanec as target. - [+] branded objects should be worth LOTS - at the moment they're worth 1!! * [+] maybe just adjust value of rarity? - [+] don't roll spot checks while training! * [+] replace f_nofeel with: - [+] revenge did too much damage (50) * [+] change how AR works - [+] need to add: "really walk into a falling rock trap" ? - [+] put only ONE staircase going up on dlev 0 - [+] why am i stopping sprinting after 1 move? * [+] somehow make sure mosnters can't see footprints in a cell with mist - [+] bones shouldn't be able to catch on fire. - [+] when you levle up, gainskill BEFORE getting new spells - [+] put out flaming objects after pickup * [+] don't say "really target yourself?" when using a potion of sleep!! - [+] enhance a random skill when levelling up? every 2 levels? - [+] weaken koboldsa little - less change of javelin - [+] don't drown instantly - take a few turns, depending on CON * [+] create vault spell for debugging ??? - [+] doors in the middle of rooms. - [+] highlight selected choice in askstr - [+] flooded_room being created without walls!!!!!! - [+] describe spell from levleup not working * [+] GETROOMEDGE RETURNING NO CELLS for circularroom!!!!! - [+] fire wizard not prompted to get firedart at l2.. Vaults * [+] X corridor - - [+] crosshatch - [+] should water be ~ instead ?? and change whatever is currently a tilde to something else... Initial work on goal: - [+] surround all stairs with barriers - [+] start player NEAR stairs (randomadjcell from stairs, allowexpand) + methods of escape - [+] knock scroll - [+] digging (but it stops the dig from going any further) --- ai.c | 153 ++++-- ai.h | 3 +- attack.c | 48 +- attack.h | 1 + defs.h | 41 +- flag.c | 4 +- io.c | 83 +++- io.h | 4 +- lf.c | 344 ++++++++----- lf.h | 2 + map.c | 360 +++++++++++--- map.h | 15 +- move.c | 63 ++- nexus.c | 91 +++- nexus.h | 5 +- objects.c | 977 ++++++++++++++++--------------------- objects.h | 6 +- spell.c | 253 ++++++---- spell.h | 6 +- text.c | 30 ++ text.h | 1 + vaults/cavein.vlt | 2 +- vaults/circle.vlt | 4 +- vaults/diningroom.vlt | 4 +- vaults/floodroom1.vlt | 10 +- vaults/floodroom2.vlt | 6 +- vaults/lair_cockatrice.vlt | 3 +- vaults/monsterzoo.vlt | 2 +- vaults/mudroom.vlt | 2 +- vaults/pillar.vlt | 4 +- vaults/pillarglass.vlt | 2 +- vaults/traproom.vlt | 2 +- vaults/vault.vlt | 2 +- 33 files changed, 1546 insertions(+), 987 deletions(-) diff --git a/ai.c b/ai.c index c080edd..1ddc0a4 100644 --- a/ai.c +++ b/ai.c @@ -556,10 +556,11 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) { } if (spellfailed) { if (db) dblog(".oO { cast spell/ability tried but failed (2)! reason = %d }", reason); + // spell failed. we will keep going through aiturn. } else { // spell succesful + return B_FALSE; } - return B_FALSE; } // see if we have a ranged attack. if so, adjust wantdist @@ -982,7 +983,7 @@ void aiturn(lifeform_t *lf) { // instead of attacking our target. if (!lfhasflag(lf, F_HIDING)) { if (db) dblog(".oO { looking for covetted objects... }"); - if (lookforobs(lf, B_COVETS)) { + if (lookforobs(lf)) { if (db) dblog(".oO { found covetted object. returning. }"); return; } @@ -991,34 +992,26 @@ void aiturn(lifeform_t *lf) { /////////////////////////////////////////////// // attacks /////////////////////////////////////////////// - + + + target = gettargetlf(lf); // do we already have a target we are attacking? - f = hasflag(lf->flags, F_TARGETLF); - if (f) { - int targid; - int lastx,lasty; - if (db) dblog(".oO { i have a target... }"); - targid = f->val[0]; - lastx = f->val[1]; - lasty = f->val[2]; - target = findlf(lf->cell->map, targid); - if (target) { - if (db) dblog(".oO { my target is lfid %d (%s). }", targid, target->race->name); - // aquatic grabbers will try to drag their prey into the water - if (lfhasflagval(lf, F_GRABBING, target->id, NA, NA, NULL) && isaquatic(lf) ) { - if ( hasobwithflag(lf->cell->obpile, F_DEEPWATER) && - !hasobwithflag(target->cell->obpile, F_DEEPWATER)) { - // move away! - if (!moveawayfrom(lf, target->cell, DT_ORTH)) { - return; - } + if (target) { + if (db) dblog(".oO { i have a target: lfid %d (%s). }", target->id, target->race->name); + // aquatic grabbers will try to drag their prey into the water + if (lfhasflagval(lf, F_GRABBING, target->id, NA, NA, NULL) && isaquatic(lf) ) { + if ( hasobwithflag(lf->cell->obpile, F_DEEPWATER) && + !hasobwithflag(target->cell->obpile, F_DEEPWATER)) { + // move away! + if (!moveawayfrom(lf, target->cell, DT_ORTH)) { + return; } } - // try to move towards them. - if (!aimovetolf(lf, target, B_TRUE)) { - // success - return; - } + } + // try to move towards them. + if (!aimovetolf(lf, target, B_TRUE)) { + // success + return; } } @@ -1088,6 +1081,7 @@ void aiturn(lifeform_t *lf) { /////////////////////////////////////////////// // look for any object which we want + /* if (!isinbattle(lf)) { if (db) dblog(".oO { looking for any ob which i want. }"); if (lookforobs(lf, B_ANY)) { @@ -1095,6 +1089,7 @@ void aiturn(lifeform_t *lf) { return; } } + */ @@ -1547,6 +1542,16 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG } +lifeform_t *gettargetlf(lifeform_t *lf) { + flag_t *f; + lifeform_t *target = NULL; + f = hasflag(lf->flags, F_TARGETLF); + if (f) { + target = findlf(lf->cell->map, f->val[0]); + } + return target; +} + object_t *hasbetterarmour(lifeform_t *lf, obpile_t *op) { object_t *o; @@ -1582,17 +1587,26 @@ object_t *hasbetterweapon(lifeform_t *lf, obpile_t *op) { // returns B_TRUE if we did something -int lookforobs(lifeform_t *lf, int covetsonly) { +int lookforobs(lifeform_t *lf) { object_t *o; enum OBTYPE oid[MAXPILEOBS]; + int oidcovet[MAXPILEOBS]; int noids = 0; enum FLAG wantflag[MAXPILEOBS]; + int wantflagcovet[MAXPILEOBS]; int nwantflags = 0; flag_t *f; cell_t *c; int n; int i; int db = B_FALSE; + lifeform_t *target; + int targdist = 999; + + target = gettargetlf(lf); + if (target) { + targdist = getcelldist(lf->cell, target->cell); + } if (wantdb && lfhasflag(lf, F_DEBUG)) { db = B_TRUE; @@ -1604,31 +1618,45 @@ int lookforobs(lifeform_t *lf, int covetsonly) { noids = 0; for (f = lf->flags->first ; f ; f = f->next) { if (f->id == F_WANTS) { - if (!covetsonly || (f->val[1] == B_COVETS)) { - oid[noids] = f->val[0]; - noids++; - } + oid[noids] = f->val[0]; + oidcovet[noids] = (f->val[1] == B_COVETS) ? B_TRUE : B_FALSE; + noids++; } else if (f->id == F_WANTSOBFLAG) { - if (!covetsonly || (f->val[1] == B_COVETS)) { - wantflag[nwantflags] = f->val[0]; - nwantflags++; - } + wantflag[nwantflags] = f->val[0]; + wantflagcovet[noids] = (f->val[1] == B_COVETS) ? B_TRUE : B_FALSE; + nwantflags++; } } // current cell has an object we want? o = hasobmulti(lf->cell->obpile, oid, noids); if (o && !isdangerousob(o, lf, B_TRUE) && aipickupok(lf, o)) { - if (db) dblog(".oO { current cell has ob i want (%s) }",o->type->name); - // try to pick it up - if (!aipickup(lf, o)) return B_TRUE; - if (db) dblog(".oO { pickup of %s failed, trying to eat! }",o->type->name); - if (!eat(lf, o)) return B_TRUE; - if (db) dblog(".oO { eating %s failed }",o->type->name); + int getit = B_TRUE; + + // if we are in battle only go for it if we covet it + if (target) { + int nn; + for (nn = 0; nn < noids; nn++) { + if (oid[nn] == o->id) break; + } + if (!oidcovet[nn]) getit = B_FALSE; + } + if (getit) { + if (db) dblog(".oO { current cell has ob i want (%s) }",o->type->name); + // try to pick it up + if (!aipickup(lf, o)) return B_TRUE; + if (db) dblog(".oO { pickup of %s failed, trying to eat! }",o->type->name); + if (!eat(lf, o)) return B_TRUE; + if (db) dblog(".oO { eating %s failed }",o->type->name); + } } // has an object with a flag we want? for (n = 0; n < nwantflags; n++) { o = hasobwithflag(lf->cell->obpile, wantflag[n]); + + // if we are in battle only go for it if we covet it + if (target && !wantflagcovet[n]) continue; + if (o && !isdangerousob(o, lf, B_TRUE) && (canpickup(lf, o, 1) || caneat(lf,o)) ) { if (db) dblog(".oO { current cell has ob with flag i want (%s) }",o->type->name); // try to pick it up @@ -1643,7 +1671,8 @@ int lookforobs(lifeform_t *lf, int covetsonly) { if (lfhasflag(lf, F_HUMANOID) && hasbp(lf, BP_WEAPON)) { f = hasflag(lf->flags, F_WANTSBETTERWEP); if (f) { - if (!covetsonly || (f->val[1] == B_COVETS)) { + // if we are in battle only go for it if we covet it + if (!target || (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); @@ -1659,7 +1688,8 @@ int lookforobs(lifeform_t *lf, int covetsonly) { // current cell has better armour? f = hasflag(lf->flags, F_WANTSBETTERARM); if (f ) { - if (!covetsonly || (f->val[1] == B_COVETS)) { + // if we are in battle only go for it if we covet it + if (!target || (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); @@ -1679,14 +1709,36 @@ int lookforobs(lifeform_t *lf, int covetsonly) { c = lf->los[i]; if (!c->lf && !lfhasflagval(lf, F_IGNORECELL, c->x, c->y, NA, NULL)) { + int celldist; + celldist = getcelldist(lf->cell, c); + o = hasobmulti(c->obpile, oid, noids); if (o && !isdangerousob(o, lf, B_TRUE) && aipickupok(lf, o)) { - if (db) dblog(".oO { remote cell has ob i want (%s). setting f_targetcell. }",o->type->name); - gothere = B_TRUE; + // if we are in battle only go for it if we covet it and + // it's closer than our target + if (target) { + int nn; + for (nn = 0; nn < noids; nn++) { + if (oid[nn] == o->id) break; + } + if (oidcovet[nn]) { + if (celldist <= targdist) { + if (db) dblog(".oO { remote cell has ob i want (%s). setting f_targetcell. }",o->type->name); + gothere = B_TRUE; + } + } + } else { + if (db) dblog(".oO { remote cell has ob i want (%s). setting f_targetcell. }",o->type->name); + gothere = B_TRUE; + } } + if (!gothere) { // has an object with a flag we want? for (n = 0; n < nwantflags; n++) { + // if we are in battle only go for it if we covet it + if (target && !wantflagcovet[n]) continue; + o = hasobwithflag(c->obpile, wantflag[n]); if (o && !isdangerousob(o, lf, B_TRUE) && aipickupok(lf, o)) { if (db) dblog(".oO { remote cell has ob with flag i want (%s) }", o->type->name); @@ -1699,7 +1751,9 @@ int lookforobs(lifeform_t *lf, int covetsonly) { // remote cell has better weapon? f = hasflag(lf->flags, F_WANTSBETTERWEP); if (f) { - if (!covetsonly || (f->val[1] == B_COVETS)) { + // if we are in battle only go for it if we covet it + if (!target || + ((f->val[1] != B_COVETS) && (celldist <= targdist)) ) { 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); @@ -1714,8 +1768,9 @@ int lookforobs(lifeform_t *lf, int covetsonly) { // remote cell has better armour? f = hasflag(lf->flags, F_WANTSBETTERARM); if (f) { - if (!covetsonly || (f->val[1] == B_COVETS)) { - + if (!target || + ((f->val[1] != B_COVETS) && (celldist <= targdist)) ) { + 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); diff --git a/ai.h b/ai.h index f92ad97..920a679 100644 --- a/ai.h +++ b/ai.h @@ -16,7 +16,8 @@ int aipickupok(lifeform_t *lf, object_t *o); int aiobok(lifeform_t *lf, object_t *o, lifeform_t *target); int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG purpose); void aiturn(lifeform_t *lf); +lifeform_t *gettargetlf(lifeform_t *lf); object_t *hasbetterarmour(lifeform_t *lf, obpile_t *op); object_t *hasbetterweapon(lifeform_t *lf, obpile_t *op); -int lookforobs(lifeform_t *lf, int covetsonly); +int lookforobs(lifeform_t *lf); int useitemwithflag(lifeform_t *lf, enum FLAG whichflag); diff --git a/attack.c b/attack.c index 4fc03b6..9c8f6ce 100644 --- a/attack.c +++ b/attack.c @@ -573,6 +573,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) char extradambuf[BUFLEN]; char withwep[BUFLEN]; char *verb; + int needfree = B_FALSE; strcpy(extradambuf, ""); @@ -582,20 +583,28 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) strcpy(withwep, ""); } + strcpy(extradambuf, ""); if (dam[i] == 0) { - strcpy(extradambuf, " but do no damage"); + if (getlorelevel(lf, victim->race->raceclass->id) >= PR_ADEPT) { + strcpy(extradambuf, " but do no damage"); + } } else if (lfhasflag(player, F_EXTRAINFO) || lfhasflag(player, F_OMNIPOTENT) ) { sprintf(extradambuf, " [%d dmg]",dam[i]); - } else { - strcpy(extradambuf, ""); } if (backstab && (i == 0)) { verb = strdup("backstab"); + needfree = B_TRUE; } else if (fatal) { verb = getkillverb(victim, wep, damtype[i], dam[i], victim->maxhp); } else { - verb = getattackverb(lf, wep, damtype[i], dam[i], victim->maxhp); + if ((getlorelevel(lf, victim->race->raceclass->id) >= PR_BEGINNER) || + !ismeleedam(damtype[i])) { + verb = getattackverb(lf, wep, damtype[i], dam[i], victim->maxhp); + } else { + verb = strdup("hit"); + needfree = B_TRUE; + } } warn("You %s %s%s%s%s", verb, @@ -610,7 +619,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) // don't also say "the xx dies" addflag(victim->flags, F_NODEATHANNOUNCE, B_TRUE, NA, NA, NULL); } - if (!strcmp(verb, "backstab")) { + if (needfree) { free(verb); } } else { @@ -1001,13 +1010,20 @@ int attackob(lifeform_t *lf, object_t *o, object_t *wep, flag_t *damflag) { int getarmourdamreduction(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damtype) { int reduceamt = 0; int ar; + int pctrange; object_t *o; ar = getarmourrating(lf); //reducepct = getdamreducepct(ar); //reduceamt = (int) ceil((reducepct / 100.0) * (float)dam); - reduceamt = ar/2; + + //reduceamt = ar/2; + + // between 25% and 75% of AR. + // ie. with AR of 20, all damage is reduced by 5-15. + pctrange = rnd(25,75); + reduceamt = pctof(pctrange, ar); // special case if (damtype == DT_PROJECTILE) { @@ -1573,6 +1589,24 @@ obpile_t *getunarmedweapon(lifeform_t *lf,flag_t **uflag) { } */ +// ie. caused by hitting something with a melee weapon +int ismeleedam(enum DAMTYPE damtype) { + switch (damtype) { + case DT_PIERCE: + case DT_SLASH: + case DT_BASH: + case DT_BITE: + case DT_CHOP: + case DT_PROJECTILE: + case DT_UNARMED: + case DT_CRUSH: + return B_TRUE; + default: + break; + } + return B_FALSE; +} + int isphysicaldam(enum DAMTYPE damtype) { switch (damtype) { case DT_BASH: @@ -1748,7 +1782,7 @@ void wepeffects(flagpile_t *fp, cell_t *where, flag_t *damflag, int dam) { if (dampct >= 50) { getdamrange(damflag, NULL, &maxdam); - extradam = (int)(dampct * (float)maxdam); + extradam = (int)((dampct/100) * (float)maxdam); if (extradam > 0) { char buf[BUFLEN]; char buf2[BUFLEN]; diff --git a/attack.h b/attack.h index 2c0bb01..c57c5c4 100644 --- a/attack.h +++ b/attack.h @@ -20,6 +20,7 @@ int getdamroll(object_t *o, lifeform_t *victim, flag_t *damflag); //int getunarmeddamroll(flag_t *f); float getstrdammod(lifeform_t *lf); //obpile_t *getunarmedweapon(lifeform_t *lf, flag_t **uflag); +int ismeleedam(enum DAMTYPE damtype); int isphysicaldam(enum DAMTYPE damtype); int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical); void wepeffects(flagpile_t *fp, cell_t *where, flag_t *damflag, int dam); diff --git a/defs.h b/defs.h index afc1d1b..3f70948 100644 --- a/defs.h +++ b/defs.h @@ -421,6 +421,7 @@ enum CELLTYPE { CT_DIRT, CT_GRASS, CT_LOOPCORRIDOR, + CT_LOWFLOOR, // rooms CT_ROOM, }; @@ -780,7 +781,6 @@ enum OBTYPE { OT_VENDINGMACHINE, OT_PORTAL, // terrain - OT_WATERSHALLOW, OT_WATERDEEP, // traps OT_TRAPARROW, @@ -978,6 +978,7 @@ enum OBTYPE { OT_S_CUREPOISON, OT_S_DETECTPOISON, OT_S_DIG, + OT_S_EVAPORATE, OT_S_WEB, OT_S_ENDUREELEMENTS, OT_S_ENTANGLE, @@ -1015,8 +1016,9 @@ enum OBTYPE { OT_S_ENERGYBLAST, OT_S_FLASH, // -- divine powers - OT_S_WISH, + OT_S_CREATEVAULT, OT_S_GIFT, + OT_S_WISH, OT_A_DEBUG, OT_A_ENHANCE, OT_A_LEARN, @@ -1308,12 +1310,33 @@ enum BODYPART { #define MAXBODYPARTS (12) // depth on a human + +#define DP_MAX DP_OVERHEAD4 +#define DP_FIRST DP_TOE enum DEPTH { +/* DP_HEAD = 4, DP_SHOULDERS = 3, DP_WAIST = 2, DP_FEET = 1, DP_NONE = 0, +*/ + DP_OVERHEAD4 = 15, + DP_OVERHEAD3 = 14, + DP_OVERHEAD2 = 13, + DP_OVERHEAD = 12, + DP_HEAD = 11, + DP_SHOULDERS = 10, + DP_CHEST = 9, + DP_BELLY = 8, + DP_WAIST = 7, + DP_THIGH = 6, + DP_KNEE = 5, + DP_CALF = 4, + DP_FEET = 3, + DP_ANKLE = 2, + DP_TOE = 1, + DP_NONE = 0, }; // empty types @@ -1369,8 +1392,11 @@ enum FLAG { // map flags F_MAPCOORDS, // v0+v1 are x/y coords for this map area F_ROOMEXIT, // there is an exit from room v0 at x=v1,y=v2 + F_NEWWATERDEPTH, // temp flag for the spread of f_deepwater obs. + // v0+1 are x/y, v2 is new depth. // object flags F_DEAD, // object will be removed + F_ONEPERCELL, // only one of these objects can exist per cell F_CREATEDBY, // object was made by lf id v0, text=real lfname F_ENCHANTABLE, // object can get +1/-1 ect F_STACKABLE, // can stack multiple objects togethr @@ -1389,6 +1415,7 @@ enum FLAG { // (optional) text = lfid of lf who left this. // should only be used for SCENT, not footprints. F_NOFEEL, // when blind, don't show "you can feel xxx" + F_FEELTEXT, // when blind, show "you can feel"+f->text // for items in shops F_SHOPITEM, // causes shops to show this item as identified F_VALUE, // how much an item is worth (over its base weight+material) @@ -1514,6 +1541,7 @@ enum FLAG { F_REDUCEMOVEMENT, // time to move off here is multiplied by v0. F_RESTRICTMOVEMENT, // must pass a diff=v0 STR check to move off it. // if v1 is B_TRUE, then it takes 1 damage if you fail. + // if v2 is TRUE, it affects flying creatures // // for multiple objects, each one adds half its difficulty @@ -1770,7 +1798,10 @@ enum FLAG { F_MOVESPEED, // override default move speed F_ACTIONSPEED, // override default action speed F_SPELLSPEED, // override default spellcast speed (ie. movespeed) - F_RARITY, // val[0] = habitat, val[1] = rarity + F_RARITY, // val[0] = habitat, val[1] = rarity% + // opt. val[2] = commonality (enum RARITY RR_xxx) + // NA means rr_common + F_NUMAPPEAR, // when randomly appearing, can have > 1. val[0] = min, val[1] = max F_MINIONS, // val0 % chance of appearing with v1-v2 lf of type text F_HITDICE, // val0: # d4 to roll for maxhp per level. val1: +xx @@ -1967,6 +1998,8 @@ enum FLAG { // vault flags F_AUTODOORS, // automatically create at least one door + // v0 is pct chance of door (as opposed to empty + // doorway with no door). F_AUTOPOPULATE, // fill this vault with obs/mons/pillars like normal rooms F_VAULTATOB, // v0/1=x/y, v1=pctchance, text=obname F_VAULTATLF, // v0/1=x/y, v1=pctchance, text=lfname @@ -2201,6 +2234,7 @@ typedef struct map_s { int id; int region; int depth; + int nrooms; // how many rooms on this map char *name; // name of this map enum HABITAT habitat; // eg. dungeon, forest, etc unsigned int seed; @@ -2296,6 +2330,7 @@ typedef struct celltype_s { char *name; // name of cell type int solid; // can you walk through it? int transparent; // can you see through it? + int floorheight; // 0 is default. <0 is low. struct material_s *material; struct flagpile_s *flags; diff --git a/flag.c b/flag.c index a93d1bc..a9f13e6 100644 --- a/flag.c +++ b/flag.c @@ -205,12 +205,12 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, if ((gamemode == GM_GAMESTARTED) && (redrawscreenatend || redrawstatatend || redolight)) { if (redolight) { - dblog("CALCINGLIGHT from flag\n"); + //dblog("CALCINGLIGHT from flag\n"); redrawscreenatend = B_TRUE; calclight(redolight); precalclos(player); } - dblog("DRAWINGSCREEN from flag\n"); + //dblog("DRAWINGSCREEN from flag\n"); if (redrawscreenatend) needredraw = B_TRUE; if (redrawstatatend) statdirty = B_TRUE; diff --git a/io.c b/io.c index c9ffbcb..4738bef 100644 --- a/io.c +++ b/io.c @@ -52,6 +52,7 @@ extern enum OBCLASS sortorder[]; extern knowledge_t *knowledge; extern objecttype_t *objecttype; extern command_t *firstcommand; +extern vault_t *firstvault; extern skill_t *firstskill; extern enum GAMEMODE gamemode; @@ -2624,6 +2625,24 @@ int askobjectmulti(obpile_t *op, char *prompt, long opts) { return B_FALSE; } +vault_t *askvault(char *prompttext) { + vault_t *v; + + // make list of all vaults + initprompt(&prompt, prompttext); + for (v = firstvault ; v ; v = v->next) { + addchoice(&prompt, 'a', v->id, NULL, v); + } + if (prompt.nchoices == 0) { + msg("Error - no vaults found."); + return NULL; + } + getchoicestr(&prompt, B_FALSE, B_TRUE); + + v = (vault_t *)prompt.result; + return v; +} + void centre(WINDOW *win, int y, char *format, ... ) { int w; char buf[BUFLEN]; @@ -3394,9 +3413,7 @@ void describeob(object_t *o) { // wait for key getch(); - real_clearmsg(B_TRUE); - needredraw = B_TRUE; - drawscreen(); + restoregamewindows(); } void describespell(objecttype_t *ot) { @@ -3449,8 +3466,7 @@ void describespell(objecttype_t *ot) { // wait for key getch(); real_clearmsg(B_TRUE); - needredraw = B_TRUE; - drawscreen(); + restoregamewindows(); } void doattackcell(char dirch) { @@ -4070,7 +4086,7 @@ void dolook(cell_t *where, int onpurpose) { if (f) { // doens't matter if you're blind getobname(o, buf, o->amt); - msg("There is %s here%c", buf, f->text[0]); + msg("There %s %s here%c", (o->amt == 1) ? "is" : "are", buf, f->text[0]); interrupt(player); seensomething = B_TRUE; } else { @@ -4091,7 +4107,16 @@ void dolook(cell_t *where, int onpurpose) { if (numobs > 0) { if (numobs == 1) { if (!hasflag(firstob->flags, F_THEREISHERE)) { - getobname(firstob, buf, firstob->amt); + if (streq(seeverb, "feel")) { + f = hasflag(firstob->flags, F_FEELTEXT); + if (f) { + strcpy(buf, f->text); + } else { + getobname(firstob, buf, firstob->amt); + } + } else { + getobname(firstob, buf, firstob->amt); + } msg("You %s %s here.", seeverb, buf); } } else if ((numobs > 1) && (numobs <= 3)) { @@ -4124,7 +4149,8 @@ void dolook(cell_t *where, int onpurpose) { // if wantunknown is set, lsit spells we DONT know. // otherwise list spells we DO know. -void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2, enum SPELLSCHOOL wantschool, int wantunknown, int wantinvalid) { +// only include spells which cost <= mpcutoff +void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2, enum SPELLSCHOOL wantschool, int wantunknown, int wantinvalid, int mpcutoff) { char ch; flag_t *f; char buf[BUFLEN]; @@ -4150,12 +4176,6 @@ void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2, if ((i == SS_DIVINE) && !hasjob(lf, J_GOD)) { continue; } - // we can't cast spells from this school? - if (getschoolskill(i) != SK_NONE) { - if (!getskill(lf, getschoolskill(i))) { - continue; - } - } for (lev = 0; lev <= MAXSPELLLEV; lev++) { // get list of spells/abilities we can cast at will for (ot = objecttype ; ot ; ot = ot->next) { @@ -4188,6 +4208,13 @@ void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2, } // end if spell/ability } // end foreach objecttype + // if we can't cast spells from this school, then just go to next spell. + if (getschoolskill(i) != SK_NONE) { + if (!getskill(lf, getschoolskill(i))) { + continue; + } + } + if (!lfhasflag(lf, F_NOSPELLS)) { // get list of spells we can cast using mp for (ot = objecttype ; ot ; ot = ot->next) { @@ -4222,7 +4249,7 @@ void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2, } else { getspellcosttext(lf, ot->id, power, mpdesc[nposs]); } - if (lf->mp >= mpcost[nposs]) { + if (mpcost[nposs] <= mpcutoff) { validspell[nposs] = B_TRUE; } else { validspell[nposs] = B_FALSE; @@ -4298,7 +4325,7 @@ void domagic(enum OBTYPE spellid, int cellx, int celly) { // init the prompt if required. if (spellid == OT_NONE) { - makespellchoicelist(&prompt, player, "Use which spell/ability:","Describe which spell/ability:", SS_NONE, B_FALSE, B_TRUE); + makespellchoicelist(&prompt, player, "Use which spell/ability:","Describe which spell/ability:", SS_NONE, B_FALSE, B_TRUE, player->mp); } finished = B_FALSE; @@ -4366,7 +4393,7 @@ void domemmagic(void) { char ch; int slot; objecttype_t *ot; - makespellchoicelist(&prompt, player, "Memorise which spell/ability:","Describe which spell/ability",SS_NONE, B_FALSE, B_TRUE); + makespellchoicelist(&prompt, player, "Memorise which spell/ability:","Describe which spell/ability",SS_NONE, B_FALSE, B_TRUE, player->maxmp); if (prompt.nchoices <= 0) { msg("You don't have any spells or abilities!"); return; @@ -4449,8 +4476,8 @@ int dopickup(obpile_t *op) { if (o->amt == 1) { // just get it howmany = ALL; - retobs[0] = op->first; - retobscount[0] = op->first->amt; + retobs[0] = o; + retobscount[0] = o->amt; nretobs = 1; needtoask = B_FALSE; } @@ -4507,6 +4534,7 @@ void doenter(lifeform_t *lf) { enterob = hasob(lf->cell->obpile, OT_VENDINGMACHINE); if (enterob) { dovendingmachine(lf, enterob); + restoregamewindows(); return; } enterob = hasob(lf->cell->obpile, OT_PORTAL); @@ -4518,7 +4546,6 @@ void doenter(lifeform_t *lf) { // try to go down dostairs(D_DOWN); } - restoregamewindows(); } void doexplain(char *question) { @@ -5465,6 +5492,7 @@ char getchoicestr(prompt_t *prompt, int useshortcuts, int showallatstart) { curs_set(1); sel = -1; while (sel == -1) { + int foundfirstvalid = B_FALSE; int atbottom; // show choices which match our input string if (showall) { @@ -5474,6 +5502,7 @@ char getchoicestr(prompt_t *prompt, int useshortcuts, int showallatstart) { nextpage = -1; nvalid = 0; + foundfirstvalid = B_FALSE; atbottom = B_FALSE; for (i = 0; i < prompt->nchoices; i++) { if (showall) { @@ -5503,6 +5532,8 @@ char getchoicestr(prompt_t *prompt, int useshortcuts, int showallatstart) { matched = strpixmatch(prompt->choice[i].text, inpstring); if (matched) { + prompt->choice[i].valid = B_TRUE; + nvalid++; if (showall) { // if we haven't printed the heading yet... if (gotheadings && !doneheading) { @@ -5516,12 +5547,14 @@ char getchoicestr(prompt_t *prompt, int useshortcuts, int showallatstart) { } // only print if we're not off the bottom if ((i >= first) && !atbottom) { + if (nvalid && !foundfirstvalid) setcol(mainwin, C_BOLDGREEN); mvwprintw(mainwin, y, 0, "%s%s", gotheadings ? " " : "", prompt->choice[i].desc); y++; + if (nvalid && !foundfirstvalid) unsetcol(mainwin, C_BOLDGREEN); + + foundfirstvalid = B_TRUE; } } - prompt->choice[i].valid = B_TRUE; - nvalid++; } else { prompt->choice[i].valid = B_FALSE; } @@ -5628,15 +5661,15 @@ char getchoicestr(prompt_t *prompt, int useshortcuts, int showallatstart) { inpstring[strlen(inpstring)-1] = '\0'; } } else if (ch == 10) { // enter - // exactly one valid choice? - if (nvalid == 1) { + // valid choices? + if (nvalid) { for (i = 0; i < prompt->nchoices; i++) { if (prompt->choice[i].valid) { sel = i; break; } } - } else if (nvalid == 0) { + } else if (nvalid == 0) { // no choices? // cancel sel = -1; break; diff --git a/io.h b/io.h index f8065d0..85876e7 100644 --- a/io.h +++ b/io.h @@ -23,6 +23,7 @@ int askobjectmulti(obpile_t *op, char *prompt, long opts); char askchar(char *prompt, char *validchars, char *def, int showchars); cell_t *askcoords(char *prompt, int targettype, lifeform_t *srclf, int maxrange, enum LOFTYPE loftype, int wanttrail); char *askstring(char *prompt, char punc, char *retbuf, int retbuflen, char *def); +vault_t *askvault(char *prompttext); void centre(WINDOW *win, int y, char *format, ... ); int chartodir(char ch); char checkforkey(void); @@ -33,6 +34,7 @@ void clearretobs(void); void cls(void); int contains(enum OBCLASS *array, int nargs, enum OBCLASS want); void describeob(object_t *o); +void describespell(objecttype_t *ot); void doattackcell(char dirch); void doclose(void); void docomms(void); @@ -86,7 +88,7 @@ void initgfx(void); void initprompt(prompt_t *p, char *q1); int keycodetokey(int keycode); void listobs(WINDOW *win, object_t **mylist, int *sellist, int *selcount, int firstob, int *counter, int lastline, int *y, char *myletters, int forpickup, int showpoints); -void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2, enum SPELLSCHOOL wantschool, int wantunknown, int wantinvalid); +void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2, enum SPELLSCHOOL wantschool, int wantunknown, int wantinvalid, int mpcutoff); void more(void); void warn(char *format, ... ); void msg(char *format, ... ); diff --git a/lf.c b/lf.c index 04feb70..7073778 100644 --- a/lf.c +++ b/lf.c @@ -656,6 +656,19 @@ int canlearn(lifeform_t *lf, enum SKILL skid) { return B_FALSE; } +int canopendoors(lifeform_t *lf) { + if (lf) { + if (!lfhasflag(lf, F_HUMANOID)) { + return B_FALSE; + } + if (lfhasflagval(lf, F_NOBODYPART, BP_HANDS, NA, NA, NULL)) { + return B_FALSE; + } + } + + return B_TRUE; +} + int canpickup(lifeform_t *lf, object_t *o, int amt) { reason = E_OK; @@ -1132,7 +1145,7 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar // cast the spell addflag(lf->flags, F_CASTINGSPELL, sid, NA, NA, NULL); - rv = dospelleffects(lf, sid, power, targlf, targob, targcell, B_UNCURSED, NULL); + rv = dospelleffects(lf, sid, power, targlf, targob, targcell, B_UNCURSED, NULL, B_FALSE); f = lfhasflag(lf, F_CASTINGSPELL); if (f) { killflag(f); @@ -1183,19 +1196,37 @@ int checkfordrowning(lifeform_t *lf, object_t *o) { // will you drown? if (depth >= DP_HEAD) { if (!slev && !lfhasflag(lf, F_BREATHWATER)) { - // you drown. - if (isplayer(lf)) { - msg("You drown."); - didsomething = B_TRUE; - } else if (cansee(player, lf)) { - char lfname[BUFLEN]; - getlfname(lf, lfname); - msg("%s drowns.",lfname); - didsomething = B_TRUE; + int damamt; + + // take drowning damage. generally you'll die + // in around 3-4 turns. + damamt = lf->maxhp / (getattr(lf, A_CON) / 3); + + if (damamt >= lf->hp) { + if (isplayer(lf)) { + msg("You drown."); + didsomething = B_TRUE; + } else if (cansee(player, lf)) { + char lfname[BUFLEN]; + getlfname(lf, lfname); + msg("%s drowns.",lfname); + didsomething = B_TRUE; + } + addflag(lf->flags, F_NODEATHANNOUNCE, B_TRUE, NA, NA, NULL); + lf->hp = 0; + setlastdam(lf, "drowning"); + } else { + if (isplayer(lf)) { + msg("You are drowning!"); + didsomething = B_TRUE; + } else if (cansee(player, lf)) { + char lfname[BUFLEN]; + getlfname(lf, lfname); + msg("%s is drowning!",lfname); + didsomething = B_TRUE; + } + losehp(lf, damamt, DT_DIRECT, NULL, "drowning"); } - addflag(lf->flags, F_NODEATHANNOUNCE, B_TRUE, NA, NA, NULL); - lf->hp = 0; - setlastdam(lf, "drowning"); } } @@ -1598,9 +1629,6 @@ void die(lifeform_t *lf) { strcpy(corpseprefix, ""); switch (lf->lastdamtype) { - case DT_FIRE: - strcat(corpseprefix, "flaming "); - break; case DT_COLD: strcat(corpseprefix, "frozen "); break; @@ -1798,8 +1826,8 @@ void dumplev(void) { // NOTE: this code copied from getrandomrace(), which is used by addmonster(). for (i = 1; i <= 25; i++) { int min,max,prevmin,prevmax; - getrarity(i-1, &prevmin, &prevmax, RARITYVARIANCELF, B_FALSE); - getrarity(i, &min, &max, RARITYVARIANCELF, B_FALSE); + getrarityrange(i-1, &prevmin, &prevmax, RARITYVARIANCELF, B_FALSE); + getrarityrange(i, &min, &max, RARITYVARIANCELF, B_FALSE); fprintf(logfile, "Dlev %d (rar >= %d): ",i,min); for (r = firstrace ; r; r = r->next) { int rarity = 0; @@ -1835,8 +1863,8 @@ void dumplev(void) { // NOTE: this code copied from getrandomrace(), which is used by addmonster(). for (i = 1; i <= 25; i++) { int min,max,prevmin,prevmax; - getrarity(i-1, &prevmin, &prevmax, RARITYVARIANCEOB, B_FALSE); - getrarity(i, &min, &max, RARITYVARIANCEOB, B_FALSE); + getrarityrange(i-1, &prevmin, &prevmax, RARITYVARIANCEOB, B_FALSE); + getrarityrange(i, &min, &max, RARITYVARIANCEOB, B_FALSE); fprintf(logfile, "Dlev %d (rar >= %d): ",i,min); for (ot = objecttype ; ot; ot = ot->next) { int rarity = 0; @@ -2148,6 +2176,22 @@ int eat(lifeform_t *lf, object_t *o) { return B_FALSE; } +void enhancerandomskill(lifeform_t *lf) { + flag_t *f; + enum SKILL poss[MAXSKILLS]; + int nposs = 0; + int sel; + for (f = lf->flags->first ; f ; f = f->next) { + if ((f->id == F_HASSKILL) && (f->val[1] != PR_MASTER)) { + poss[nposs] = f->val[0]; + nposs++; + } + } + sel = rnd(0,nposs-1); + + giveskill(lf, poss[sel]); +} + void enhanceskills(lifeform_t *lf) { enum SKILL whichsk; flag_t *f; @@ -2178,49 +2222,6 @@ void enhanceskills(lifeform_t *lf) { more(); } - // give job-based level rewards - f = levelabilityready(lf); - while (f) { - if (f->id == F_LEVABIL) { - addflag(lf->flags, F_CANWILL, f->val[1], f->val[2], f->val[2], f->text); - } else if (f->id == F_LEVFLAG) { - addflag(lf->flags, f->val[1], f->val[2], NA, NA, f->text); - } else if (f->id == F_LEVSKILL) { - giveskill(lf, f->val[1]); - } else if (f->id == F_LEVSPELL) { - addflag(lf->flags, F_CANCAST, f->val[1], NA, NA, NULL); - } else if (f->id == F_LEVSPELLSCHOOL) { // select a spell from school - if (isplayer(lf)) { - makespellchoicelist(&prompt, player, "Learn which new spell:","Describe which spell:", f->val[1], B_TRUE, B_FALSE); - if (prompt.nchoices > 0) { - objecttype_t *ot; - getchoicestr(&prompt, B_TRUE, B_TRUE); - ot = prompt.result; - if (ot) { - addflag(lf->flags, F_CANCAST, ot->id, NA, NA, NULL); - } - } else { - msg("There are no new spells for you to learn at this time."); - } - } else { - makespellchoicelist(&prompt, player, "xx","xx:", f->val[1], B_FALSE, B_FALSE); - if (prompt.nchoices > 0) { - objecttype_t *ot; - // pick one randomly - ot = (objecttype_t *)prompt.choice[rnd(0,prompt.nchoices)].data; - if (ot) { - addflag(lf->flags, F_CANCAST, ot->id, NA, NA, NULL); - } - } - } - } - f->lifetime = LEVABILITYDONE; // mark as done. - - // get next one - f = levelabilityready(lf); - } - // now refresh them all for next level. - refreshlevelabilities(lf); // increase str/int etc if we can f = lfhasflag(lf, F_STATGAINREADY); @@ -2254,6 +2255,11 @@ void enhanceskills(lifeform_t *lf) { f = lfhasflag(lf, F_STATGAINREADY); } + // enhance a random skill every 2 levels (ie. 3/5/7/etc) + if (((lf->level + 1) % 2) == 0) { + enhancerandomskill(lf); + } + // now ask about learning/enhancing skills if (isplayer(lf)) { char eorl = 'e'; @@ -2364,21 +2370,64 @@ void enhanceskills(lifeform_t *lf) { statdirty = B_TRUE; } else { // monsters will just enhance a random skill, they never learn new ones. - enum SKILL poss[MAXSKILLS]; - int nposs = 0; - int sel; - for (f = lf->flags->first ; f ; f = f->next) { - if ((f->id == F_HASSKILL) && (f->val[1] != PR_MASTER)) { - poss[nposs] = f->val[0]; - nposs++; - } - } - sel = rnd(0,nposs-1); - - giveskill(lf, poss[sel]); + enhancerandomskill(lf); lf->skillpoints--; } // end if isplayer + // give job-based level rewards + f = levelabilityready(lf); + while (f) { + if (f->id == F_LEVABIL) { + addflag(lf->flags, F_CANWILL, f->val[1], f->val[2], f->val[2], f->text); + } else if (f->id == F_LEVFLAG) { + addflag(lf->flags, f->val[1], f->val[2], NA, NA, f->text); + } else if (f->id == F_LEVSKILL) { + giveskill(lf, f->val[1]); + } else if (f->id == F_LEVSPELL) { + addflag(lf->flags, F_CANCAST, f->val[1], NA, NA, NULL); + } else if (f->id == F_LEVSPELLSCHOOL) { // select a spell from school + if (isplayer(lf)) { + int done = B_FALSE; + while (!done) { + makespellchoicelist(&prompt, player, "Learn which new spell:","Describe which spell:", f->val[1], B_TRUE, B_FALSE, player->maxmp); + if (prompt.nchoices > 0) { + objecttype_t *ot; + getchoicestr(&prompt, B_TRUE, B_TRUE); + ot = prompt.result; + if (ot) { + if (prompt.whichq == 0) { // learn the spell + addflag(lf->flags, F_CANCAST, ot->id, NA, NA, NULL); + done = B_TRUE; + } else { + describespell(ot); + } + } + } else { + msg("There are no new spells for you to learn at this time."); + done = B_TRUE; + } + } + } else { + // monster gets random spell + makespellchoicelist(&prompt, lf, "xx","xx:", f->val[1], B_TRUE, B_FALSE, lf->maxmp); + if (prompt.nchoices > 0) { + objecttype_t *ot; + // pick one randomly + ot = (objecttype_t *)prompt.choice[rnd(0,prompt.nchoices)].data; + if (ot) { + addflag(lf->flags, F_CANCAST, ot->id, NA, NA, NULL); + } + } + } + } + f->lifetime = LEVABILITYDONE; // mark as done. + + // get next one + f = levelabilityready(lf); + } + // now refresh them all for next level. + refreshlevelabilities(lf); + killflagsofid(lf->flags, F_HASNEWLEVEL); // ready for another level? @@ -2949,6 +2998,7 @@ int getactspeed(lifeform_t *lf) { return speed; } +// only include allies which will follow you up/down stairs etc void getadjallies(lifeform_t *lf, lifeform_t **adjally, int *nadjallies) { int d; for (d = DC_N; d <= DC_NW; d++) { @@ -2956,7 +3006,7 @@ void getadjallies(lifeform_t *lf, lifeform_t **adjally, int *nadjallies) { c = getcellindir(lf->cell, d); if (c && c->lf) { if (areallies(lf, c->lf) || areenemies(lf, c->lf)) { - if (!isimmobile(c->lf)) { + if (!isimmobile(c->lf) && cansee(c->lf, lf)) { adjally[*nadjallies] = c->lf; (*nadjallies)++; } @@ -3105,7 +3155,9 @@ int getattackspeed(lifeform_t *lf) { w = getweapon(lf); if (w) { - speed *= ((float)getobattackdelay(w) / 100.0); + int del; + del = getobattackdelay(w); + speed = pctof(del, speed); } return (int)speed; @@ -3852,7 +3904,7 @@ int getminions(lifeform_t *lf, lifeform_t **minion, int *nminions) { } int getnightvisrange(lifeform_t *lf) { - int range = -1; // default + int range = 1; // default flag_t *f; f = lfhasflag(lf, F_SEEINDARK); @@ -4172,6 +4224,7 @@ int getvisrange(lifeform_t *lf) { int getmovespeed(lifeform_t *lf) { int speed = 0; flag_t *f; + object_t *o; f = lfhasflag(lf, F_MOVESPEED); if (f) { @@ -4216,6 +4269,14 @@ int getmovespeed(lifeform_t *lf) { if (speed < 1) speed = 1; + // reducemovement flags? + o = hasobwithflag(lf->cell->obpile, F_REDUCEMOVEMENT); + if (o) { + f = hasflag(o->flags, F_REDUCEMOVEMENT); + speed += (f->val[0] * SPEEDUNIT); + } + + // water adjustspeedforwater(lf, &speed); @@ -4625,6 +4686,7 @@ race_t *getrandomrace(cell_t *c, int forcedepth) { int db = B_FALSE; int depth; int raritymin,raritymax; + enum RARITY wantrr = RR_COMMON; // determine rarity of lf to generate if (forcedepth != NA) { @@ -4633,9 +4695,15 @@ race_t *getrandomrace(cell_t *c, int forcedepth) { depth = getmapdifficulty(c ? c->map : NULL); } - getrarity(depth, &raritymin, &raritymax, RARITYVARIANCELF, B_TRUE); + getrarityrange(depth, &raritymin, &raritymax, RARITYVARIANCELF, B_TRUE); - if (db) dblog("finding random lf with rarity val %d-%d\n",raritymin,raritymax); + // pick rr... + wantrr = RR_COMMON; + while ((wantrr < RR_VERYRARE) && onein(3)) { + wantrr++; + } + + if (db) dblog("finding random lf with rarity val %d-%d and rr <= %d\n",raritymin,raritymax, wantrr); // try to find a lf of this type which will @@ -4658,7 +4726,9 @@ race_t *getrandomrace(cell_t *c, int forcedepth) { if (rarflag) { if ((rarflag->val[1] >= raritymin) && (rarflag->val[1] <= raritymax)) { - valid = B_TRUE; + if ((rarflag->val[2] == NA) || (rarflag->val[2] <= wantrr)) { + valid = B_TRUE; + } } } @@ -5337,6 +5407,7 @@ int giveskill(lifeform_t *lf, enum SKILL id) { } if (isplayer(lf) && (gamemode == GM_GAMESTARTED)) { msg("You have learned the %s %s skill!", getskilllevelname(f->val[1]), getskillname(sk->id)); + more(); } statdirty = B_TRUE; // in case skill changes your stats } else { @@ -5381,11 +5452,12 @@ int giveskill(lifeform_t *lf, enum SKILL id) { if (f->val[1] == PR_NOVICE) { msg("You now make basic maps of your surroundings."); } else if (f->val[1] == PR_BEGINNER) { - msg("Your map will now show the location of staircases."); + msg("Your map now shows the location of staircases."); } else if (f->val[1] == PR_ADEPT) { - msg("Your map will now show the location of doors."); + msg("Your map now shows the location of doors."); } else if (f->val[1] == PR_SKILLED) { - msg("You will no longer forget your surroundings."); + //msg("You will no longer forget your surroundings."); + addflag(lf->flags, F_PHOTOMEM, B_TRUE, NA, NA, NULL); } else if (f->val[1] == PR_EXPERT) { msg("Your map will now show the location of objects."); } @@ -6074,6 +6146,11 @@ int haslof(cell_t *src, cell_t *dest, enum LOFTYPE loftype, cell_t **newdest) { cell_t *retcell[MAXRETCELLS]; reason = E_OK; + + if (loftype == LOF_DONTNEED) { + return B_TRUE; + } + if (newdest) *newdest = src; //if (!viewer) return B_FALSE; @@ -6409,7 +6486,8 @@ void initjobs(void) { addflag(lastjob->flags, F_STARTSKILL, SK_ATHLETICS, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_ARMOUR, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_SHIELDS, PR_NOVICE, NA, NULL); - addflag(lastjob->flags, F_STARTSKILL, SK_LORE_HUMANOID, PR_NOVICE, NA, NULL); + addflag(lastjob->flags, F_STARTSKILL, SK_LORE_HUMANOID, PR_ADEPT, NA, NULL); + addflag(lastjob->flags, F_STARTSKILL, SK_LORE_NATURE, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_TRACKING, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_CARTOGRAPHY, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_COOKING, NA, NA, NULL); @@ -6453,6 +6531,7 @@ void initjobs(void) { addflag(lastjob->flags, F_STARTSKILL, SK_SWIMMING, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_TECHUSAGE, PR_BEGINNER, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_TRACKING, PR_NOVICE, NA, NULL); + addflag(lastjob->flags, F_STARTSKILL, SK_LORE_HUMANOID, PR_SKILLED, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_BACKSTAB, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_CARTOGRAPHY, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_COOKING, NA, NA, NULL); @@ -6470,7 +6549,7 @@ void initjobs(void) { addflag(lastjob->flags, F_STARTATT, A_DEX, DX_AVERAGE, NA, NULL); addflag(lastjob->flags, F_STARTATT, A_IQ, IQ_ENLIGHTENED, NA, NULL); // skills - addflag(lastjob->flags, F_STARTSKILL, SK_LORE_NATURE, PR_ADEPT, NA, NULL); + addflag(lastjob->flags, F_STARTSKILL, SK_LORE_NATURE, PR_SKILLED, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_STAVES, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_CARTOGRAPHY, PR_ADEPT, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_TRACKING, PR_NOVICE, NA, NULL); @@ -6521,6 +6600,7 @@ void initjobs(void) { 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_LORE_HUMANOID, PR_NOVICE, NA, NULL); + addflag(lastjob->flags, F_STARTSKILL, SK_LORE_NATURE, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_SWIMMING, PR_BEGINNER, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_ATHLETICS, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_CARTOGRAPHY, NA, NA, NULL); @@ -6556,6 +6636,8 @@ void initjobs(void) { addflag(lastjob->flags, F_STARTSKILL, SK_LONGBLADES, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_UNARMED, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_SWIMMING, PR_ADEPT, NA, NULL); + addflag(lastjob->flags, F_STARTSKILL, SK_LORE_HUMANOID, PR_NOVICE, NA, NULL); + addflag(lastjob->flags, F_STARTSKILL, SK_LORE_UNDEAD, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_ATHLETICS, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_BACKSTAB, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_LISTEN, NA, NA, NULL); @@ -6579,6 +6661,7 @@ void initjobs(void) { addflag(lastjob->flags, F_STARTSKILL, SK_LOCKPICKING, PR_BEGINNER, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_SPOTHIDDEN, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_SHORTBLADES, PR_NOVICE, NA, NULL); + addflag(lastjob->flags, F_STARTSKILL, SK_LORE_HUMANOID, PR_BEGINNER, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_ATHLETICS, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_CHANNELING, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_COOKING, NA, NA, NULL); @@ -6622,6 +6705,8 @@ void initjobs(void) { // can detect magic objects addflag(lastjob->flags, F_STARTSKILL, SK_CARTOGRAPHY, PR_ADEPT, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_LORE_ARCANA, PR_BEGINNER, NA, NULL); + addflag(lastjob->flags, F_STARTSKILL, SK_LORE_UNDEAD, PR_NOVICE, NA, NULL); + addflag(lastjob->flags, F_STARTSKILL, SK_LORE_DEMONS, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_SPELLCASTING, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_CHANNELING, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_STAVES, PR_NOVICE, NA, NULL); @@ -6682,6 +6767,7 @@ void initrace(void) { // races / monsters addrace(R_HUMAN, "human", 75, '@', C_GREY, MT_FLESH, RC_HUMANOID); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 60, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_FOREST, 75, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); addflag(lastrace->flags, F_HITDICE, 2, 2, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); @@ -6887,6 +6973,7 @@ void initrace(void) { addrace(R_GIANTHILL, "hill giant", 160, 'H', C_GREY, MT_FLESH, RC_HUMANOID); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 55, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_FOREST, 55, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_HUGE, NA, NA, NULL); addflag(lastrace->flags, F_HITDICE, 19, NA, NA, NULL); @@ -7020,6 +7107,7 @@ void initrace(void) { addflag(lastrace->flags, F_NUMAPPEAR, 2, 3, NA, ""); addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 72, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_FOREST, 72, NA, NULL); addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HITDICE, 8, NA, NA, NULL); addflag(lastrace->flags, F_ARMOURRATING, 9, NA, NA, NULL); @@ -7043,6 +7131,7 @@ void initrace(void) { 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, 68, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_FOREST, 68, NA, NULL); addflag(lastrace->flags, F_HITDICE, 6, NA, NA, NULL); addflag(lastrace->flags, F_ARMOURRATING, 9, NA, NA, NULL); addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL); @@ -7071,6 +7160,7 @@ void initrace(void) { 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, 65, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_FOREST, 65, NA, NULL); addflag(lastrace->flags, F_HITDICE, 10, NA, NA, NULL); addflag(lastrace->flags, F_ARMOURRATING, 9, NA, NA, NULL); addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL); @@ -7094,6 +7184,7 @@ void initrace(void) { addrace(R_GOBLIN, "goblin", 20, 'g', C_BROWN, MT_FLESH, RC_HUMANOID); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 87, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_FOREST, 87, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL); addflag(lastrace->flags, F_HITDICE, 1, 3, NA, NULL); addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL); @@ -7121,6 +7212,7 @@ void initrace(void) { addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "goblin corpse"); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_FOREST, 75, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL); addflag(lastrace->flags, F_HITDICE, 3, 5, NA, NULL); addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL); @@ -7147,6 +7239,7 @@ void initrace(void) { addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "goblin corpse"); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_FOREST, 70, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL); addflag(lastrace->flags, F_HITDICE, 3, 7, NA, NULL); addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL); @@ -7176,6 +7269,7 @@ void initrace(void) { addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "goblin corpse"); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 63, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_FOREST, 63, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL); addflag(lastrace->flags, F_HITDICE, 5, 6, NA, NULL); addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL); @@ -7202,6 +7296,7 @@ void initrace(void) { addrace(R_HOBGOBLIN, "hobgoblin", 90, 'g', C_GREEN, MT_FLESH, RC_HUMANOID); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 73, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_FOREST, 73, NA, NULL); addflag(lastrace->flags, F_NUMAPPEAR, 1, 2, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); addflag(lastrace->flags, F_HITDICE, 2, 3, NA, NULL); @@ -7231,6 +7326,7 @@ void initrace(void) { lastrace->baseid = R_HOBGOBLIN; addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 60, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_FOREST, 60, NA, NULL); addflag(lastrace->flags, F_NUMAPPEAR, 1, 2, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); addflag(lastrace->flags, F_HITDICE, 2, 3, NA, NULL); @@ -7275,10 +7371,10 @@ void initrace(void) { addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_DOPEY, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_DEX, DX_NIMBLE, NA, NULL); addflag(lastrace->flags, F_STARTOBDT, 20, DT_PIERCE, NA, NULL); - addflag(lastrace->flags, F_STARTOBCLASS, 40, OC_POTION, NA, NULL); + addflag(lastrace->flags, F_STARTOBCLASS, 25, OC_POTION, NA, NULL); addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "1-3 darts"); - addflag(lastrace->flags, F_STARTOB, 33, NA, NA, "javelin"); - addflag(lastrace->flags, F_STARTOB, 33, NA, NA, "buckler"); + addflag(lastrace->flags, F_STARTOB, 10, NA, NA, "javelin"); + addflag(lastrace->flags, F_STARTOB, 15, 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, 3, NA, "shouts^a shout"); @@ -7314,6 +7410,7 @@ void initrace(void) { 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, 72, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_FOREST, 72, NA, NULL); addflag(lastrace->flags, F_HITDICE, 6, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, ST_MIGHTY, NA, NULL); @@ -8280,7 +8377,7 @@ void initrace(void) { addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, ""); - addflag(lastrace->flags, F_RARITY, H_DUNGEON, 90, NA, ""); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, 80, NA, ""); addflag(lastrace->flags, F_RARITY, H_FOREST, 80, NA, ""); addflag(lastrace->flags, F_HITDICE, 2, 1, NA, ""); addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d4"); @@ -9576,31 +9673,28 @@ void adjustspeedforwater(lifeform_t *lf, int *speed) { flag_t *f; if (!isairborne(lf)) { for (o = lf->cell->obpile->first ; o ; o = o->next) { - f = hasflag(o->flags, F_REDUCEMOVEMENT); + f = hasflag(o->flags, F_DEEPWATER); if (f) { - if (hasflag(o->flags, F_DEEPWATER)) { - int modamt = 0; - // water - if (isaquatic(lf)) { - modamt = 0; - } else { - switch (getskill(lf, SK_SWIMMING)) { - default: - case PR_NOVICE: - case PR_INEPT: modamt = f->val[0]; break; // normal penalty - case PR_BEGINNER: modamt = f->val[0] - 2; break; - case PR_ADEPT: modamt = 0; break; - case PR_SKILLED: modamt = -1; break; - case PR_EXPERT: modamt = -2; break; - case PR_MASTER: modamt = -2; break; - } - } - limit(&modamt, 0, 5); - *speed += (modamt * SPEEDUNIT); + int modamt; + modamt = (f->val[0] / 5); // ie. 0 - 4 + if (modamt > 4) modamt = 4; + // water + if (isaquatic(lf)) { + modamt = 0; } else { - // something else - *speed += (f->val[0] * SPEEDUNIT); + switch (getskill(lf, SK_SWIMMING)) { + default: + case PR_NOVICE: + case PR_INEPT: break; // normal penalty + case PR_BEGINNER: modamt -= 2; if (modamt < 0) modamt = 0; break; // bit less + case PR_ADEPT: modamt = 0; break; // nothing + case PR_SKILLED: modamt = -1; break; // faster + case PR_EXPERT: modamt = -2; break; // faster + case PR_MASTER: modamt = -2; break; // faster + } } + limit(&modamt, 0, 5); + *speed += (modamt * SPEEDUNIT); } } } @@ -9981,8 +10075,7 @@ int isswimming(lifeform_t *lf) { if (gamemode != GM_GAMESTARTED) { return B_FALSE; } - if (!isairborne(lf) && - hasobwithflag(lf->cell->obpile, F_DEEPWATER) && + if (!isairborne(lf) && (getcellwaterdepth(lf->cell, lf) >= DP_WAIST) && getskill(lf, SK_SWIMMING)) { return B_TRUE; } @@ -10254,7 +10347,7 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml msg("%s releases a cloud of purple spores!", lfname); drawscreen(); } - spellcloud(lf->cell, 3, '\0', C_MAGENTA, OT_S_SLEEP, 8); + spellcloud(lf->cell, 3, '\0', C_MAGENTA, OT_S_SLEEP, 8, B_TRUE); } @@ -10568,6 +10661,7 @@ int modattr(lifeform_t *lf, enum ATTRIB attr, int amt) { } } msg("%s %s %s!", lfname, verb, adverb); + more(); } return B_FALSE; } @@ -11532,12 +11626,12 @@ int scare(lifeform_t *lf, lifeform_t *scarer, int howlong, int scarerbonus) { // immune to fear? if (lfhasflag(lf, F_UNDEAD)) return B_FALSE; - + if (lfhasflag(lf, F_ASLEEP)) { return B_FALSE; } // not intelligent enough to be scared? - if (getiqname(getattr(scarer, A_IQ), NULL) <= IQ_VEGETABLE) { + if (getiqname(getattr(lf, A_IQ), NULL) <= IQ_VEGETABLE) { return B_FALSE; } @@ -12068,7 +12162,7 @@ int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *r othermod += 5; } if (lfhasflag(lf, F_STABILITY) || !hasbp(lf, BP_FEET)) { - othermod += 20; + othermod += 25; } } else if (ct == SC_FALL) { if (lfhasflag(lf, F_STABILITY) || !hasbp(lf, BP_FEET)) { @@ -12211,8 +12305,7 @@ int slipon(lifeform_t *lf, object_t *o) { char obname[BUFLEN]; char lfname[BUFLEN]; - if (lfhasflag(lf, F_STABILITY) || !hasbp(lf, BP_FEET) || - lfhasflag(lf, F_NONCORPOREAL) || isairborne(lf)) { + if (lfhasflag(lf, F_NONCORPOREAL) || isairborne(lf)) { return B_TRUE; } @@ -12841,7 +12934,7 @@ void turneffectslf(lifeform_t *lf) { f = lfhasflag(l, F_HIDING); if (f && !lfhasflagval(lf, F_SPOTTED, l->id, NA, NA, NULL) && !isinbattle(lf)) { // can you see their cell? - if (haslos(lf, l->cell)) { + if (!lfhasflag(lf, F_TRAINING) && haslos(lf, l->cell)) { int bonus = 0; int dist; if (!lfhasflag(l, F_SILENTMOVE) && !lfhasflag(lf, F_DEAF)) { @@ -13242,7 +13335,7 @@ int touch(lifeform_t *lf, object_t *o) { // not wearing gloves? if (!getequippedob(lf->pack, BP_HANDS)) { // default power of 4 - dospelleffects(lf, OT_S_FREEZEOB, 4, NULL, o, NULL, B_UNCURSED, NULL); + dospelleffects(lf, OT_S_FREEZEOB, 4, NULL, o, NULL, B_UNCURSED, NULL, B_FALSE); // we use val[0] here rather than timeleft, because we don't // want to decrement it each turn. @@ -13310,6 +13403,11 @@ int touch(lifeform_t *lf, object_t *o) { gloves = getequippedob(lf->pack, BP_HANDS); if (gloves) { takedamage(gloves, 2, DT_FIRE); + if (!hasflag(gloves->flags, F_DEAD)) { + // if your gloves weren't destroyed the fire + // will go out. + killflagsofid(o->flags, F_ONFIRE); + } } else { // otherwise YOU get damaged. if (isplayer(lf)) { @@ -13559,7 +13657,7 @@ int usestairs(lifeform_t *lf, object_t *o) { // move player to new map moveto(lf, newcell, B_TRUE, B_TRUE); if ((dir == D_UP) && !isairborne(lf)) { - stopsprinting(adjally[n]); // you can sprint down stairs, but not up + stopsprinting(lf); // you can sprint down stairs, but not up taketime(lf, getmovespeed(lf)*2); // takes longer to climb } else { taketime(lf, getmovespeed(lf)); diff --git a/lf.h b/lf.h index ef2303d..dad1e0c 100644 --- a/lf.h +++ b/lf.h @@ -27,6 +27,7 @@ int candrink(lifeform_t *lf, object_t *o); int caneat(lifeform_t *lf, object_t *o); int canhear(lifeform_t *lf, cell_t *c); int canlearn(lifeform_t *lf, enum SKILL skid); +int canopendoors(lifeform_t *lf); int canpickup(lifeform_t *lf, object_t *o, int amt); int canpolymorphto(enum RACE rid); int canpush(lifeform_t *lf, object_t *o, int dir); @@ -51,6 +52,7 @@ void dumplev(void); void dumplf(void); void dumpxp(void); int eat(lifeform_t *lf, object_t *o); +void enhancerandomskill(lifeform_t *lf); void enhanceskills(lifeform_t *lf); object_t *eyesshaded(lifeform_t *lf); int fall(lifeform_t *lf, lifeform_t *fromlf, int announce); diff --git a/map.c b/map.c index f5e6f51..d967a35 100644 --- a/map.c +++ b/map.c @@ -126,7 +126,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int auto } if ((raceid == R_NONE) || (raceid == R_RANDOM)) { - r = getrandomrace(c, 0); + r = getrandomrace(c, NA); } else { r = findrace(raceid); } @@ -342,7 +342,7 @@ int addrandomthing(cell_t *c, int obchance, int *nadded) { int rv = TT_NONE; // if there's already someone there, // then add an object. - if (c->lf || (rnd(1,100) <= obchance)) { + if (!cellwalkable(NULL, c, NULL) || (rnd(1,100) <= obchance)) { object_t *o; // object o = addrandomob(c); @@ -359,44 +359,86 @@ int addrandomthing(cell_t *c, int obchance, int *nadded) { return rv; } +// populates retcell[] with all cells within given radius of centre +void getradiuscells(cell_t *centre, int radius, int dirtype, enum LOFTYPE needlof, int wantcentre, cell_t **retcell, int *ncells) { + int (*distfunc)(cell_t *, cell_t *); + int x,y; + cell_t *c; + + *ncells = 0; + + if (!c) { + return; + } + if (dirtype == DT_ORTH) { + distfunc = getcelldistorth; + } else { + distfunc = getcelldist; + } + for (y = centre->y - radius; y <= centre->y + radius; y++) { + for (x = centre->x - radius; x <= centre->x + radius; x++) { + c = getcellat(centre->map, x,y); + if (c && haslof(centre, c, needlof, NULL) && (distfunc(centre, c) <= radius) && + (wantcentre || (c != centre)) ) { + retcell[*ncells] = c; + (*ncells)++; + } + } + } +} + // whichside should be D_ORTH // for now, this function will NOT include room corners -void getroomedge(map_t *map, int roomid, int minx, int miny, int maxx, int maxy, int whichside, cell_t **retcell, int *ncells) { +void getroomedge(map_t *map, int roomid, int minx, int miny, int maxx, int maxy, int whichside, cell_t **retcell, int *ncells, int onlywantsolid) { int x,y; + cell_t *c; *ncells = 0; if (whichside == D_N) { y = miny; for (x = minx+1; x <= maxx-1; x++) { - retcell[*ncells] = getcellat(map, x, y); - (*ncells)++; + c = getcellat(map, x, y); + if (!onlywantsolid || c->type->solid) { + retcell[*ncells] = getcellat(map, x, y); + (*ncells)++; + } } } else if (whichside == D_S) { y = maxy; for (x = minx+1; x <= maxx-1; x++) { - retcell[*ncells] = getcellat(map, x, y); - (*ncells)++; + c = getcellat(map, x, y); + if (!onlywantsolid || c->type->solid) { + retcell[*ncells] = getcellat(map, x, y); + (*ncells)++; + } } } else if (whichside == D_W) { x = minx; for (y = miny+1; y <= maxy-1; y++) { - retcell[*ncells] = getcellat(map, x, y); - (*ncells)++; + c = getcellat(map, x, y); + if (!onlywantsolid || c->type->solid) { + retcell[*ncells] = getcellat(map, x, y); + (*ncells)++; + } } } else if (whichside == D_E) { x = maxx; for (y = miny+1; y <= maxy-1; y++) { - retcell[*ncells] = getcellat(map, x, y); - (*ncells)++; + c = getcellat(map, x, y); + if (!onlywantsolid || c->type->solid) { + retcell[*ncells] = getcellat(map, x, y); + (*ncells)++; + } } } } -void autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy) { +int autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy, int doorpct) { int i,d; cell_t *poss[MAXCANDIDATES], *cell[MAXCANDIDATES]; // TODO: should this be maxroomw * maxroomh ? int ncells = 0, npossible = 0; int doorsadded = 0; + int db = B_FALSE; // for each side, make list of all possible door locations // then pick one randomly. @@ -404,7 +446,7 @@ void autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy) { // place a door. for (d = D_N; d <= D_W; d++) { npossible = 0; - getroomedge(map, roomid, minx, miny, maxx, maxy, d, cell, &ncells); + getroomedge(map, roomid, minx, miny, maxx, maxy, d, cell, &ncells, B_TRUE); for (i = 0; i < ncells; i++) { cell_t *newcell; // is there empty space on the other side of this wall segment? @@ -418,7 +460,7 @@ void autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy) { // walls to either side of the potential door location, then // always add a door if ((countcellexits(newcell) == 1) && wallstoleftright(newcell, d)) { - if (onein(2)) { + if (rnd(1,100) <= doorpct) { makedoor(cell[i]); } else { setcelltype(cell[i], getemptycelltype(map->habitat)); @@ -436,7 +478,13 @@ void autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy) { if (npossible > 0) { int sel; sel = rnd(0,npossible-1); - makedoor(poss[sel]); + + if (rnd(1,100) <= doorpct) { + makedoor(poss[sel]); + } else { + setcelltype(poss[sel], getemptycelltype(map->habitat)); + } + doorsadded++; } } // end foreach direction @@ -474,16 +522,20 @@ void autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy) { for (i = 0; i < ndodoors; i++) { int sel; d = dodoor[i]; - getroomedge(map, roomid, minx, miny, maxx, maxy, d, cell, &ncells); + getroomedge(map, roomid, minx, miny, maxx, maxy, d, cell, &ncells, B_TRUE); sel = rnd(0,ncells-1); - if (onein(2)) { + if (rnd(1,100) <= doorpct) { makedoor(cell[sel]); + doorsadded++; } else { setcelltype(cell[sel], getemptycelltype(map->habitat)); + doorsadded++; } } } + if (db) dblog("autodoors() added %d doors to roomid %d", doorsadded, roomid); + return doorsadded; } @@ -614,6 +666,103 @@ int cellhaslos(cell_t *c1, cell_t *dest) { return B_TRUE; } +void clearcell(cell_t *c) { + // kill everything there + if (c->lf) { + killlf(c->lf); + } + while (c->obpile->first) { + killob(c->obpile->first); + } + c->known = B_FALSE; + c->knownglyph.ch = ' '; + c->knownglyph.colour = C_GREY; +} + +// returns true if something happened +int dowaterspread(cell_t *c) { + float thisdepth,surrounddepth = DP_NONE; + int i; + int nsurroundwithwater = 0,nsurround = 0; + int db = B_FALSE; + + if (!c || c->type->solid || hascloseddoor(c)) { + return B_FALSE; + } + + // calculate depth of this cell + thisdepth = getcellwaterdepth(c, NULL); + + // calculate average depth of surrounding cells + for (i = DC_N; i <= DC_NW; i++) { + cell_t *newc; + + newc = getcellindir(c, i); + if (newc && !newc->type->solid && !hascloseddoor(newc)) { + float newcdepth; + int ok = B_FALSE; + + if (newc->type->floorheight == c->type->floorheight) { + ok = B_TRUE; + } else if (newc->type->floorheight < c->type->floorheight) { + // ie. downhill. don't include these + ok = B_FALSE; + } else if (newc->type->floorheight > c->type->floorheight) { + // ie. uphill. + ok = B_TRUE; + } + + if (ok) { + newcdepth = getcellwaterdepth(newc, NULL); + + nsurround++; // ie. a non-solid cell + surrounddepth += newcdepth; + + if (newcdepth > DP_NONE) { + nsurroundwithwater++; // ie. a non-solid cell _with water_ + } + } + } + } + + + // if there was water here or around us... + if (nsurroundwithwater || thisdepth) { + float newdepth; + + //surrounddepth /= ((float)nsurround); + surrounddepth /= ((float)nsurroundwithwater); + limitf(&surrounddepth,(float)DP_NONE, (float)DP_MAX); + + if (thisdepth == surrounddepth) { + // if there are any nonsolid surrounding cells _without_ water, and + // there is water here, our depth drops. + if ((thisdepth > 0) && (nsurround - nsurroundwithwater >= 2)) { + newdepth = thisdepth - 1; + } else { + newdepth = thisdepth; + } + } else if (surrounddepth > thisdepth) { + // surrounding cells are deeper - they flow into here + newdepth = (thisdepth + surrounddepth) * 0.8; + } else if (thisdepth > surrounddepth) { + // surrounding cells are shallower - this cell will go down. + newdepth = (thisdepth + surrounddepth) * 0.2; + } + + addflag(c->map->flags, F_NEWWATERDEPTH, c->x, c->y, (int)newdepth, NULL); + if (db) { + + dblog("%s %d,%d: goes from %d to %d (surrounddepth is %d)\n", + thisdepth ? "water depth at" : "NEW WATER AT ", + c->x, c->y, + (int)thisdepth, (int)newdepth, (int)surrounddepth); + } + return B_TRUE; + } + return B_FALSE; +} + cell_t *getcellat(map_t *map, int x, int y) { if (!isonmap(map, x, y)) return NULL; return map->cell[y*map->w + x]; @@ -665,7 +814,7 @@ void getcellglyph(glyph_t *g, cell_t *c, lifeform_t *viewer) { object_t *o; // draw highest object in sort order - o = gettopobject(c); + o = gettopobject(c, B_TRUE); if (o && !hasflag(o->flags, F_NOGLYPH)) { // return the object's glyph *g = *(getglyph(o)); @@ -708,6 +857,17 @@ void getcellglyph(glyph_t *g, cell_t *c, lifeform_t *viewer) { } } + +enum DEPTH getcellwaterdepth(cell_t *c, lifeform_t *lf) { + object_t *o; + o = hasobwithflag(c->obpile, F_DEEPWATER); + if (o) { + return getobdepth(o, lf); + } + return DP_NONE; +} + + int getdoorlockdiff(int depth) { return 19 + depth; } @@ -768,7 +928,9 @@ int getmapdifficulty(map_t *m) { return diff; } -object_t *gettopobject(cell_t *where) { +// forglyph will be true if we are using this function for the purpose +// of figuring out which glyph to draw +object_t *gettopobject(cell_t *where, int forglyph) { object_t *o,*oo = NULL; enum LFSIZE largest = SZ_MINI; int c; @@ -779,6 +941,7 @@ object_t *gettopobject(cell_t *where) { // ignore hidden traps, but not secret doors if (hasflag(o->flags, F_SECRET) && !isdoor(o, NULL)) { } else if (hasflag(o->flags, F_TRAIL) && !canseeob(player, o)) { + } else if (forglyph && hasflag(o->flags, F_NOGLYPH)) { } else { f = hasflag(o->flags, F_IMPASSABLE); if (f && (f->val[0] > largest)) { @@ -801,6 +964,7 @@ object_t *gettopobject(cell_t *where) { if (o->type->obclass->id == sortorder[c]) { if (hasflag(o->flags, F_SECRET)) { } else if (hasflag(o->flags, F_TRAIL) && !canseeob(player, o)) { + } else if (forglyph && hasflag(o->flags, F_NOGLYPH)) { } else { return o; } @@ -894,8 +1058,8 @@ int calcroompos(map_t *map, int w, int h, int *bx, int *by) { cell_t *cell; // try placing room at all positions - for (y = 0; y < map->h; y++) { - for (x = 0; x < map->w; x++) { + for (y = 1; y < map->h; y++) { + for (x = 1; x < map->w; x++) { // would the room fit here? if ( ((x + (w-1)) <= (map->w-1)) && ((y + (h-1)) <= (map->h-1))) { @@ -1222,42 +1386,50 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir) { } if (!roomvault[i]) { // just do a normal room - createroom(map, i, NA, NA, NULL, NULL, &roomw[i],&roomh[i]); + createroom(map, i, NA, NA, NULL, NULL, &roomw[i],&roomh[i], 50, B_FALSE); roomvault[i] = B_FALSE; } } } - // add staircases - dungeons always have an up and down stairs + // add staircases. + // first dungeon level has 1 up stairs, 3 down. + // subsequent levels always have 3 up and down stairs for (i = 0; i < 3; i++) { - // add up stairs - c = NULL; - while (!c || !isempty(c) || countobs(c->obpile, B_TRUE)) { - c = getrandomroomcell(map, ANYROOM); - } - o = addob(c->obpile, "staircase going up"); - linkstairs(o); - // first dungeon level has barriers over the exit stairs - if ((map->region == RG_FIRSTDUNGEON) && (map->depth == 1)) { - if (c->lf) killlf(c->lf); - addob(c->obpile, "magical barrier"); - /* - int d; - // surround stairs with barriers - for (d = DC_N; d <= DC_NW; d++) { - cell_t *newc; - newc = getcellindir(c, d); - - if (newc && !newc->type->solid) { - // kill lfs there - if (newc->lf) killlf(newc->lf); - // add a barrier - addob(newc->obpile, "magical barrier"); - } + // UP STAIRS + if ((map->region == RG_FIRSTDUNGEON) && (map->depth == 1) && (i > 0)) { + // first dungeon level, already added 1 up stairs + } else { + c = NULL; + while (!c || !isempty(c) || countobs(c->obpile, B_TRUE)) { + c = getrandomroomcell(map, ANYROOM); + } + o = addob(c->obpile, "staircase going up"); + linkstairs(o); + + // first dungeon level has barriers over the exit stairs + if ((map->region == RG_FIRSTDUNGEON) && (map->depth == 1)) { + if (c->lf) killlf(c->lf); + addob(c->obpile, "magical barrier"); + /* + int d; + // surround stairs with barriers + for (d = DC_N; d <= DC_NW; d++) { + cell_t *newc; + newc = getcellindir(c, d); + + if (newc && !newc->type->solid) { + // kill lfs there + if (newc->lf) killlf(newc->lf); + // add a barrier + addob(newc->obpile, "magical barrier"); + } + } + */ } - */ } + // DOWN STAIRS c = NULL; while (!c || !isempty(c) || countobs(c->obpile, B_TRUE)) { c = getrandomroomcell(map, ANYROOM); @@ -1460,11 +1632,13 @@ void createmap(map_t *map, int depth, int region, int habitat, map_t *parentmap, map->depth = depth; map->region = region; - + sprintf(buf, "Region %d (#%d)",map->region, map->id); map->name = strdup(buf); map->habitat = habitat; + map->nrooms = 0; + // link to other maps if required. // default to no links for (i = D_UP; i <= D_DOWN; i++) { @@ -1588,16 +1762,14 @@ void createmap(map_t *map, int depth, int region, int habitat, map_t *parentmap, map->nextmap[D_DOWN] = firstdungeon->id; // add stairs going down to dungeon - for (i = 0; i < 3; i++) { - cell_t *c; - object_t *o; - c = NULL; - while (!c || !cellwalkable(NULL, c, NULL)) { - c = getrandomcell(map); - } - o = addob(c->obpile, "staircase going down"); - linkstairs(o); + cell_t *c; + object_t *o; + c = NULL; + while (!c || !cellwalkable(NULL, c, NULL)) { + c = getrandomcell(map); } + o = addob(c->obpile, "staircase going down"); + linkstairs(o); } // join up any unlinked staircases in this map. @@ -1670,8 +1842,10 @@ int createvault(map_t *map, int roomid, vault_t *v, int *retw, int *reth) { f = hasflag(v->flags, F_VAULTRANDOMMAP); if (f) { - // just make a normal room to start with. - if (createroom(map, roomid, f->val[0], f->val[1], &minx, &miny, &w, &h)) { + // just make a normal room to start with. but make sure : + // - it is surrounded with walls! + // - we don't do autodoors (will handle this further down) + if (createroom(map, roomid, f->val[0], f->val[1], &minx, &miny, &w, &h, 0, B_TRUE)) { return B_TRUE; } maxx = minx + w - 1; @@ -1694,7 +1868,9 @@ int createvault(map_t *map, int roomid, vault_t *v, int *retw, int *reth) { cell_t *cell; celltype_t *ct; cell = getcellat(map, x, y); - + + clearcell(cell); + // set cell type ct = getvaultcelltype(v, x-minx,y-miny); setcelltype(cell, ct ? ct->id : getemptycelltype(cell->map->habitat)); @@ -1713,21 +1889,25 @@ int createvault(map_t *map, int roomid, vault_t *v, int *retw, int *reth) { addvaultcontents(map, v, minx, miny, maxx, maxy); // auto add doors if required - if (hasflag(v->flags, F_AUTODOORS)) { - autodoors(map, roomid, minx, miny, maxx, maxy); + f = hasflag(v->flags, F_AUTODOORS); + if (f) { + autodoors(map, roomid, minx, miny, maxx, maxy, f->val[0]); } linkexits(map, roomid, minx, miny, maxx,maxy); + map->nrooms++; + return B_FALSE; } // make sure exits/doors in a given room link up to the rest of the map. -void linkexits(map_t *m, int roomid, int minx, int miny, int maxx, int maxy) { +int linkexits(map_t *m, int roomid, int minx, int miny, int maxx, int maxy) { int x,y,i; cell_t *poss[MAXCANDIDATES],*c; int nposs = 0; int db = B_FALSE; + int nadded = 0; if (db) dblog("linkexits for roomid %d", roomid); @@ -1802,6 +1982,7 @@ void linkexits(map_t *m, int roomid, int minx, int miny, int maxx, int maxy) { // now create a path if (db) dblog(" Linking %s (distance %d).", getdirname(whichway), bestdist); + nadded++; c = getcellindir(poss[i], whichway); while (c && !cellwalkable(NULL, c, NULL)) { setcelltype(c, getemptycelltype(c->map->habitat)); @@ -1811,10 +1992,11 @@ void linkexits(map_t *m, int roomid, int minx, int miny, int maxx, int maxy) { } // end if ncorridors = 0 } // end for each door if (db) dblog("linkexits complete."); + return nadded; } // room w/h are returned in *w and *h if given. -int createroom(map_t *map, int roomid, int overrideminw, int overrideminh, int *retx, int *rety, int *retw, int *reth) { +int createroom(map_t *map, int roomid, int overrideminw, int overrideminh, int *retx, int *rety, int *retw, int *reth, int doorpct, int forcewalls) { int x,y; cell_t *cell; int minx,miny; @@ -1858,21 +2040,32 @@ int createroom(map_t *map, int roomid, int overrideminw, int overrideminh, int * for (y = miny; y <= maxy; y++) { for (x = minx; x <= maxx; x++) { cell = getcellat(map, x, y); - // make it a border or room - if ((y == miny) || (y == maxy) || - (x == minx) || (x == maxx)) { - if (cell->type->solid) { - setcelltype(cell, CT_ROOMWALL); + if (cell) { + // kill contents + clearcell(cell); + // make it a border or room + if ((y == miny) || (y == maxy) || + (x == minx) || (x == maxx)) { + // ie. if you haven't forced walls then if this room overlaps + // with another one, no walls will be created. + if (forcewalls || (!forcewalls && cell->type->solid)) { + setcelltype(cell, CT_ROOMWALL); + } + //} + } else { + setcelltype(cell, CT_ROOM); } - } else { - setcelltype(cell, CT_ROOM); + cell->roomid = roomid; } - cell->roomid = roomid; } } // add doors - autodoors(map, roomid, minx, miny, maxx, maxy); + if (doorpct) { + autodoors(map, roomid, minx, miny, maxx, maxy, doorpct); + } + + map->nrooms++; return B_FALSE; } @@ -2613,6 +2806,18 @@ object_t *hasenterableobject(cell_t *c) { return hasobwithflag(c->obpile, F_CLIMBABLE); } +object_t *hascloseddoor(cell_t *c) { + object_t *o; + int isopen; + for (o = c->obpile->first ; o ; o = o->next) { + if (isdoor(o, &isopen)) { + if (!isopen) { + return o; + } + } + } + return NULL; +} lifeform_t *haslf(cell_t *c) { if (c->lf && !isdead(c->lf)) { @@ -2962,6 +3167,11 @@ void makedoor(cell_t *cell) { map_t *m; char doorbuf[BUFLEN]; + // can't have more than one door in a cell + if (hasobwithflag(cell->obpile, F_DOOR)) { + return; + } + m = cell->map; setcelltype(cell, getemptycelltype(m->habitat)); @@ -3073,7 +3283,7 @@ void setcellknown(cell_t *cell, int forcelev) { cell->knownglyph = cell->type->glyph; // high cartography skill lets us remember certain objects... if (slev >= PR_EXPERT) { - o = gettopobject(cell); + o = gettopobject(cell, B_TRUE); if (o) { cell->knownglyph = *(getglyph(o)); } diff --git a/map.h b/map.h index d9827ee..a2eeb34 100644 --- a/map.h +++ b/map.h @@ -6,20 +6,24 @@ map_t *addmap(void); lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int autogen, int *nadded); object_t *addrandomob(cell_t *c); int addrandomthing(cell_t *c, int obchance, int *nadded); -void autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy); +int autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy, int doorpct); int cellhaslos(cell_t *c1, cell_t *dest); +void clearcell(cell_t *c); +int dowaterspread(cell_t *c); cell_t *getcellat(map_t *map, int x, int y); int getcelldist(cell_t *src, cell_t *dst); int getcelldistorth(cell_t *src, cell_t *dst); void getcellglyph(glyph_t *g, cell_t *c, lifeform_t *viewer); +enum DEPTH getcellwaterdepth(cell_t *c, lifeform_t *lf); int getdoorlockdiff(int depth); int getdoorsecretdiff(int depth); enum CELLTYPE getemptycelltype(enum HABITAT hab); enum CELLTYPE getwallcelltype(enum HABITAT hab); flag_t *getmapcoords(map_t *m, int *x, int *y); int getmapdifficulty(map_t *m); -void getroomedge(map_t *m, int roomid, int minx, int miny, int maxx, int maxy, int whichside, cell_t **retcell, int *ncells); -object_t *gettopobject(cell_t *where); +void getradiuscells(cell_t *centre, int radius, int dirtype, enum LOFTYPE needlof, int wantcentre, cell_t **retcell, int *ncells); +void getroomedge(map_t *m, int roomid, int minx, int miny, int maxx, int maxy, int whichside, cell_t **retcell, int *ncells, int onlywantsolid); +object_t *gettopobject(cell_t *where, int forglyph); void calclight(map_t *map); int calcroompos(map_t *map, int w, int h, int *bx, int *by); int countadjcellsoftype(cell_t *cell, int id); @@ -28,7 +32,7 @@ int countcellexits(cell_t *cell); void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir); void createforest(map_t *map, int depth, map_t *parentmap, int exitdir); void createmap(map_t *map, int depth, int region, int habitat, map_t *parentmap, int exitdir); -int createroom(map_t *map, int roomid, int overrideminw, int overrideminh, int *retx, int *rety, int *retw, int *reth); +int createroom(map_t *map, int roomid, int overrideminw, int overrideminh, int *retx, int *rety, int *retw, int *reth, int doorpct, int forcewalls); int createvault(map_t *map, int roomid, vault_t *v, int *retw, int *reth); int dirtox(int dt, int dir); int dirtoy(int dt, int dir); @@ -60,6 +64,7 @@ void getroomcells(map_t *m, int roomid, cell_t **retcell, int *ncells); int getslipperyness(cell_t *c, object_t **slipob); cell_t *getstairdestination(object_t *o); object_t *hasenterableobject(cell_t *c); +object_t *hascloseddoor(cell_t *c); lifeform_t *haslf(cell_t *c); int hasknownobject(cell_t *c); int hasobject(cell_t *c); @@ -76,7 +81,7 @@ int isnewcellok(cell_t *cell, char *err); int isonmap(map_t *map, int x, int y); int isoutdoors(map_t *m); int iswallindir(cell_t *cell, int dir); -void linkexits(map_t *m, int roomid, int minx, int miny, int maxx, int maxy); +int linkexits(map_t *m, int roomid, int minx, int miny, int maxx, int maxy); int linkstairs(object_t *o); void makedoor(cell_t *cell); void makelit(cell_t *c, enum LIGHTLEV how, int howlong); diff --git a/move.c b/move.c index bb763cd..2ab13d9 100644 --- a/move.c +++ b/move.c @@ -70,16 +70,29 @@ int ispossiblemove(lifeform_t *lf, int dir) { return B_TRUE; } break; - case E_DOORINWAY: case E_CANTMOVE: case E_GRABBEDBY: case E_TOOHEAVY: case E_LFINWAY: return B_TRUE; + case E_DOORINWAY: + if (canopendoors(lf)) { + return B_TRUE; + } + break; case E_OBINWAY: inway = (object_t *)rdata; if (inway && ispushable(inway)) { - return B_TRUE; + // player can always try pushing... + if (isplayer(lf)) { + return B_TRUE; + } else { + // for ai, move is only 'possible' if + // we are strong enough to push the object. + if (canpush(lf, inway, dir)) { + return B_TRUE; + } + } } break; default: @@ -153,7 +166,15 @@ int celldangerous(lifeform_t *lf, cell_t *cell, int onlyifknown, enum ERROR *err } } + for (o = cell->obpile->first ; o ; o = o->next) { + if (hasflag(o->flags, F_TRAP) && canseeob(lf, o)) { + if (error) { + *error = E_AVOIDOB; + rdata = o; + } + return B_TRUE; + } f = hasflag(o->flags, F_DEEPWATER); if (f) { // non swimming creature in water? @@ -250,7 +271,6 @@ int cellwalkable(lifeform_t *lf, cell_t *cell, enum ERROR *error) { if (error) *error = E_LFINWAY; return B_FALSE; } - for (o = cell->obpile->first ; o ; o = o->next) { if (isimpassableob(o, lf)) { if (lf) { @@ -261,6 +281,7 @@ int cellwalkable(lifeform_t *lf, cell_t *cell, enum ERROR *error) { // ok but still set error *error = E_OBINWAY; } else { + // not ok rdata = o; if (error) { if (isdoor(o, NULL)) { @@ -907,7 +928,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) { } // did you just enter the water? if (!prewater) { - if (getskill(lf, SK_SWIMMING)) { + if ((getobdepth(o, lf) >= DP_WAIST) && getskill(lf, SK_SWIMMING)) { if (isplayer(lf)) { msg("You start swimming."); didmsg = B_TRUE; @@ -1169,7 +1190,7 @@ int moveto(lifeform_t *lf, cell_t *newcell, int onpurpose, int dontclearmsg) { // make some noise // (stealth check to avoid this) - if (!lfhasflag(lf, F_SILENTMOVE)) { + if (!lfhasflag(lf, F_SILENTMOVE) && !lfhasflag(lf, F_SNEAK)) { if (!skillcheck(lf, SC_STEALTH, 20, 0)) { if (isairborne(lf)) { makenoise(lf, N_FLY); @@ -1276,7 +1297,7 @@ int opendoor(lifeform_t *lf, object_t *o) { return B_TRUE; } - if (lf && lfhasflagval(lf, F_NOBODYPART, BP_HANDS, NA, NA, NULL)) { + if (!canopendoors(lf)) { if (isplayer(lf)) { msg("You have no hands with which to open the door!"); } @@ -1363,8 +1384,8 @@ int opendoor(lifeform_t *lf, object_t *o) { } where = getoblocation(o); if (!haslos(player, where)) { - // don't anonuce this is we can see it. - // normally 'noise()' takes case of this by + // don't anonuce this if we can see it. + // normally 'noise()' takes care 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. @@ -1604,6 +1625,7 @@ int initiatemove(lifeform_t *lf, cell_t *cell, int *didmsg) { for (o = lf->cell->obpile->first ; o ; o = nexto) { nexto = o->next; + if ((o->type->id == OT_WEB) && (lf->race->baseid == R_SPIDER)) { continue; } @@ -1615,7 +1637,19 @@ int initiatemove(lifeform_t *lf, cell_t *cell, int *didmsg) { if (f) { char lfname[BUFLEN]; int diff; + int checkmod = 0; int getsweaker; + + if (isairborne(lf) && (f->val[2] != B_TRUE)) { + continue; + } + + + if ((o->type->id == OT_WEB) && isairborne(lf)) { + checkmod -= 5; + } + + getlfname(lf,lfname); getobname(o, buf, o->amt); @@ -1631,7 +1665,7 @@ int initiatemove(lifeform_t *lf, cell_t *cell, int *didmsg) { diff = (o->amt - 1) * ((float)f->val[0] / 4.0); } getsweaker = f->val[1]; - if (skillcheck(lf, SC_STR, diff, 0)) { + if (skillcheck(lf, SC_STR, diff, checkmod)) { if (isplayer(lf)) { msg("You tear free from %s!", buf); if (didmsg) *didmsg = B_TRUE; @@ -1696,11 +1730,12 @@ int initiatemove(lifeform_t *lf, cell_t *cell, int *didmsg) { if (!lfhasflag(lf, F_SNEAK)) { slip = getslipperyness(lf->cell, &slipob); if (slip && !skillcheck(lf, SC_SLIP, slip, 0)) { - slipon(lf, slipob); - if (didmsg) *didmsg = B_TRUE; - // don't move - reason = E_OK; - return B_TRUE; + if (!slipon(lf, slipob)) { + if (didmsg) *didmsg = B_TRUE; + // don't move + reason = E_OK; + return B_TRUE; + } } } } diff --git a/nexus.c b/nexus.c index 4cd9726..a45fd27 100644 --- a/nexus.c +++ b/nexus.c @@ -74,6 +74,8 @@ long timeleft = 0; extern int statdirty; +extern int noredraw; + int needredraw = B_TRUE; int numdraws = 0; @@ -290,11 +292,11 @@ int main(int argc, char **argv) { // pre-calc line-of-sight for player precalclos(player); - // don't want any mosnters starting within los of player + // don't want any mosnters starting within los/lof of player for (y = 0; y < player->cell->map->h; y++) { for (x = 0; x < player->cell->map->w; x++) { c = getcellat(player->cell->map, x, y); - if (c && c->lf && haslos(player, c)) { + if (c && c->lf && (haslos(player, c) || haslof(player->cell, c, LOF_WALLSTOP, NULL))) { if (!isplayer(c->lf) && !ispetof(c->lf, player)) { killlf(c->lf); } @@ -372,7 +374,7 @@ int main(int argc, char **argv) { return B_FALSE; } -celltype_t *addcelltype(int id, char *name, char glyph, int colour, 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, int floorheight) { celltype_t *a; // add to the end of the list @@ -398,6 +400,7 @@ celltype_t *addcelltype(int id, char *name, char glyph, int colour, int solid, i a->solid = solid; a->transparent = transparent; a->material = findmaterial(mat); + a->floorheight = floorheight; a->flags = addflagpile(NULL, NULL); @@ -630,7 +633,6 @@ void donextturn(map_t *map) { } if (hasflag(player->flags, F_ASLEEP)) { - // ooo is this right ? needredraw = B_FALSE; /* } else if (isdead(who) || cansee(player, who)) { @@ -708,7 +710,7 @@ enum COLOUR getpctcol(float num, float max) { return C_ORANGE; } -void getrarity(int depth, int *min, int *max, int range, int oodok) { +void getrarityrange(int depth, int *min, int *max, int range, int oodok) { int mid; int num; @@ -750,15 +752,16 @@ int init(void) { initrace(); // cell types - addcelltype(CT_WALL, "rock wall", '#', C_GREY, B_SOLID, B_OPAQUE, MT_STONE); - addcelltype(CT_WALLGLASS, "glass wall", '#', C_CYAN, B_SOLID, B_TRANS, MT_GLASS); - addcelltype(CT_WALLMETAL, "metal wall", '#', C_WHITE, B_SOLID, B_OPAQUE, MT_METAL); - 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); - addcelltype(CT_GRASS, "grass", '.', C_GREEN, B_EMPTY, B_TRANS, MT_PLANT); - addcelltype(CT_DIRT, "dirt", '.', C_BROWN, B_EMPTY, B_TRANS, MT_STONE); + addcelltype(CT_WALL, "rock wall", '#', C_GREY, B_SOLID, B_OPAQUE, MT_STONE, 0); + addcelltype(CT_WALLGLASS, "glass wall", '#', C_CYAN, B_SOLID, B_TRANS, MT_GLASS, 0); + addcelltype(CT_WALLMETAL, "metal wall", '#', C_WHITE, B_SOLID, B_OPAQUE, MT_METAL, 0); + addcelltype(CT_ROOMWALL, "rock wall", '#', C_GREY, B_SOLID, B_OPAQUE, MT_STONE, 0); + addcelltype(CT_CORRIDOR, "rock floor", '.', C_GREY, B_EMPTY, B_TRANS, MT_STONE, 0); + addcelltype(CT_LOOPCORRIDOR, "rock floor", 'L', C_GREY, B_EMPTY, B_TRANS, MT_STONE, 0); + addcelltype(CT_ROOM, "rock floor", '.', C_GREY, B_EMPTY, B_TRANS, MT_STONE, 0); + addcelltype(CT_GRASS, "grass", '.', C_GREEN, B_EMPTY, B_TRANS, MT_PLANT, 0); + addcelltype(CT_DIRT, "dirt", '.', C_BROWN, B_EMPTY, B_TRANS, MT_STONE, 0); + addcelltype(CT_LOWFLOOR, "low rock floor", '.', C_GREY, B_EMPTY, B_TRANS, MT_STONE, -1); gamemode = GM_VALIDATION; if (validateobs()) { @@ -905,6 +908,23 @@ int limit(int *what, int min, int max) { return limited; } +int limitf(float *what, float min, float max) { + int limited = B_FALSE; + if (min != NA) { + if (*what < min) { + *what = min; + limited = B_TRUE; + } + } + if (max != NA) { + if (*what > max) { + *what = max; + limited = B_TRUE; + } + } + return limited; +} + int onein(int howmany) { if (rnd(1,howmany) == 1) return B_TRUE; return B_FALSE; @@ -1256,6 +1276,7 @@ void timeeffectsworld(map_t *map) { timeleft += firstlftime; // now do effects based on time... while (timeleft >= TICK_INTERVAL) { + flag_t *f, *nextf; timeleft -= TICK_INTERVAL; @@ -1279,10 +1300,50 @@ void timeeffectsworld(map_t *map) { c->lit = c->origlit; } } - } + + // water spreads... + if (dowaterspread(c) && haslos(player, c)) { + needredraw = B_TRUE; + } + } // end if c } } // end for (y... + // now finish off water spread + noredraw = B_TRUE; + for (f = map->flags->first ; f ; f = nextf) { + nextf = f->next; + if (f->id == F_NEWWATERDEPTH) { + cell_t *c; + c = getcellat(map, f->val[0], f->val[1]); + if (c) { + if (f->val[2] > DP_NONE) { + o = hasobwithflag(c->obpile, F_DEEPWATER); + if (!o) { + o = addob(c->obpile, "water"); + } + + if (o) { + flag_t *dflag; + dflag = hasflag(o->flags, F_DEEPWATER); + // adjust depth + dflag->val[0] = f->val[2]; + } + } else { + // water depth is now zero. + o = hasobwithflag(c->obpile, F_DEEPWATER); + if (o) { + killob(o); + addob(c->obpile, "large puddle of water"); + } + } + } + killflag(f); + continue; + } + } + noredraw = B_FALSE; + // now handle effects on lifeforms and/or their objects for (l = map->lf ; l ; l = l->next) { timeeffectslf(l); diff --git a/nexus.h b/nexus.h index 5af2d12..5ed932e 100644 --- a/nexus.h +++ b/nexus.h @@ -1,6 +1,6 @@ #include "defs.h" -celltype_t *addcelltype(int id, char *name, char glyph, int colour, 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, int floorheight); command_t *addcommand(enum COMMAND id, char c, char *desc); void checkdeath(void); void checkendgame(void); @@ -12,13 +12,14 @@ void dobresnham(int d, int xinc1, int yinc1, int dinc1, int xinc2, int yinc2, in void donextturn(map_t *map); char *getdirname(int dir); enum COLOUR getpctcol(float num, float max); -void getrarity(int depth, int *min, int *max, int range, int oodok); +void getrarityrange(int depth, int *min, int *max, int range, int oodok); int init(void); void calcbresnham(map_t *m, int x1, int y1, int x2, int y2, cell_t **retcell, int *numpixels); void initbresnham(int x1, int y1, int x2, int y2, int *xinc1, int *yinc1, int *dinc1, int *xinc2, int *yinc2, int *dinc2, int *numpixels, int *d); void initcommands(void); int isplayerturn(void); int limit(int *what, int min, int max); +int limitf(float *what, float min, float max); int onein(int howmany); int parseplayerfile(FILE *f, lifeform_t *lf); float pctof(float pct, float num); diff --git a/objects.c b/objects.c index 50aff20..51325e6 100644 --- a/objects.c +++ b/objects.c @@ -394,9 +394,11 @@ object_t *addob(obpile_t *where, char *name) { } // create a new object -// if canstack is true, we are allwoed -// to join similar objects together instead of -// creating new obejct entries. +// if canstack is true, we are allwoed +// to join similar objects together into a single +// object with o->amt set, instead of +// creating new obejct entries. +// NOTE: This function MUST return number of obs created via global "nretobs" object_t *addobject(obpile_t *where, char *name, int canstack) { objecttype_t *ot; object_t *o = NULL; @@ -418,6 +420,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack) { int nom = 0; int n; int bookcontents = -1; + enum DEPTH wantdepth = DP_MAX; int wantrarity = RR_NONE; int wantgoodness = G_NA; int donesomething; @@ -511,7 +514,23 @@ object_t *addobject(obpile_t *where, char *name, int canstack) { // handle prefixes. strip them off as we go. donesomething = B_TRUE; while (donesomething) { + int n; donesomething = B_FALSE; + + // water flags + for (n = DP_MAX; n >= DP_FIRST; n--) { + char wpre[BUFLEN]; + sprintf(wpre, "%s ", getwaterdepthname(n)); + if (strstarts(p, wpre)) { + wantdepth = n; + p += strlen(wpre); + p++; // go past space + donesomething = B_TRUE; + break; + } + } + if (donesomething) continue; + if (strstarts(p, "blessed ")) { if (db) dblog("DB: ob is blessed (%s)",p); wantblessed = B_BLESSED; @@ -696,7 +715,16 @@ object_t *addobject(obpile_t *where, char *name, int canstack) { } if (db) dblog("DB: FOUND: ot->name = '%s'", ot->name ); - // we now have the objecttype. + //////////////////////////////////// + // we now have the objecttype! + //////////////////////////////////// + + if (hasflag(ot->flags, F_ONEPERCELL)) { + if (hasob(where, ot->id)) { + nretobs = 0; + return NULL; + } + } // override blessed status from flags... f = hasflag(ot->flags, F_STARTBLESSED); @@ -830,8 +858,6 @@ object_t *addobject(obpile_t *where, char *name, int canstack) { if (f) { f->known = B_FALSE; } - - // non-inherited from here on: // if adding to a player... @@ -884,26 +910,28 @@ object_t *addobject(obpile_t *where, char *name, int canstack) { cell_t *c; int val[3]; c = getoblocation(o); - // fill in flag vals - switch (doorflag[n]) { - case F_LOCKED: - val[0] = B_TRUE; - val[1] = getdoorlockdiff(c->map->depth); - val[2] = NA; - break; - case F_JAMMED: - val[0] = rnd(1,c->map->depth+3); - val[1] = NA; - val[2] = NA; - break; - case F_SECRET: - val[0] = getdoorsecretdiff(c->map->depth); - val[1] = NA; - val[2] = NA; - break; - default: break; + if (c) { + // fill in flag vals + switch (doorflag[n]) { + case F_LOCKED: + val[0] = B_TRUE; + val[1] = getdoorlockdiff(c->map->depth); + val[2] = NA; + break; + case F_JAMMED: + val[0] = rnd(1,c->map->depth+3); + val[1] = NA; + val[2] = NA; + break; + case F_SECRET: + val[0] = getdoorsecretdiff(c->map->depth); + val[1] = NA; + val[2] = NA; + break; + default: break; + } + addflag(o->flags, doorflag[n], val[0], val[1], val[2], NULL); } - addflag(o->flags, doorflag[n], val[0], val[1], val[2], NULL); } } @@ -966,7 +994,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack) { if (!corpserace) { // random one. - corpserace = getrandomrace(NULL, 0); + corpserace = getrandomrace(NULL, NA); } o->weight = corpserace->weight; @@ -1017,10 +1045,10 @@ object_t *addobject(obpile_t *where, char *name, int canstack) { where = getoblocation(o); // select random race if (where) { - corpserace = getrandomrace(where, 0); + corpserace = getrandomrace(where, NA); } else { // ie. vending machine - corpserace = getrandomrace(NULL, 0); + corpserace = getrandomrace(NULL, NA); } } @@ -1099,6 +1127,11 @@ object_t *addobject(obpile_t *where, char *name, int canstack) { } } + } else if (o->type->id == OT_WATERDEEP) { + f = hasflag(o->flags, F_DEEPWATER); + if (f && (f->val[0] != wantdepth)) { + f->val[0] = wantdepth; + } } // chance of masterwork based on wantgoodness @@ -1387,33 +1420,24 @@ object_t *addobject(obpile_t *where, char *name, int canstack) { // add objects in a circle // returns # added. int addobburst(cell_t *where, int range, int dirtype, char *name, lifeform_t *fromlf, enum LOFTYPE needlof) { - int (*distfunc)(cell_t *, cell_t *); - int x,y; - cell_t *c; int nadded = 0; + cell_t *cell[MAXCANDIDATES]; + int ncells,i; if (!where) return 0; redrawpause(); - if (dirtype == DT_ORTH) { - distfunc = getcelldistorth; - } else { - distfunc = getcelldist; - } - - for (y = where->y - range; y <= where->y + range; y++) { - for (x = where->x - range; x <= where->x + range; x++) { - c = getcellat(where->map, x,y); - if (c && haslof(where, c, needlof, NULL) && (distfunc(where, c) <= range)) { - if (!c->type->solid) { - object_t *o; - o = addob(c->obpile, name); - if (o) { - if (fromlf) setobcreatedby(o, fromlf); - nadded++; - } - } + getradiuscells(where, range, dirtype, needlof, B_TRUE, cell, &ncells); + for (i = 0; i < ncells; i++) { + cell_t *c; + c = cell[i]; + if (!c->type->solid) { + object_t *o; + o = addob(c->obpile, name); + if (o) { + if (fromlf) setobcreatedby(o, fromlf); + nadded++; } } } @@ -2015,6 +2039,10 @@ int canseeob(lifeform_t *lf, object_t *o) { // can't see return B_FALSE; } + if (o->pile->where && hasobwithflag(o->pile, F_BLOCKSVIEW)) { + return B_FALSE; + } + f = hasflag(o->flags, F_TRAIL); if (f) { if (f->val[2] == S_SIGHT) { @@ -2648,6 +2676,7 @@ glyph_t *getglyph(object_t *o) { col = getmaterialcolour(o->material->id); } } else { + f = hasflag(o->flags, F_GLYPH); if (f) { g = f->text[0]; @@ -2660,6 +2689,16 @@ glyph_t *getglyph(object_t *o) { col = getmaterialcolour(o->material->id); } } + + // override colour + if (o->type->id == OT_WATERDEEP) { + if (getobdepth(o, player) >= DP_HEAD) { + col = C_BOLDBLUE; + } else { + col = C_BLUE; + } + } + tempglyph.ch = g; tempglyph.colour = col; return &tempglyph; @@ -2898,11 +2937,32 @@ skill_t *getobskill(object_t *o) { return NULL; } +int getobspellpower(object_t *o, lifeform_t *lf) { + flag_t *f; + int power = 1; + f = hasflag(o->flags, F_LINKSPELL); + if (f) { + power = f->val[1]; + if (power == NA) power = 1; + if (lf) { + // increase based on your magic item usage skill + power += (getskill(lf, SK_CHANNELING)*2); + } + // blessed objects are more powerful + if (isblessed(o)) power += 4; + + // enforce limits + } + limit(&power, 1, 10); + return power; +} + // returns value of obejcts, in gold int getobvalue(object_t *o) { float price; flag_t *f; int rarity = 0; + enum RARITY rr = RR_COMMON; if (o->type->id == OT_GOLD) { return o->amt; @@ -2944,10 +3004,9 @@ int getobvalue(object_t *o) { if (o->type->obclass->id == OC_BOOK) { price += (pow(getspelllevel(f->val[0]), 2) * 30); } else if (o->type->obclass->id == OC_SCROLL) { - // do nothing price += (pow(getspelllevel(f->val[0]), 2) * 2); } else if (o->type->obclass->id == OC_POTION) { - price += (pow(getspelllevel(f->val[0]), 2) * 5); + price += (pow(getspelllevel(f->val[0]), 2)); } else if (o->type->obclass->id == OC_WAND) { price += (pow(getspelllevel(f->val[0]), 2) * 15); } @@ -2956,23 +3015,29 @@ int getobvalue(object_t *o) { } } + // TODO: rings? + + if (hasflag(o->flags, F_HASBRAND)) { + price += 1000; + } + // rarity - rarity = getobrarity(o); + rarity = getobrarity(o, &rr); // potions if (o->type->obclass->id == OC_POTION) { // potion value is based on rarity - price += ((100 - rarity)*2.75); + price += ((100 - rarity)*0.5); } else if (o->type->obclass->id == OC_TOOLS) { // tool value is based on rarity - price += ((100 - rarity)*5.75); + price += ((100 - rarity)*3.75); } else if (o->type->obclass->id == OC_TECH) { // tech value is based on tech level & rarity float multiplier = 1; switch (gettechlevel(o)) { case PR_INEPT: multiplier = 3.25; - break; // do nothing + break; case PR_NOVICE: multiplier = 5.25; break; @@ -3008,7 +3073,26 @@ int getobvalue(object_t *o) { price *= 2; } - // rarity + // scarcity... + switch (rr) { + case RR_UNIQUE: + price *= 5; + break; + case RR_VERYRARE: + price *= 3; + break; + case RR_RARE: + price *= 2; + break; + case RR_UNCOMMON: + break; + case RR_COMMON: + price *= 0.75; + break; + default: + break; + } + /* if (rarity >= 70) { price /= 1.5; } else if (rarity <= 40) { @@ -3018,13 +3102,13 @@ int getobvalue(object_t *o) { } else if (rarity <= 10) { price *= 5; } + */ // blessed/cursed - if (isblessed(o)) price *= 1.5; - if (iscursed(o)) price /= 3; + if (isblessed(o) || iscursed(o)) price *= 1.25; // minimum - if (price < 1) price = 1; + limitf(&price, 1, NA); price = ((int)price * o->amt); return (int) price; @@ -3447,7 +3531,7 @@ enum DEPTH getobdepth(object_t *o, lifeform_t *lf) { depth = f->val[0]; if (lf) { int mod; - mod = SZ_HUMAN - getlfsize(lf); + mod = (SZ_HUMAN - getlfsize(lf)) * DP_CALF; depth += mod; limit(&depth, DP_NONE, DP_HEAD); } @@ -3504,6 +3588,9 @@ char *getobdesc(object_t *o, char *buf) { } else { sprintf(buf, "%s", o->type->desc); } + } else if (o->type->id == OT_WATERDEEP) { + sprintf(buf, "%s water.", getwaterdepthname(getobdepth(o, player))); + capitalise(buf); } else { sprintf(buf, "%s", o->type->desc); } @@ -3693,7 +3780,7 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan sprintf(buf, "%s %s",r->name, o->type->name); strcat(basename, buf); } else { - sprintf(basename, "%s", o->type->name); + strcat(basename, o->type->name); } // skilled and upwards get the direction @@ -3705,6 +3792,8 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan strcat(basename, dname); } } // end if sight/smell + } else if (o->type->id == OT_WATERDEEP) { + sprintf(basename, "%s water", getwaterdepthname(getobdepth(o, player))); } else { if (showall) { strcpy(basename,o->type->name); @@ -3737,34 +3826,30 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan if (!showall) { if ((gamemode == GM_GAMESTARTED) && adjustforblind && !haslos(player, where) ) { - // override with obclass names - switch (o->type->obclass->id) { - case OC_BOOK: - strcpy(basename, "book"); - break; - case OC_POTION: - strcpy(basename, "potion"); - break; - case OC_RING: - strcpy(basename, "ring"); - break; - case OC_SCROLL: - strcpy(basename, "scroll"); - break; - case OC_WAND: - strcpy(basename, "wand"); - break; - default: - break; - } - if (o->type->obclass->id == OC_RING) { - strcpy(basename, "ring"); - } else if (o->type->obclass->id == OC_SCROLL) { - strcpy(basename, "scroll"); - } else if (o->type->obclass->id == OC_POTION) { - strcpy(basename, "potion"); - } else if (o->type->obclass->id == OC_RING) { - strcpy(basename, "ring"); + f = hasflag(o->flags, F_FEELTEXT); + if (f) { + strcpy(basename, f->text); + } else { + // override with obclass names + switch (o->type->obclass->id) { + case OC_BOOK: + strcpy(basename, "book"); + break; + case OC_POTION: + strcpy(basename, "potion"); + break; + case OC_RING: + strcpy(basename, "ring"); + break; + case OC_SCROLL: + strcpy(basename, "scroll"); + break; + case OC_WAND: + strcpy(basename, "wand"); + break; + default: + break; + } } } } @@ -4149,8 +4234,12 @@ float getobweight(object_t *o) { float getobunitweight(object_t *o) { float weight; flag_t *f; - - weight = o->weight; + + if (o->type->id == OT_WATERDEEP) { + weight = 75 * getobdepth(o, NULL); + } else { + weight = o->weight; + } // has its material been changed? if (o->material != o->type->material) { @@ -4206,6 +4295,7 @@ char *real_getrandomob(map_t *map, char *buf, int cond, int cval, int forcedepth obmod_t *om; flag_t *omposs[MAXCANDIDATES]; int noms = 0; + enum RARITY wantrr = RR_COMMON; db = obdb; @@ -4216,10 +4306,16 @@ char *real_getrandomob(map_t *map, char *buf, int cond, int cval, int forcedepth depth = getmapdifficulty(map); } - getrarity(depth, &raritymin, &raritymax, RARITYVARIANCEOB, B_TRUE); + getrarityrange(depth, &raritymin, &raritymax, RARITYVARIANCEOB, B_TRUE); + + // pick rr... + wantrr = RR_COMMON; + while ((wantrr < RR_VERYRARE) && onein(3)) { + wantrr++; + } while (!done) { - if (db) dblog("adding random object with rarity value between %d - %d",raritymin,raritymax); + if (db) dblog("adding random object with rarity value between %d - %d and rr <= %d",raritymin,raritymax,wantrr); if (db) { objectclass_t *oc; switch (cond) { @@ -4240,8 +4336,8 @@ char *real_getrandomob(map_t *map, char *buf, int cond, int cval, int forcedepth for (ot = objecttype ; ot ; ot = ot->next) { int rarok = B_FALSE, condok = B_FALSE; flag_t *rarflag = NULL; - // correct rarity? + // correct rarity? rarflag = hasflagval(ot->flags, F_RARITY, H_ALL, NA, NA, NULL); if (!rarflag) { if (map) { @@ -4252,7 +4348,9 @@ char *real_getrandomob(map_t *map, char *buf, int cond, int cval, int forcedepth } if (rarflag) { if ((rarflag->val[1] >= raritymin) && (rarflag->val[1] <= raritymax)) { - rarok = B_TRUE; + if ((rarflag->val[2] == NA) || (rarflag->val[2] <= wantrr)) { + rarok = B_TRUE; + } } } @@ -4299,7 +4397,10 @@ char *real_getrandomob(map_t *map, char *buf, int cond, int cval, int forcedepth } } // end while !done - if (db) dblog("got %d possibilities.",nposs); + if (db) dblog("got %d possibilities. now adjusting for RR_",nposs); + + + // pick a random object from our possiblities selidx = rnd(0,nposs-1); ot = poss[selidx]; @@ -4406,10 +4507,13 @@ char *getrandomobwithclass(map_t *map, enum OBCLASS cid, char *buf, int depthmod return real_getrandomob(map, buf, RO_OBCLASS, cid, getmapdifficulty(map) + depthmod); } -int getobrarity(object_t *o) { +int getobrarity(object_t *o, enum RARITY *rr) { cell_t *c; map_t *m = NULL; flag_t *f; + + if (rr) *rr = RR_COMMON; + // check for rarity on this object's map first c = getoblocation(o); if (c) { @@ -4418,12 +4522,18 @@ int getobrarity(object_t *o) { if (m) { f = hasflagval(o->flags, F_RARITY,m->habitat, NA, NA, NULL); if (f) { + if (rr) { + *rr = (f->val[2] == NA) ? RR_COMMON : f->val[2]; + } return f->val[1]; } } // any rarity value at all? f = hasflag(o->flags, F_RARITY); if (f) { + if (rr) { + *rr = (f->val[2] == NA) ? RR_COMMON : f->val[2]; + } return f->val[1]; } // ie. doesn't randomly appear @@ -4576,7 +4686,7 @@ char *gettopobname(cell_t *c, char *retbuf) { return retbuf; } else { object_t *o; - o = gettopobject(c); + o = gettopobject(c, B_FALSE); if (o) { getobname(o, buf, o->amt); strcat(retbuf, buf); @@ -4734,7 +4844,6 @@ void ignite(object_t *o) { strcpy(convertto, ff->text); } - f = hasflag(o->flags, F_ONFIRE); if (!f) { if (strlen(convertto)) { @@ -4978,6 +5087,7 @@ void initobjects(void) { addflag(lastmaterial->flags, F_DTVULN, DT_FIRE, NA, NA, NULL); // doesn't catch on fire, but IS vulnerable to it addflag(lastmaterial->flags, F_DTVULN, DT_ACID, NA, NA, NULL); addmaterial(MT_FLESH, "flesh", 2); + addflag(lastmaterial->flags, F_FLAMMABLE, 3, NA, NA, NULL); addmaterial(MT_WETPAPER, "wet paper", 3); addmaterial(MT_CLOTH, "cloth", 3); addflag(lastmaterial->flags, F_FLAMMABLE, 3, NA, NA, NULL); @@ -5007,6 +5117,12 @@ void initobjects(void) { addmaterial(MT_SLIME, "slime", 9); addmaterial(MT_STONE, "stone", 10); addflag(lastmaterial->flags, F_HARD, B_TRUE, NA, NA, NULL); + addflag(lastmaterial->flags, F_DTIMMUNE, DT_FIRE, NA, NA, NULL); + addflag(lastmaterial->flags, F_DTIMMUNE, DT_PIERCE, NA, NA, NULL); + addflag(lastmaterial->flags, F_DTIMMUNE, DT_BITE, NA, NA, NULL); + addflag(lastmaterial->flags, F_DTIMMUNE, DT_SLASH, NA, NA, NULL); + addflag(lastmaterial->flags, F_DTRESIST, DT_CHOP, NA, NA, NULL); + addflag(lastmaterial->flags, F_DTRESIST, DT_PROJECTILE, NA, NA, NULL); addmaterial(MT_METAL, "metal", 13); addflag(lastmaterial->flags, F_HARD, B_TRUE, NA, NA, NULL); addflag(lastmaterial->flags, F_DTIMMUNE, DT_FIRE, NA, NA, NULL); @@ -5180,6 +5296,7 @@ void initobjects(void) { addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OBHP, 80, 80, NA, NULL); addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "20-50 stones"); + addflag(lastot->flags, F_FEELTEXT, NA, NA, NA, "a statue"); addot(OT_STAIRSDOWN, "staircase going down", "A stone staircase winding downwards.", MT_STONE, 3000, OC_DFEATURE); addflag(lastot->flags, F_GLYPH, NA, NA, NA, ">"); @@ -5208,6 +5325,7 @@ void initobjects(void) { addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "."); addflag(lastot->flags, F_REPELBLESSED, B_CURSED, NA, NA, NULL); + addflag(lastot->flags, F_NOFEEL, B_TRUE, NA, NA, NULL); addot(OT_PENTAGRAM, "pentagram", "A area imbued with evil.", MT_NOTHING, 0, OC_DFEATURE); addflag(lastot->flags, F_RARITY, H_ALL, 80, NA, ""); @@ -5216,27 +5334,18 @@ void initobjects(void) { addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "."); addflag(lastot->flags, F_REPELBLESSED, B_BLESSED, NA, NA, NULL); + addflag(lastot->flags, F_NOFEEL, 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, 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); + addflag(lastot->flags, F_NOFEEL, B_TRUE, NA, NA, NULL); // terrain - addot(OT_WATERSHALLOW, "shallow water", "Waist-deep water.", MT_WATER, 150, OC_TERRAIN); - addflag(lastot->flags, F_NO_A, B_TRUE, NA, NA, NULL); - addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); - addflag(lastot->flags, F_GLYPH, C_BLUE, NA, NA, "~"); - addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); - addflag(lastot->flags, F_DEEPWATER, DP_WAIST, NA, NA, NULL); - addflag(lastot->flags, F_DTCONVERT, DT_COLD, NA, NA, "sheet of ice"); - addflag(lastot->flags, F_DTCREATEOB, DT_FIRE, 1, DT_COMPASS, "cloud of steam"); - addflag(lastot->flags, F_DRINKABLE, B_TRUE, NA, B_DONTKILL, NULL); - addflag(lastot->flags, F_LINKOB, OT_POT_WATER, NA, NA, NULL); - addflag(lastot->flags, F_REDUCEMOVEMENT, 3, NA, NA, NULL); - - addot(OT_WATERDEEP, "deep water", "Very deep water.", MT_WATER, 300, OC_TERRAIN); + addot(OT_WATERDEEP, "water", "Deep water.", MT_WATER, 300, OC_TERRAIN); addflag(lastot->flags, F_NO_A, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_GLYPH, C_BOLDBLUE, NA, NA, "~"); @@ -5245,8 +5354,8 @@ void initobjects(void) { addflag(lastot->flags, F_DTCREATEOB, DT_FIRE, 1, DT_COMPASS, "cloud of steam"); addflag(lastot->flags, F_DRINKABLE, B_TRUE, NA, B_DONTKILL, NULL); addflag(lastot->flags, F_LINKOB, OT_POT_WATER, NA, NA, NULL); - addflag(lastot->flags, F_DEEPWATER, DP_HEAD, NA, NA, NULL); - addflag(lastot->flags, F_REDUCEMOVEMENT, 4, NA, NA, NULL); + addflag(lastot->flags, F_DEEPWATER, DP_MAX, NA, NA, NULL); + addflag(lastot->flags, F_ONEPERCELL, B_TRUE, NA, NA, NULL); // traps addot(OT_TRAPTRIP, "tripwire", "A thin wire at ankle height.", MT_NOTHING, 0, OC_TRAP); @@ -5265,6 +5374,8 @@ void initobjects(void) { addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "."); addflag(lastot->flags, F_SECRET, 25, NA, NA, NULL); + addflag(lastot->flags, F_NOFEEL, B_TRUE, NA, NA, NULL); + addot(OT_TRAPTELEPORT, "teleportation trap", "A magical dispersal field.", MT_NOTHING, 0, OC_TRAP); addflag(lastot->flags, F_TRAP, NA, B_TRUE, NA, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); @@ -5273,6 +5384,8 @@ void initobjects(void) { addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "."); addflag(lastot->flags, F_SECRET, 30, NA, NA, NULL); + addflag(lastot->flags, F_NOFEEL, B_TRUE, NA, NA, NULL); + addot(OT_TRAPARROW, "arrow trap", "A pressure plate which causes arrows to shoot at you.", MT_NOTHING, 0, OC_TRAP); addflag(lastot->flags, F_TRAP, 25, B_TRUE, NA, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 76, NA, NULL); @@ -5281,6 +5394,8 @@ void initobjects(void) { addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "."); addflag(lastot->flags, F_SECRET, 30, NA, NA, NULL); + addflag(lastot->flags, F_NOFEEL, B_TRUE, NA, NA, NULL); + addot(OT_TRAPARROWP, "poison arrow trap", "A pressure plate which causes poisoned arrows to shoot at you.", MT_NOTHING, 0, OC_TRAP); addflag(lastot->flags, F_TRAP, 25, B_TRUE, NA, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 69, NA, NULL); @@ -5289,6 +5404,8 @@ void initobjects(void) { addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "."); addflag(lastot->flags, F_SECRET, 30, NA, NA, NULL); + addflag(lastot->flags, F_NOFEEL, B_TRUE, NA, NA, NULL); + addot(OT_TRAPGAS, "gas trap", "A pressure plate which releases poisonous gas.", MT_NOTHING, 0, OC_TRAP); addflag(lastot->flags, F_TRAP, 27, B_TRUE, NA, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 69, NA, NULL); @@ -5297,6 +5414,8 @@ void initobjects(void) { addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "."); addflag(lastot->flags, F_SECRET, 30, NA, NA, NULL); + addflag(lastot->flags, F_NOFEEL, B_TRUE, NA, NA, NULL); + addot(OT_TRAPFIRE, "fire trap", "A pressure plate which fires a pillar of flame.", MT_NOTHING, 0, OC_TRAP); addflag(lastot->flags, F_TRAP, 30, B_TRUE, NA, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 59, NA, NULL); @@ -5305,6 +5424,8 @@ void initobjects(void) { addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "."); addflag(lastot->flags, F_SECRET, 30, NA, NA, NULL); + addflag(lastot->flags, F_NOFEEL, B_TRUE, NA, NA, NULL); + addot(OT_TRAPMINE, "landmine trap", "A buried, pressure-sensitive explosive device.", MT_NOTHING, 0, OC_TRAP); addflag(lastot->flags, F_TRAP, 30, B_TRUE, NA, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); @@ -5314,13 +5435,17 @@ void initobjects(void) { addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "."); addflag(lastot->flags, F_SECRET, 30, NA, NA, NULL); + addflag(lastot->flags, F_NOFEEL, B_TRUE, NA, NA, NULL); + // money etc - addot(OT_GOLD, "gold coin", "Sparkling nuggets of gold, the standard currency of Nexus.", MT_GOLD, 0.1, OC_MONEY); + addot(OT_GOLD, "gold coin", "Sparkling nuggets of gold, the standard currency of Nexus.", MT_GOLD, 0.01, OC_MONEY); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_RARITY, H_ALL, 100, NA, ""); addflag(lastot->flags, F_NUMAPPEAR, 1, 100, NA, ""); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_FEELTEXT, NA, NA, NA, "some gold"); + addot(OT_STONE, "stone", "A medium-sized roundish stone.", MT_STONE, 0.5, OC_ROCK); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, ""); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, ""); @@ -5334,6 +5459,7 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, ""); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_POWDER, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_FEELTEXT, NA, NA, NA, "some ash"); addot(OT_ASHEXPLODE, "pile of exploding powder", "A pile of ash.", MT_STONE, 0.1, OC_ROCK); addflag(lastot->flags, F_GLYPH, NA, NA, NA, ","); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, ""); @@ -5342,6 +5468,7 @@ void initobjects(void) { addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_POWDER, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, "pile of ash"); + addflag(lastot->flags, F_FEELTEXT, NA, NA, NA, "some ash"); addot(OT_ASHCONCEAL, "pile of concealing powder", "A pile of ash.", MT_STONE, 0.1, OC_ROCK); addflag(lastot->flags, F_GLYPH, NA, NA, NA, ","); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, ""); @@ -5349,6 +5476,7 @@ void initobjects(void) { addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_POWDER, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, "pile of ash"); + addflag(lastot->flags, F_FEELTEXT, NA, NA, NA, "some ash"); addot(OT_ASHSLEEP, "pile of sleeping powder", "A pile of ash.", MT_STONE, 0.1, OC_ROCK); addflag(lastot->flags, F_GLYPH, NA, NA, NA, ","); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, ""); @@ -5356,6 +5484,7 @@ void initobjects(void) { addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_POWDER, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, "pile of ash"); + addflag(lastot->flags, F_FEELTEXT, NA, NA, NA, "some ash"); addot(OT_GEMOFSEEING, "gem of seeing", "Magically enhances your eyesight.", MT_STONE, 1, OC_ROCK); addflag(lastot->flags, F_HOLDCONFER, F_XRAYVIS, 2, NA, NULL); addflag(lastot->flags, F_HOLDCONFER, F_SEEINVIS, B_TRUE, NA, NULL); @@ -5442,7 +5571,7 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_DUNGEON, 85, NA, NULL); addflag(lastot->flags, F_RARITY, H_FOREST, 85, NA, NULL); addot(OT_MUSHROOM, "mushroom", "A large brown mushroom.", MT_FOOD, 0.2, OC_FOOD); - addflag(lastot->flags, F_EDIBLE, B_TRUE, 50, NA, ""); + addflag(lastot->flags, F_EDIBLE, B_TRUE, 60, NA, ""); addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL); addflag(lastot->flags, F_RARITY, H_FOREST, 100, NA, NULL); addflag(lastot->flags, F_NUMAPPEAR, 1, 3, NA, ""); @@ -5450,6 +5579,7 @@ void initobjects(void) { 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); + addflag(lastot->flags, F_FEELTEXT, NA, NA, NA, "some bread"); 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, ""); @@ -5465,6 +5595,7 @@ void initobjects(void) { 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); + addflag(lastot->flags, F_FEELTEXT, NA, NA, NA, "some bread"); addot(OT_CLOVER, "four leafed clover", "A rare 4-leafed clover.", MT_FOOD, 0.5, OC_FOOD); addflag(lastot->flags, F_GLYPH, C_GREEN, NA, NA, "%"); addflag(lastot->flags, F_EDIBLE, B_TRUE, 5, NA, ""); @@ -5572,93 +5703,93 @@ 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); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_UNCOMMON, 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); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_UNCOMMON, NULL); addot(OT_SCR_MENDING, "scroll of mending", "Repairs damage to objects.", MT_PAPER, 0.5, OC_SCROLL); addflag(lastot->flags, F_LINKSPELL, OT_S_MENDING, NA, NA, NULL); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 98, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 98, RR_UNCOMMON, NULL); addflag(lastot->flags, F_MAXPOWER, 4, NA, 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, 84, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 84, RR_UNCOMMON, NULL); addot(OT_MAP, "piece of graph paper", "Paper containing a set of grid-lines, intended for mapping.", MT_PAPER, 0.5, OC_SCROLL); addflag(lastot->flags, F_HOLDCONFER, F_PHOTOMEM, NA, IFKNOWN, NULL); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, RR_UNCOMMON, NULL); 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, 4, NA, NULL); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, RR_UNCOMMON, NULL); addflag(lastot->flags, F_AIBOOSTITEM, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_AIFLEEITEM, B_TRUE, NA, NA, NULL); addot(OT_SCR_DETECTAURA, "scroll of detect aura", "Senses holiness or evil near the caster.", MT_PAPER, 0.5, OC_SCROLL); addflag(lastot->flags, F_LINKSPELL, OT_S_DETECTAURA, NA, NA, NULL); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 85, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 85, RR_UNCOMMON, NULL); addot(OT_SCR_DETECTLIFE, "scroll of detect life", "Senses life near the caster.", MT_PAPER, 0.5, OC_SCROLL); addflag(lastot->flags, F_LINKSPELL, OT_S_DETECTLIFE, NA, NA, NULL); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 85, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 85, RR_UNCOMMON, NULL); addot(OT_SCR_DETECTOBS, "scroll of detect objects", "Senses objects near the caster.", MT_PAPER, 0.5, OC_SCROLL); addflag(lastot->flags, F_LINKSPELL, OT_S_DETECTOBS, NA, NA, NULL); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 85, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 85, RR_UNCOMMON, NULL); addot(OT_SCR_DETECTMAGIC, "scroll of detect magic", "Allows the reader to detect magical enchantments.", MT_PAPER, 0.5, OC_SCROLL); addflag(lastot->flags, F_LINKSPELL, OT_S_DETECTMAGIC, NA, NA, NULL); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, RR_UNCOMMON, NULL); addot(OT_SCR_FLAMEPILLAR, "scroll of flame pillar", "Creates a tall pillar of flame.", MT_PAPER, 0.5, OC_SCROLL); addflag(lastot->flags, F_LINKSPELL, OT_S_FLAMEPILLAR, NA, NA, NULL); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, RR_UNCOMMON, NULL); - addot(OT_SCR_FLAMEBURST, "scroll of flame burst", "Creates a radial blast of fire out from the caster.", MT_PAPER, 0.5, OC_SCROLL); + addot(OT_SCR_FLAMEBURST, "scroll of flame burst", "Creates a radial blast of fire out from the caster, dealing 2d6 damage. Range is based on spell power.", MT_PAPER, 0.5, OC_SCROLL); addflag(lastot->flags, F_LINKSPELL, OT_S_FLAMEBURST, NA, NA, NULL); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, RR_UNCOMMON, NULL); addot(OT_SCR_ENCHANT, "scroll of enchantment", "Magically enhances a weapon or piece of armour.", MT_PAPER, 0.5, OC_SCROLL); addflag(lastot->flags, F_LINKSPELL, OT_S_ENCHANT, NA, NA, NULL); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, RR_UNCOMMON, NULL); addot(OT_SCR_FREEZEOB, "scroll of freezing touch", "Permenantly changes the next object touched into solid ice.", MT_PAPER, 0.5, OC_SCROLL); addflag(lastot->flags, F_LINKSPELL, OT_S_FREEZEOB, NA, NA, NULL); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, RR_UNCOMMON, 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); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, RR_UNCOMMON, NULL); addot(OT_SCR_LIGHT, "scroll of light", "Creates a permenant light source centred on the caster.", MT_PAPER, 0.5, OC_SCROLL); addflag(lastot->flags, F_LINKSPELL, OT_S_LIGHT, NA, NA, NULL); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, RR_COMMON, NULL); addflag(lastot->flags, F_AIFLEEITEM, B_TRUE, NA, NA, NULL); addot(OT_SCR_MAPPING, "scroll of sense surroundings", "Magically imbues the caster with a map of his/her surroundings.", MT_PAPER, 0.5, OC_SCROLL); addflag(lastot->flags, F_LINKSPELL, OT_S_MAPPING, 4, NA, NULL); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, RR_UNCOMMON, 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); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, RR_UNCOMMON, 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); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, RR_RARE, 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, 4, NA, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); - addflag(lastot->flags, F_AIFLEEITEM, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_AIFLEEITEM, B_TRUE, NA, RR_COMMON, 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); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, RR_UNCOMMON, NULL); addot(OT_SCR_WISH, "scroll of wishing", "Grants the caster any item of their choice (with some limitations).", MT_PAPER, 0.5, OC_SCROLL); addflag(lastot->flags, F_LINKSPELL, OT_S_WISH, NA, NA, NULL); @@ -5882,6 +6013,7 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); + addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); // l2 addot(OT_S_BLADEBURN, "bladeburn", "Ignites the target's bladed weapon, causing it to temporarily deal fire damage.", MT_NOTHING, 0, OC_SPELL); @@ -6049,6 +6181,10 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); + addot(OT_S_EVAPORATE, "evaporate", "Instantly converts all water in the given area into steam.", MT_NOTHING, 0, OC_SPELL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); + addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); addot(OT_S_SLEETSTORM, "sleet storm", "Creates an cloud of sleet, hampering vision and movement.", MT_NOTHING, 0, OC_SPELL); addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); @@ -6358,7 +6494,7 @@ void initobjects(void) { addflag(lastot->flags, F_MAXPOWER, 6, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_NEED, NA, NULL); // l3 - addot(OT_S_ENERGYBLAST, "energy blast", "Causes a ring of energy to expand from the caster, causing 2-6 damage to anything in sight.", MT_NOTHING, 0, OC_SPELL); + addot(OT_S_ENERGYBLAST, "energy blast", "Causes a ring of energy to expand from the caster (radius based on power), causing 2-6 damage to anything in sight.", MT_NOTHING, 0, OC_SPELL); addflag(lastot->flags, F_SPELLSCHOOL, SS_WILD, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJSELF, NA, NA, NULL); @@ -6389,6 +6525,10 @@ void initobjects(void) { addot(OT_S_GIFT, "gift", "Grants the target 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); + addot(OT_S_CREATEVAULT, "create vault", "Create a vault of the given type.", MT_NOTHING, 0, OC_SPELL); + addflag(lastot->flags, F_SPELLLEVEL, 9, NA, NA, NULL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINE, NA, NA, NULL); + addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL); addot(OT_A_EMPLOY, "employ", "Assigns a job to the target lifeform.", MT_NOTHING, 0, OC_ABILITY); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); @@ -6453,374 +6593,79 @@ void initobjects(void) { // books addot(OT_MANUAL, "manual", "Teaches you one level of its subject matter.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 48, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 48, RR_RARE, NULL); addot(OT_SPELLBOOK, "spellbook", "Teaches you the spell contained within.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); - /* - addot(OT_MAN_ARMOUR, "manual of armour", "Teaches you the skill 'armour'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_ARMOUR, NA, NA, NULL); - addot(OT_MAN_ATHLETICS, "manual of athletics", "Teaches you the skill 'athletics'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_ATHLETICS, NA, NA, NULL); - addot(OT_MAN_COOKING, "manual of cooking", "Teaches you the skill 'cooking'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_COOKING, NA, NA, NULL); - addot(OT_MAN_BACKSTAB, "manual of stabbing", "Teaches you the skill 'backstab'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_BACKSTAB, NA, NA, NULL); - addot(OT_MAN_FIRSTAID, "manual of first aid", "Teaches you the skill 'first aid'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_FIRSTAID, NA, NA, NULL); - addot(OT_MAN_LISTEN, "manual of listening", "Teaches you the skill 'listen'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_LISTEN, NA, NA, NULL); - addot(OT_MAN_LOCKPICKING, "manual of lockpicking", "Teaches you the skill 'lockpicking'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_LOCKPICKING, NA, NA, NULL); - addot(OT_MAN_MAGITEMUSAGE, "manual of channeling", "Teaches you the skill 'channeling'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_CHANNELING, NA, NA, NULL); - addot(OT_MAN_RANGED, "manual of ranged weapons", "Teaches you the skill 'ranged weapons'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_RANGED, NA, NA, NULL); - addot(OT_MAN_SHIELDS, "manual of shields", "Teaches you the skill 'shields'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_SHIELDS, NA, NA, NULL); - addot(OT_MAN_SPELLCASTING, "manual of sorcery", "Teaches you the skill 'sorcery'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_SPELLCASTING, NA, NA, NULL); - addot(OT_MAN_SPOTHIDDEN, "manual of searching", "Teaches you the skill 'searching'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_SPOTHIDDEN, NA, NA, NULL); - addot(OT_MAN_STEALTH, "manual of stealth", "Teaches you the skill 'stealth'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_STEALTH, NA, NA, NULL); - addot(OT_MAN_TECHUSAGE, "manual of technology", "Teaches you the skill 'technology'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_TECHUSAGE, NA, NA, NULL); - addot(OT_MAN_TRAPS, "manual of traps", "Teaches you the skill 'traps'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_TRAPS, NA, NA, NULL); - addot(OT_MAN_TWOWEAPON, "manual of dual weilding", "Teaches you the skill 'dual weilding'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_TWOWEAPON, NA, NA, NULL); - // knowledge manuals - addot(OT_MAN_LORE_ARCANA, "tome of arcane lore", "Teaches you the skill 'lore:arcana'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_LORE_ARCANA, NA, NA, NULL); - addot(OT_MAN_LORE_NATURE, "tome of nature lore", "Teaches you the skill 'lore:nature'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_LORE_NATURE, NA, NA, NULL); - addot(OT_MAN_LORE_DEMONS, "tome of demonology", "Teaches you the skill 'lore:demonology'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_LORE_DEMONS, NA, NA, NULL); - addot(OT_MAN_LORE_HUMANOID, "tome of human lore", "Teaches you the skill 'lore:humanoids'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_LORE_HUMANOID, NA, NA, NULL); - addot(OT_MAN_LORE_UNDEAD, "tome of undead lore", "Teaches you the skill 'lore:undead'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_LORE_UNDEAD, NA, NA, NULL); - // weapon manuals - addot(OT_MAN_AXES, "manual of axes", "Teaches you the skill 'axes'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_AXES, NA, NA, NULL); - addot(OT_MAN_CLUBS, "manual of clubs", "Teaches you the skill 'clubs'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_CLUBS, NA, NA, NULL); - addot(OT_MAN_LONGBLADES, "manual of long blades", "Teaches you the skill 'long blades'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_LONGBLADES, NA, NA, NULL); - addot(OT_MAN_POLEARMS, "manual of polearms", "Teaches you the skill 'polearms'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_POLEARMS, NA, NA, NULL); - addot(OT_MAN_SHORTBLADES, "manual of short blades", "Teaches you the skill 'short blades'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_SHORTBLADES, NA, NA, NULL); - addot(OT_MAN_STAVES, "manual of staves", "Teaches you the skill 'staves'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_STAVES, NA, NA, NULL); - addot(OT_MAN_UNARMED, "manual of unarmed combat", "Teaches you the skill 'unarmed combat'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_UNARMED, NA, NA, NULL); - // spell manuals - addot(OT_MAN_SS_ALLOMANCY, "manual of allomancy", "Teaches you the skill 'allomancy'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_SS_ALLOMANCY, NA, NA, NULL); - addot(OT_MAN_SS_AIR, "manual of air magic", "Teaches you the skill 'air magic'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_SS_AIR, NA, NA, NULL); - addot(OT_MAN_SS_DEATH, "manual of necromancy", "Teaches you the skill 'necromancy'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_SS_DEATH, NA, NA, NULL); - addot(OT_MAN_SS_DIVINATION, "manual of divination", "Teaches you the skill 'divination'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_SS_DIVINATION, NA, NA, NULL); - addot(OT_MAN_SS_NATURE, "manual of nature", "Teaches you the skill 'nature magic'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_SS_NATURE, NA, NA, NULL); - addot(OT_MAN_SS_FIRE, "manual of fire magic", "Teaches you the skill 'fire magic'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_SS_FIRE, NA, NA, NULL); - addot(OT_MAN_SS_COLD, "manual of ice magic", "Teaches you the skill 'ice magic'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_SS_COLD, NA, NA, NULL); - addot(OT_MAN_SS_GRAVITY, "manual of gravitation magic", "Teaches you the skill 'gravitation magic'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_SS_GRAVITY, NA, NA, NULL); - addot(OT_MAN_SS_LIFE, "manual of life magic", "Teaches you the skill 'life magic'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_SS_LIFE, NA, NA, NULL); - addot(OT_MAN_SS_MODIFICATION, "manual of modification magic", "Teaches you the skill 'modification magic'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_SS_MODIFICATION, NA, NA, NULL); - addot(OT_MAN_SS_MENTAL, "manual of psionics", "Teaches you the skill 'psionics'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_SS_MENTAL, NA, NA, NULL); - addot(OT_MAN_SS_SUMMONING, "manual of summoning", "Teaches you the skill 'summoning'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_SS_SUMMONING, NA, NA, NULL); - addot(OT_MAN_SS_TRANSLOCATION, "manual of translocation", "Teaches you the skill 'translocation'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_SS_TRANSLOCATION, NA, NA, NULL); - addot(OT_MAN_SS_WILD, "manual of wild magic", "Teaches you the skill 'wild magic'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_SS_WILD, NA, NA, NULL); - */ - - // spellbooks - /* - addot(OT_SB_ANIMATEDEAD, "spellbook of animate dead", "Teaches the spell 'animate dead'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_ANIMATEDEAD, NA, NA, NULL); - addot(OT_SB_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_FEAR, "spellbook of cause fear", "Teaches the spell 'cause fear'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_FEAR, NA, NA, NULL); - addot(OT_SB_FEEBLEMIND, "spellbook of feeblemind", "Teaches the spell 'feeblemind'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_FEEBLEMIND, 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_POSSESSION, "spellbook of possession", "Teaches the spell 'possession'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_POSSESSION, NA, NA, NULL); - addot(OT_SB_WEAKEN, "spellbook of weaken", "Teaches the spell 'weaken'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_WEAKEN, NA, NA, NULL); - addot(OT_SB_BLINDNESS, "spellbook of blindness", "Teaches the spell 'blindness'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_BLINDNESS, NA, NA, NULL); - addot(OT_SB_INFINITEDEATH, "spellbook of infinite death", "Teaches the spell 'infinite death'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_INFINITEDEATH, NA, NA, NULL); - addot(OT_SB_STENCH, "spellbook of stench", "Teaches the spell 'stench'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_STENCH, NA, NA, NULL); - // divination - addot(OT_SB_DETECTLIFE, "spellbook of detect life", "Teaches the spell 'detect life'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_DETECTLIFE, NA, NA, NULL); - addot(OT_SB_DETECTOBS, "spellbook of detect objects", "Teaches the spell 'detect objects'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_DETECTOBS, NA, NA, NULL); - addot(OT_SB_LOCATEOBJECT, "spellbook of locate object", "Teaches the spell 'locate object'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_LOCATEOBJECT, NA, NA, NULL); - addot(OT_SB_LORE, "spellbook of lore", "Teaches the spell 'lore'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_LORE, NA, NA, NULL); - addot(OT_SB_MAPPING, "spellbook of sense surroundings", "Teaches the spell 'surroundings'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_MAPPING, NA, NA, NULL); - addot(OT_SB_DETECTAURA, "spellbook of detect aura", "Teaches the spell 'detect aura'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_DETECTAURA, NA, NA, NULL); - addot(OT_SB_REVEALHIDDEN, "spellbook of reveal hidden", "Teaches the spell 'reveal hidden'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_REVEALHIDDEN, NA, NA, NULL); - addot(OT_SB_SEEINVIS, "spellbook of see invisible", "Teaches the spell 'see invisible'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_SEEINVIS, NA, NA, NULL); - addot(OT_SB_IDENTIFY, "spellbook of identification", "Teaches the spell 'identification'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_IDENTIFY, NA, NA, NULL); - // elemental - air - addot(OT_SB_AIRBLAST, "spellbook of airblast", "Teaches the spell 'airblast'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_AIRBLAST, NA, NA, NULL); - addot(OT_SB_CALLLIGHTNING, "spellbook of call lightning", "Teaches the spell 'call lightning'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_CALLLIGHTNING, NA, NA, NULL); - addot(OT_SB_CLOUDKILL, "spellbook of cloudkill", "Teaches the spell 'cloudkill'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_CLOUDKILL, NA, NA, NULL); - addot(OT_SB_GUSTOFWIND, "spellbook of gust of wind", "Teaches the spell 'gust of wind'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_GUSTOFWIND, NA, NA, NULL); - addot(OT_SB_LIGHTNINGSTORM, "spellbook of lightning storm", "Teaches the spell 'lightning storm'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_LIGHTNINGSTORM, NA, NA, NULL); - addot(OT_SB_WINDSHIELD, "spellbook of cyclonic shield", "Teaches the spell 'cyclonic shield'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_WINDSHIELD, NA, NA, NULL); - // elemental - fire - addot(OT_SB_BLADEBURN, "spellbook of bladeburn", "Teaches the spell 'bladeburn'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_BLADEBURN, NA, NA, NULL); - addot(OT_SB_BURNINGWAVE, "spellbook of burning wave", "Teaches the spell 'burning wave'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_BURNINGWAVE, NA, NA, NULL); - addot(OT_SB_SPARK, "spellbook of spark", "Teaches the spell 'spark'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_SPARK, NA, NA, NULL); - addot(OT_SB_FIREDART, "spellbook of flame dart", "Teaches the spell 'flame dart'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_FIREDART, NA, NA, NULL); - addot(OT_SB_FLAMEPILLAR, "spellbook of flame pillar", "Teaches the spell 'flame pillar'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_FLAMEPILLAR, NA, NA, NULL); - addot(OT_SB_FLAMEBURST, "spellbook of flame burst", "Teaches the spell 'flame burst'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_FLAMEBURST, NA, NA, NULL); - addot(OT_SB_FIREBALL, "spellbook of fireball", "Teaches the spell 'fireball'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_FIREBALL, NA, NA, NULL); - addot(OT_SB_SLOW, "spellbook of slowness", "Teaches the spell 'slowness'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_SLOW, NA, NA, NULL); - addot(OT_SB_GRAVLOWER, "spellbook of lessen gravity", "Teaches the spell 'lessen gravity'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_GRAVLOWER, NA, NA, NULL); - addot(OT_SB_GRAVBOOST, "spellbook of boost gravity", "Teaches the spell 'boost gravity'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_GRAVBOOST, NA, NA, NULL); - addot(OT_SB_FLIGHT, "spellbook of fly", "Teaches the spell 'fly'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_FLIGHT, NA, NA, NULL); - addot(OT_SB_HASTE, "spellbook of haste", "Teaches the spell 'haste'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_HASTE, NA, NA, NULL); - addot(OT_SB_LEVITATION, "spellbook of levitation", "Teaches the spell 'levitation'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_LEVITATION, NA, NA, NULL); - // elemental - ice - addot(OT_SB_CHILL, "spellbook of chill", "Teaches the spell 'chill'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_CHILL, NA, NA, NULL); - addot(OT_SB_COLDRAY, "spellbook of cone of cold", "Teaches the spell 'cone of cold'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_COLDRAY, NA, NA, NULL); - addot(OT_SB_FROSTBITE, "spellbook of frostbite", "Teaches the spell 'frostbite'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_FROSTBITE, NA, NA, NULL); - addot(OT_SB_FREEZEOB, "spellbook of freezing touch", "Teaches the spell 'freezing touch'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_FREEZEOB, NA, NA, NULL); - addot(OT_SB_ICEEDGE, "spellbook of ice edge", "Teaches the spell 'ice edge'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_ICEEDGE, NA, NA, NULL); - addot(OT_SB_ICICLE, "spellbook of icicle", "Teaches the spell 'icicle'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_ICICLE, NA, NA, NULL); - addot(OT_SB_WALLOFICE, "spellbook of wall of ice", "Teaches the spell 'wall of ice'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_WALLOFICE, NA, NA, NULL); - // life - addot(OT_SB_HEALINGMIN, "spellbook of minor healing", "Teaches the spell 'minor healing'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_HEALINGMIN, NA, NA, NULL); - addot(OT_SB_TURNUNDEAD, "spellbook of turn undead", "Teaches the spell 'turn undead'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_TURNUNDEAD, NA, NA, NULL); - addot(OT_SB_HEALING, "spellbook of healing", "Teaches the spell 'healing'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_HEALING, NA, NA, NULL); - // mental - addot(OT_SB_MINDSCAN, "spellbook of mind scan", "Teaches the spell 'mind scan'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_MINDSCAN, NA, NA, NULL); - addot(OT_SB_SLEEP, "spellbook of sleep", "Teaches the spell 'sleep'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_SLEEP, NA, NA, NULL); - addot(OT_SB_TELEKINESIS, "spellbook of telekinesis", "Teaches the spell 'telekinesis'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_TELEKINESIS, NA, NA, NULL); - addot(OT_SB_PACIFY, "spellbook of pacify", "Teaches the spell 'pacify'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_PACIFY, NA, NA, NULL); - addot(OT_SB_PSYARMOUR, "spellbook of psychic armour", "Teaches the spell 'psychic armour'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_PSYARMOUR, NA, NA, NULL); - addot(OT_SB_CHARM, "spellbook of charm", "Teaches the spell 'charm'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_CHARM, NA, NA, NULL); - // modification - addot(OT_SB_HOLDPORTAL, "spellbook of hold portal", "Teaches the spell 'hold portal'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_HOLDPORTAL, NA, NA, NULL); - addot(OT_SB_INSCRIBE, "spellbook of inscribe", "Teaches the spell 'inscribe'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_INSCRIBE, NA, NA, NULL); - addot(OT_SB_INVISIBILITY, "spellbook of invisibility", "Teaches the spell 'invisibility'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_INVISIBILITY, NA, NA, NULL); - addot(OT_SB_KNOCK, "spellbook of knock", "Teaches the spell 'knock'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_KNOCK, NA, NA, NULL); - addot(OT_SB_LIGHT, "spellbook of light", "Teaches the spell 'light'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_LIGHT, NA, NA, NULL); - addot(OT_SB_DARKNESS, "spellbook of darkness", "Teaches the spell 'darkness'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_DARKNESS, NA, NA, NULL); - addot(OT_SB_COLDBURST, "spellbook of cold burst", "Teaches the spell 'cold burst'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_COLDBURST, NA, NA, NULL); - addot(OT_SB_DIG, "spellbook of dig", "Teaches the spell 'dig'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_DIG, NA, NA, NULL); - addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL); - addot(OT_SB_GASEOUSFORM, "spellbook of gaseous form", "Teaches the spell 'gaseous form'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_GASEOUSFORM, NA, NA, NULL); - addot(OT_SB_GREASE, "spellbook of grease", "Teaches the spell 'grease'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_GREASE, NA, NA, NULL); - addot(OT_SB_MENDING, "spellbook of mending", "Teaches the spell 'mending'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_MENDING, NA, NA, NULL); - addot(OT_SB_PASSWALL, "spellbook of passwall", "Teaches the spell 'passwall'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_PASSWALL, NA, NA, NULL); - - addot(OT_SB_PETRIFY, "spellbook of petrify", "Teaches the spell 'petrify'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_PETRIFY, NA, NA, NULL); - addot(OT_SB_POLYMORPH, "spellbook of polymorph", "Teaches the spell 'polymorph'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_POLYMORPH, NA, NA, NULL); - addot(OT_SB_STICKTOSNAKE, "spellbook of sticks to snakes", "Teaches the spell 'sticks to snakes'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_STICKTOSNAKE, NA, NA, NULL); - // summoning - addot(OT_SB_CREATEMONSTER, "spellbook of create monster", "Teaches the spell 'create monster'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_CREATEMONSTER, NA, NA, NULL); - addot(OT_SB_SUMMONWEAPON, "spellbook of summon weapon", "Teaches the spell 'summon weapon'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_SUMMONWEAPON, NA, NA, NULL); - // translocation - addot(OT_SB_BLINK, "spellbook of blink", "Teaches the spell 'blink'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_BLINK, NA, NA, NULL); - addot(OT_SB_DISPERSAL, "spellbook of dispersal", "Teaches the spell 'dispersal'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_DISPERSAL, NA, NA, NULL); - addot(OT_SB_GATE, "spellbook of gate", "Teaches the spell 'gate'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_GATE, NA, NA, NULL); - addot(OT_SB_TELEPORT, "spellbook of teleportation", "Teaches the spell 'teleportation'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_TELEPORT, NA, NA, NULL); - addot(OT_SB_TWIDDLE, "spellbook of twiddle", "Teaches the spell 'twiddle'.", MT_PAPER, 1.5, OC_BOOK); - addflag(lastot->flags, F_LINKSPELL, OT_S_TWIDDLE, NA, NA, NULL); - */ - - - // assign rarity to books - /* - for (ot = objecttype ; ot ; ot = ot->next) { - if ((ot->obclass->id == OC_BOOK) && !hasflag(ot->flags, F_RARITY)) { - flag_t *f; - f = hasflag(ot->flags, F_LINKSPELL); - if (f) { - // find the linked spell - objecttype_t *spelltype; - spelltype = findot(f->val[0]); - if (spelltype) { - flag_t *f2; - f2 = hasflag(spelltype->flags, F_SPELLLEVEL); - if (f2) { - int rarity; - rarity = 90 - (f2->val[0]*12) - rnd(1,10); - addflag(ot->flags, F_RARITY, H_ALL, rarity, NA, NULL); - } else { - dblog("Spell %s has no spell level - can't determine rarity for spellbook.", spelltype->name); - exit(1); - } - } else { - dblog("Spellbook %s linked to a spell id that doesn't exist.",ot->name); - exit(1); - } - } else if (hasflag(ot->flags, F_MANUALOF)) { - addflag(ot->flags, F_RARITY, H_ALL, 50, NA, NULL); - } - - } - } - */ - + addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, RR_RARE, NULL); // wands addot(OT_WAND_KNOCK, "wand of opening", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, RR_UNCOMMON, NULL); addflag(lastot->flags, F_LINKSPELL, OT_S_KNOCK, NA, NA, NULL); addflag(lastot->flags, F_OPERNEEDTARGET, TT_DOOR, NA, NA, NULL); addot(OT_WAND_LIGHT, "wand of light", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 83, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 83, RR_UNCOMMON, NULL); addflag(lastot->flags, F_LINKSPELL, OT_S_LIGHT, 3, NA, NULL); addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, NA, NA, NULL); addot(OT_WAND_REVEALHIDDEN, "wand of reveal hidden", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, RR_UNCOMMON, NULL); addflag(lastot->flags, F_LINKSPELL, OT_S_REVEALHIDDEN, NA, NA, NULL); addot(OT_WAND_SLOW, "wand of slowness", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, RR_RARE, NULL); addflag(lastot->flags, F_LINKSPELL, OT_S_SLOW, NA, NA, NULL); addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); addot(OT_WAND_DIGGING, "wand of digging", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, RR_RARE, NULL); addflag(lastot->flags, F_LINKSPELL, OT_S_DIG, NA, NA, NULL); addflag(lastot->flags, F_OPERNEEDTARGET, TT_NONE, NA, NA, NULL); addot(OT_WAND_COLD, "wand of cold", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 73, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 73, RR_RARE, NULL); addflag(lastot->flags, F_LINKSPELL, OT_S_COLDRAY, NA, NA, NULL); addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); addot(OT_WAND_FIRE, "wand of fire", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 73, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 73, RR_RARE, NULL); addflag(lastot->flags, F_LINKSPELL, OT_S_FIREDART, NA, NA, NULL); addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); addot(OT_WAND_HASTE, "wand of haste", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, RR_RARE, NULL); addflag(lastot->flags, F_LINKSPELL, OT_S_HASTE, NA, NA, NULL); addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL); addot(OT_WAND_WEAKNESS, "wand of enfeeblement", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, RR_RARE, NULL); addflag(lastot->flags, F_LINKSPELL, OT_S_WEAKEN, NA, NA, NULL); addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); addot(OT_WAND_WONDER, "wand of wonder", "Produces random effects.", MT_METAL, 0.5, OC_WAND); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, RR_RARE, NULL); addflag(lastot->flags, F_OPERNEEDTARGET, TT_NONE, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); addot(OT_WAND_INVIS, "wand of invisibility", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 65, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 65, RR_RARE, NULL); addflag(lastot->flags, F_LINKSPELL, OT_S_INVISIBILITY, NA, NA, NULL); addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL); addot(OT_WAND_DISPERSAL, "wand of dispersal", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 65, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 65, RR_RARE, NULL); addflag(lastot->flags, F_LINKSPELL, OT_S_DISPERSAL, NA, NA, NULL); addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER|TT_OBJECT, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); addflag(lastot->flags, F_AIFLEEITEM, B_TRUE, NA, NA, NULL); addot(OT_WAND_FIREBALL, "wand of fireball", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 65, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 65, RR_RARE, NULL); addflag(lastot->flags, F_LINKSPELL, OT_S_FIREBALL, NA, NA, NULL); addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); addot(OT_WAND_DETONATION, "wand of detonation", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, RR_RARE, NULL); addflag(lastot->flags, F_LINKSPELL, OT_S_DETONATE, NA, NA, NULL); addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER|TT_DOOR, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); addot(OT_WAND_POLYMORPH, "wand of polymorph", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, RR_RARE, NULL); addflag(lastot->flags, F_LINKSPELL, OT_S_POLYMORPH, NA, NA, NULL); addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); @@ -6840,6 +6685,7 @@ void initobjects(void) { addflag(lastot->flags, F_GLYPH, NA, NA, NA, "!"); addflag(lastot->flags, F_PRODUCESLIGHT, 2, NA, NA, NULL); addflag(lastot->flags, F_HOLDCONFER, F_PRODUCESLIGHT, 2, IFKNOWN, NULL); + addflag(lastot->flags, F_FEELTEXT, NA, NA, NA, "a flask"); addot(OT_CANDLE, "candle", "A short wax candle.", MT_WAX, 0.2, OC_TOOLS); addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL); @@ -7072,8 +6918,6 @@ void initobjects(void) { // misc - - addot(OT_EMPTYFLASK, "empty flask", "An empty glass flask.", MT_GLASS, 0.2, OC_MISC); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); @@ -7100,7 +6944,7 @@ void initobjects(void) { addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_GLYPH, NA, NA, NA, "^"); addflag(lastot->flags, F_SHARP, 2, 5, NA, NULL); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); addot(OT_ICESHEET, "sheet of ice", "A large sheet of slippery ice.", MT_ICE, 0.5, OC_MISC); addflag(lastot->flags, F_STACKABLE, NA, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); @@ -7139,7 +6983,7 @@ void initobjects(void) { addflag(lastot->flags, F_GLYPH, NA, NA, NA, "?"); addflag(lastot->flags, F_NOMATCONVERT, NA, NA, NA, NULL); - addot(OT_VOMITPOOL, "pool of vomit", "A disgusting pool of regurgitated food.", MT_WATER, 0, OC_MISC); + addot(OT_VOMITPOOL, "pool of vomit", "A disgusting pool of regurgitated food.", MT_WATER, 1, 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, C_GREEN, NA, NA, ","); @@ -7191,14 +7035,14 @@ void initobjects(void) { addflag(lastot->flags, F_DRINKABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_LINKOB, OT_POT_ACID, NA, NA, NULL); - addot(OT_SLIMEPOOL, "pool of slime", "A disgusting mass of sticky slime.", MT_WATER, 0, OC_MISC); + addot(OT_SLIMEPOOL, "pool of slime", "A disgusting mass of sticky slime.", MT_WATER, 20, 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_NOPICKUP, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_EDIBLE, B_TRUE, 2, NA, NULL); - addot(OT_PUDDLEOIL, "puddle of oil", "A slippery puddle of oil.", MT_OIL, 0, OC_MISC); + addot(OT_PUDDLEOIL, "puddle of oil", "A slippery puddle of oil.", MT_OIL, 15, 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, C_GREY, NA, NA, ","); // should really be dark grey @@ -7215,7 +7059,7 @@ void initobjects(void) { addflag(lastot->flags, F_OBDIETEXT, NA, NA, NA, "evaporates"); // 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); + addot(OT_SPLASHWATER, "splash of water", "A small splash of water.", MT_NOTHING, 0.5, 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, C_BLUE, NA, NA, ","); @@ -7228,7 +7072,7 @@ void initobjects(void) { addflag(lastot->flags, F_DTVULN, DT_FIRE, NA, NA, "0d1+100"); addflag(lastot->flags, F_LINKOB, OT_POT_WATER, NA, NA, NULL); - addot(OT_MUDPOOL, "pool of mud", "A large puddle of wet mud.", MT_WATER, 0, OC_MISC); + addot(OT_MUDPOOL, "pool of mud", "A large puddle of wet mud.", MT_WATER, 60, 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, C_BROWN, NA, NA, "{"); @@ -7241,7 +7085,7 @@ void initobjects(void) { //addflag(lastot->flags, F_WALKDAM, DT_WATER, NA, NA, "0d1+1"); addflag(lastot->flags, F_WALKDAMBP, BP_FEET, DT_WATER, FALLTHRU, "0d1+1"); - addot(OT_PUDDLEWATER, "small puddle of water", "A small puddle of water.", MT_WATER, 0, OC_MISC); + addot(OT_PUDDLEWATER, "small puddle of water", "A small puddle of water.", MT_WATER, 10, 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, C_BLUE, NA, NA, ","); @@ -7255,7 +7099,7 @@ void initobjects(void) { //addflag(lastot->flags, F_WALKDAM, DT_WATER, NA, NA, "0d1+1"); addflag(lastot->flags, F_WALKDAMBP, BP_FEET, DT_WATER, FALLTHRU, "0d1+1"); - addot(OT_PUDDLEWATERL, "large puddle of water", "A large pool of water.", MT_WATER, 0, OC_MISC); + addot(OT_PUDDLEWATERL, "large puddle of water", "A large pool of water.", MT_WATER, 20, 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, C_BLUE, NA, NA, "{"); @@ -7268,7 +7112,6 @@ void initobjects(void) { addflag(lastot->flags, F_LINKOB, OT_POT_WATER, NA, NA, NULL); addflag(lastot->flags, F_WALKDAMBP, BP_FEET, DT_WATER, FALLTHRU, "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); @@ -7291,6 +7134,7 @@ void initobjects(void) { 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_BLOODC, NA, NA, NULL); + addflag(lastot->flags, F_NOFEEL, B_TRUE, NA, NA, NULL); addot(OT_BLOODSPLASH, "splash of blood", "A small pool of blood.", MT_BLOOD, 0, OC_MISC); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL); @@ -7375,6 +7219,7 @@ void initobjects(void) { addflag(lastot->flags, F_INVULNERABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOGLYPH, NA, NA, NA, NULL); addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_NOFEEL, B_TRUE, NA, NA, NULL); // NOTE: must add F_TRAIL when creating this object. addot(OT_SCENT, "scent", "The scent of a creature, only perceivable to those with an enhanced sense of smell.", MT_NOTHING, 0, OC_MISC); addflag(lastot->flags, F_NO_A, B_TRUE, NA, NA, NULL); @@ -7383,11 +7228,12 @@ void initobjects(void) { addflag(lastot->flags, F_INVULNERABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOGLYPH, NA, NA, NA, NULL); addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_NOFEEL, B_TRUE, NA, NA, NULL); // NOTE: must add F_TRAIL when creating this object. // effects addot(OT_FIRELARGE, "large fire", "A large, roaring inferno.", MT_FIRE, 0, OC_EFFECT); - addflag(lastot->flags, F_GLYPH, C_ORANGE, NA, NA, "^"); + addflag(lastot->flags, F_GLYPH, C_ORANGE, NA, NA, "~"); addflag(lastot->flags, F_DIECONVERTTEXT, NA, NA, NA, "dies down a little"); addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "medium fire"); addflag(lastot->flags, F_OBHP, 3, 3, NA, NULL); @@ -7398,7 +7244,7 @@ void initobjects(void) { addflag(lastot->flags, F_PRODUCESLIGHT, 3, NA, NA, NULL); addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "!"); addot(OT_FIREMED, "medium fire", "A medium-sized roaring fire.", MT_FIRE, 0, OC_EFFECT); - addflag(lastot->flags, F_GLYPH, C_RED, NA, NA, "^"); + addflag(lastot->flags, F_GLYPH, C_RED, NA, NA, "~"); addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "small fire"); addflag(lastot->flags, F_DIECONVERTTEXT, NA, NA, NA, "dies down a little"); addflag(lastot->flags, F_OBHP, 3, 3, NA, NULL); @@ -7409,7 +7255,7 @@ void initobjects(void) { addflag(lastot->flags, F_PRODUCESLIGHT, 2, NA, NA, NULL); addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "!"); addot(OT_FIRESMALL, "small fire", "A small blaze.", MT_FIRE, 0, OC_EFFECT); - addflag(lastot->flags, F_GLYPH, C_RED, NA, NA, "^"); + addflag(lastot->flags, F_GLYPH, C_RED, NA, NA, "~"); addflag(lastot->flags, F_OBDIETEXT, B_TRUE, NA, NA, "goes out"); addflag(lastot->flags, F_OBHP, 3, 3, NA, NULL); addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL); @@ -7556,7 +7402,7 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_FOREST, 90, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_GLYPH, C_GREEN, NA, NA, "^"); - addflag(lastot->flags, F_RESTRICTMOVEMENT, 30, B_FALSE, NA, NULL);// the value here will be filled in by the spell. + addflag(lastot->flags, F_RESTRICTMOVEMENT, 30, B_FALSE, B_TRUE, NULL);// the value here will be filled in by the spell. addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OBHP, 5, 5, NA, NULL); addflag(lastot->flags, F_DTVULN, DT_FIRE, NA, NA, NULL); @@ -7569,7 +7415,7 @@ void initobjects(void) { addflag(lastot->flags, F_GLYPH, C_GREY, NA, NA, "^"); addflag(lastot->flags, F_RARITY, H_DUNGEON, 86, NA, NULL); addflag(lastot->flags, F_RARITY, H_FOREST, 88, NA, NULL); - addflag(lastot->flags, F_RESTRICTMOVEMENT, 25, B_TRUE, NA, NULL); + addflag(lastot->flags, F_RESTRICTMOVEMENT, 25, B_TRUE, B_TRUE, NULL); addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OBHP, 5, 5, NA, NULL); @@ -7878,7 +7724,7 @@ void initobjects(void) { addot(OT_RING_HUNGER, "ring of hunger", "Greatly increases the metabolic rate of the wearer.", MT_METAL, 0.1, OC_RING); addflag(lastot->flags, F_RARITY, H_ALL, 73, NA, ""); - addflag(lastot->flags, F_EQUIPCONFER, F_FASTMETAB, 4, NA, NULL); + addflag(lastot->flags, F_EQUIPCONFER, F_FASTMETAB, 3, NA, NULL); addflag(lastot->flags, F_STARTBLESSED, B_CURSED, NA, 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, 73, NA, ""); @@ -8082,14 +7928,12 @@ void initobjects(void) { // axes addot(OT_AXE, "axe", "A short pole with a heavy, wedge-shaped blade for chopping.", MT_METAL, 4, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL); - addflag(lastot->flags, F_OBATTACKDELAY, 150, NA, NA, NULL); addflag(lastot->flags, F_DAM, DT_CHOP, NA, NA, "1d6"); 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, 9, NA, NULL); addot(OT_BATTLEAXE, "battleaxe", "An large axe specifically designed for combat.", MT_METAL, 5, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); - addflag(lastot->flags, F_OBATTACKDELAY, 140, NA, NA, NULL); addflag(lastot->flags, F_DAM, DT_CHOP, NA, NA, "1d8+1"); addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); @@ -8097,7 +7941,7 @@ void initobjects(void) { addflag(lastot->flags, F_ATTREQ, A_STR, 13, 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); + addflag(lastot->flags, F_OBATTACKDELAY, 150, NA, NA, NULL); addflag(lastot->flags, F_DAM, DT_CHOP, NA, NA, "1d9+1"); addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_ACCURACY, 70, NA, NA, NULL); @@ -8105,7 +7949,6 @@ void initobjects(void) { addflag(lastot->flags, F_ATTREQ, A_STR, 16, NA, NULL); addot(OT_HANDAXE, "hand axe", "A fast one-handed axe, ideal for throwing.", MT_METAL, 2, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); - addflag(lastot->flags, F_OBATTACKDELAY, 120, NA, NA, NULL); addflag(lastot->flags, F_DAM, DT_CHOP, NA, NA, "1d7"); addflag(lastot->flags, F_ACCURACY, 85, NA, NA, NULL); addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL); @@ -8113,7 +7956,6 @@ void initobjects(void) { addflag(lastot->flags, F_ATTREQ, A_STR, 7, NA, NULL); addot(OT_WARAXE, "war axe", "An axe made for combat.", MT_METAL, 4, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); - addflag(lastot->flags, F_OBATTACKDELAY, 130, NA, NA, NULL); addflag(lastot->flags, F_DAM, DT_CHOP, NA, NA, "1d7+1"); addflag(lastot->flags, F_ACCURACY, 85, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_AXES, NA, NA, NULL); @@ -8157,7 +7999,7 @@ void initobjects(void) { addflag(lastot->flags, F_USESSKILL, SK_SHORTBLADES, NA, 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, 73, NA, NULL); - addflag(lastot->flags, F_OBATTACKDELAY, 90, NA, NA, NULL); + addflag(lastot->flags, F_OBATTACKDELAY, 75, NA, NA, NULL); addflag(lastot->flags, F_DAM, DT_PIERCE, NA, NA, "1d4"); addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_SHORTBLADES, NA, NA, NULL); @@ -8197,14 +8039,13 @@ void initobjects(void) { // long blades addot(OT_FALCHION, "falchion", "A single-edged heavy sword made for chopping.", MT_METAL, 4.5, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 61, NA, NULL); - addflag(lastot->flags, F_OBATTACKDELAY, 135, NA, NA, NULL); addflag(lastot->flags, F_DAM, DT_CHOP, NA, NA, "1d8+3"); 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, 13, NA, NULL); addot(OT_GREATSWORD, "greatsword", "A massive two-handed sword.", MT_METAL, 10, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 55, NA, NULL); - addflag(lastot->flags, F_OBATTACKDELAY, 180, NA, NA, NULL); + addflag(lastot->flags, F_OBATTACKDELAY, 150, NA, NA, NULL); addflag(lastot->flags, F_DAM, DT_SLASH, NA, NA, "1d12+6"); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); @@ -8212,7 +8053,6 @@ void initobjects(void) { addflag(lastot->flags, F_ATTREQ, A_STR, 13, 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); addflag(lastot->flags, F_DAM, DT_SLASH, NA, NA, "1d8+4"); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_LONGBLADES, NA, NA, NULL); @@ -8220,18 +8060,17 @@ void initobjects(void) { 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); - addflag(lastot->flags, F_OBATTACKDELAY, 130, NA, NA, NULL); addflag(lastot->flags, F_DAM, DT_SLASH, NA, NA, "1d6"); addflag(lastot->flags, F_ACCURACY, 70, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_LONGBLADES, NA, NA, NULL); addot(OT_SCIMITAR, "scimitar", "A fast, sharp, curved blade.", MT_METAL, 2, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); - addflag(lastot->flags, F_OBATTACKDELAY, 120, NA, NA, NULL); - addflag(lastot->flags, F_DAM, DT_SLASH, NA, NA, "1d8+2"); + addflag(lastot->flags, F_OBATTACKDELAY, 90, NA, NA, NULL); + addflag(lastot->flags, F_DAM, DT_SLASH, NA, NA, "1d7"); 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, 8, NA, NULL); - addot(OT_CUTLASS, "cutlass", "An accuracte, light-weight pirate blade.", MT_METAL, 1, OC_WEAPON); + addot(OT_CUTLASS, "cutlass", "An accurate, light-weight pirate blade.", MT_METAL, 1, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); addflag(lastot->flags, F_DAM, DT_SLASH, NA, NA, "1d7"); addflag(lastot->flags, F_ACCURACY, 90, NA, NA, NULL); @@ -8305,7 +8144,6 @@ void initobjects(void) { addflag(lastot->flags, F_ATTREQ, A_STR, 7, 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); addflag(lastot->flags, F_DAM, DT_PIERCE, NA, NA, "1d10"); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_POLEARMS, NA, NA, NULL); @@ -8314,8 +8152,8 @@ void initobjects(void) { // staves addot(OT_QUARTERSTAFF, "quarterstaff", "A long, stout pole.", MT_WOOD, 2, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, NULL); - addflag(lastot->flags, F_OBATTACKDELAY, 120, NA, NA, NULL); addflag(lastot->flags, F_DAM, DT_BASH, NA, NA, "1d8"); + addflag(lastot->flags, F_OBATTACKDELAY, 110, NA, NA, NULL); 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); @@ -8324,7 +8162,6 @@ void initobjects(void) { addot(OT_BAMBOOSTAFF, "bamboo staff", "A long hard pole made from bamboo.", MT_WOOD, 1.5, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 85, NA, NULL); - addflag(lastot->flags, F_OBATTACKDELAY, 110, NA, NA, NULL); addflag(lastot->flags, F_DAM, DT_BASH, NA, NA, "2d4"); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); @@ -8334,7 +8171,7 @@ void initobjects(void) { addot(OT_BLADEDSTAFF, "bladed staff", "A long wooden pole with blades on either end.", MT_WOOD, 2, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 85, NA, NULL); - addflag(lastot->flags, F_OBATTACKDELAY, 130, NA, NA, NULL); + addflag(lastot->flags, F_OBATTACKDELAY, 110, NA, NA, NULL); addflag(lastot->flags, F_DAM, DT_SLASH, NA, NA, "2d4+3"); addflag(lastot->flags, F_ACCURACY, 75, NA, NA, NULL); addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); @@ -8345,7 +8182,7 @@ void initobjects(void) { addot(OT_IRONSTAFF, "iron staff", "A long, stout metal pole.", MT_METAL, 4, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL); - addflag(lastot->flags, F_OBATTACKDELAY, 130, NA, NA, NULL); + addflag(lastot->flags, F_OBATTACKDELAY, 110, NA, NA, NULL); addflag(lastot->flags, F_DAM, DT_BASH, NA, NA, "3d4+1"); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); @@ -8357,21 +8194,19 @@ void initobjects(void) { // clubs (bashing) addot(OT_CLUB, "club", "A heavy, blunt wooden instrument to hit things with.", MT_WOOD, 3, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, NULL); - addflag(lastot->flags, F_OBATTACKDELAY, 140, NA, NA, NULL); addflag(lastot->flags, F_DAM, DT_BASH, NA, NA, "1d6"); 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, 7, NA, NULL); addot(OT_FLAIL, "flail", "A flexible chain attached to a heavy weight.", MT_METAL, 6, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); - addflag(lastot->flags, F_OBATTACKDELAY, 140, NA, NA, NULL); addflag(lastot->flags, F_DAM, DT_BASH, NA, NA, "2d4"); 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, 9, NA, NULL); addot(OT_FLAILHEAVY, "heavy flail", "A flexible chain attached to a very heavy weight.", MT_METAL, 12, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); - addflag(lastot->flags, F_OBATTACKDELAY, 155, NA, NA, NULL); + addflag(lastot->flags, F_OBATTACKDELAY, 115, NA, NA, NULL); addflag(lastot->flags, F_DAM, DT_BASH, NA, NA, "2d6"); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_CLUBS, NA, NA, NULL); @@ -8386,7 +8221,6 @@ void initobjects(void) { addflag(lastot->flags, F_ATTREQ, A_STR, 16, 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); addflag(lastot->flags, F_DAM, DT_BASH, NA, NA, "1d7+1"); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_CLUBS, NA, NA, NULL); @@ -8394,14 +8228,13 @@ void initobjects(void) { 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); - addflag(lastot->flags, F_DAM, DT_BASH, NA, NA, "1d9+1"); + addflag(lastot->flags, F_DAM, DT_BASH, NA, NA, "1d9+3"); 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, 13, NA, NULL); addot(OT_NUNCHAKU, "nunchaku", "Two stout sticks connected with a short or rope. Good for disarming.", MT_WOOD, 1.5, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); - addflag(lastot->flags, F_OBATTACKDELAY, 100, NA, NA, NULL); addflag(lastot->flags, F_DISARMATTACK, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DAM, DT_BASH, NA, NA, "1d6+1"); addflag(lastot->flags, F_ACCURACY, 75, NA, NA, NULL); @@ -8409,7 +8242,6 @@ void initobjects(void) { addflag(lastot->flags, F_ATTREQ, A_DEX, 10, NA, NULL); addot(OT_SPANNER, "spanner", "A long, heavy metal wrench.", MT_METAL, 1, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); - addflag(lastot->flags, F_OBATTACKDELAY, 120, NA, NA, NULL); addflag(lastot->flags, F_DAM, DT_BASH, NA, NA, "1d4"); addflag(lastot->flags, F_ACCURACY, 65, NA, NA, NULL); addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL); @@ -8662,6 +8494,15 @@ int iscursed(object_t *o) { return B_FALSE; } +int isdamaged(object_t *o) { + flag_t *f; + f = hasflag(o->flags, F_OBHP); + if (f && (f->val[0] < f->val[1])) { + return B_TRUE; + } + return B_FALSE; +} + int isdangerousob(object_t *o, lifeform_t *lf, int onlyifknown) { enum IQBRACKET iqb; iqb = getiqname(getattr(lf, A_IQ), NULL); @@ -9792,9 +9633,7 @@ int obmatchescondition(object_t *o, long opts) { if ((opts & AO_READABLE) && isreadable(o)) ok = B_TRUE; if ((opts & AO_ARMOUR) && (o->type->obclass->id == OC_ARMOUR)) ok = B_TRUE; if (opts & AO_DAMAGED) { - flag_t *ff; - ff = hasflag(o->flags, F_OBHP); - if (ff && (ff->val[0] < ff->val[1])) { + if (isdamaged(o)) { ok = B_TRUE; } } @@ -10072,7 +9911,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { default: break; } - dospelleffects(lf, spelltocast, power, where ? where->lf : NULL, NULL, where, isblessed(o), &willid); + dospelleffects(lf, spelltocast, power, where ? where->lf : NULL, NULL, where, isblessed(o), &willid, B_FALSE); // special wands } else if (o->type->id == OT_WAND_WONDER) { int power; @@ -10094,67 +9933,67 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { } break; case 1: // summon monster - dospelleffects(lf, OT_S_CREATEMONSTER, rnd(1,4), NULL, NULL, NULL, B_UNCURSED, &willid); + dospelleffects(lf, OT_S_CREATEMONSTER, rnd(1,4), NULL, NULL, NULL, B_UNCURSED, &willid, B_FALSE); break; case 2: // animate dead - dospelleffects(lf, OT_S_ANIMATEDEAD, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid); + dospelleffects(lf, OT_S_ANIMATEDEAD, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid, B_FALSE); break; case 3: // blindness - dospelleffects(lf, OT_S_BLINDNESS, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid); + dospelleffects(lf, OT_S_BLINDNESS, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid, B_FALSE); break; case 4: // levitate - dospelleffects(lf, OT_S_LEVITATION, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid); + dospelleffects(lf, OT_S_LEVITATION, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid, B_FALSE); break; case 5: // dispersal - dospelleffects(lf, OT_S_DISPERSAL, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid); + dospelleffects(lf, OT_S_DISPERSAL, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid, B_FALSE); break; case 6: // flash - dospelleffects(lf, OT_S_FLASH, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid); + dospelleffects(lf, OT_S_FLASH, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid, B_FALSE); break; case 7: // light - dospelleffects(lf, OT_S_LIGHT, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid); + dospelleffects(lf, OT_S_LIGHT, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid, B_FALSE); break; case 8: // heal - dospelleffects(lf, OT_S_HEALING, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid); + dospelleffects(lf, OT_S_HEALING, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid, B_FALSE); break; case 9: // minor heal - dospelleffects(lf, OT_S_HEALINGMIN, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid); + dospelleffects(lf, OT_S_HEALINGMIN, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid, B_FALSE); break; case 10: // invis - dospelleffects(lf, OT_S_INVISIBILITY, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid); + dospelleffects(lf, OT_S_INVISIBILITY, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid, B_FALSE); break; case 11: // haste - dospelleffects(lf, OT_S_HASTE, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid); + dospelleffects(lf, OT_S_HASTE, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid, B_FALSE); break; case 12: // pull - dospelleffects(lf, OT_S_PULL, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid); + dospelleffects(lf, OT_S_PULL, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid, B_FALSE); break; case 13: // blast - dospelleffects(lf, OT_S_AIRBLAST, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid); + dospelleffects(lf, OT_S_AIRBLAST, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid, B_FALSE); break; case 14: // slow - dospelleffects(lf, OT_S_SLOW, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid); + dospelleffects(lf, OT_S_SLOW, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid, B_FALSE); break; case 15: // sleep - dospelleffects(lf, OT_S_SLEEP, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid); + dospelleffects(lf, OT_S_SLEEP, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid, B_FALSE); break; case 16: // gas - dospelleffects(lf, OT_S_CLOUDKILL, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid); + dospelleffects(lf, OT_S_CLOUDKILL, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid, B_FALSE); break; case 17: // dark - dospelleffects(lf, OT_S_DARKNESS, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid); + dospelleffects(lf, OT_S_DARKNESS, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid, B_FALSE); break; case 18: // stone - dospelleffects(lf, OT_S_PETRIFY, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid); + dospelleffects(lf, OT_S_PETRIFY, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid, B_FALSE); break; case 19: // fireball - dospelleffects(lf, OT_S_FIREBALL, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid); + dospelleffects(lf, OT_S_FIREBALL, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid, B_FALSE); break; case 20: // poly - dospelleffects(lf, OT_S_POLYMORPH, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid); + dospelleffects(lf, OT_S_POLYMORPH, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid, B_FALSE); break; case 21: // teleport - dospelleffects(lf, OT_S_TELEPORT, power, lf , NULL, lf->cell, o->blessed, &willid); + dospelleffects(lf, OT_S_TELEPORT, power, lf , NULL, lf->cell, o->blessed, &willid, B_FALSE); break; //oooooooooo } @@ -10876,7 +10715,7 @@ void quaff(lifeform_t *lf, object_t *o) { } if (o->type->obclass->id == OC_POTION) { - potioneffects(lf, o->type->id, o->blessed, &seen); + potioneffects(lf, o->type->id, o, o->blessed, &seen); } else { drinkflag= hasflag(o->flags, F_DRINKABLE); if (drinkflag) { @@ -10884,7 +10723,7 @@ void quaff(lifeform_t *lf, object_t *o) { flag_t *f; f = hasflag(o->flags, F_LINKOB); if (f) { - potioneffects(lf, f->val[0], o->blessed, NULL); + potioneffects(lf, f->val[0], o, o->blessed, NULL); } else { eat(lf, o); } @@ -10915,7 +10754,8 @@ void quaff(lifeform_t *lf, object_t *o) { } -void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE potblessed, int *seen) { +// o can be NULL if we're just doing potion EFFECTS, not actually drinking one. +void potioneffects(lifeform_t *lf, enum OBTYPE oid, object_t *o, enum BLESSTYPE potblessed, int *seen) { char lfname[BUFLEN]; unsigned int dam; int i; @@ -11072,7 +10912,7 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE potblessed, i } break; case OT_POT_ETHEREALNESS: - dospelleffects(lf, OT_S_PASSWALL, (potblessed) ? 5 : 1, lf, NULL, lf->cell, potblessed, seen); + dospelleffects(lf, OT_S_PASSWALL, (potblessed) ? 5 : 1, lf, NULL, lf->cell, potblessed, seen, B_TRUE); break; case OT_POT_EXPERIENCE: // gain xp! @@ -11088,19 +10928,19 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE potblessed, i gainxp(lf, getxpforlev(lf->level+1) - lf->xp); break; case OT_POT_GASEOUSFORM: - dospelleffects(lf, OT_S_GASEOUSFORM, (potblessed) ? 5 : 1, lf, NULL, lf->cell, potblessed, seen); + dospelleffects(lf, OT_S_GASEOUSFORM, (potblessed) ? 5 : 1, lf, NULL, lf->cell, potblessed, seen, B_TRUE); break; case OT_POT_HEALING: - dospelleffects(lf, OT_S_HEALING,potblessed ? 5 : 1, lf, NULL, lf->cell, potblessed, seen); + dospelleffects(lf, OT_S_HEALING,potblessed ? 5 : 1, lf, NULL, lf->cell, potblessed, seen, B_TRUE); break; case OT_POT_HEALINGMIN: - dospelleffects(lf, OT_S_HEALINGMIN,potblessed ? 5 : 1, lf, NULL, lf->cell, potblessed, seen); + dospelleffects(lf, OT_S_HEALINGMIN,potblessed ? 5 : 1, lf, NULL, lf->cell, potblessed, seen, B_TRUE); break; case OT_POT_HEALINGMAJ: - dospelleffects(lf, OT_S_HEALINGMAJ,potblessed ? 5 : 1, lf, NULL, lf->cell, potblessed, seen); + dospelleffects(lf, OT_S_HEALINGMAJ,potblessed ? 5 : 1, lf, NULL, lf->cell, potblessed, seen, B_TRUE); break; case OT_POT_INVIS: - dospelleffects(lf, OT_S_INVISIBILITY,potblessed ? 6 : 3, lf, NULL, lf->cell, potblessed, seen); + dospelleffects(lf, OT_S_INVISIBILITY,potblessed ? 6 : 3, lf, NULL, lf->cell, potblessed, seen, B_TRUE); break; case OT_POT_INVULN: if (getmr(lf) && skillcheck(lf, SC_RESISTMAG, 30, 0)) { @@ -11151,10 +10991,10 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE potblessed, i case OT_POT_POLYMORPH: if (potblessed == B_BLESSED) { // controlled polymorph - dospelleffects(lf, OT_S_POLYMORPH, 5, lf, NULL, lf->cell, potblessed, NULL); + dospelleffects(lf, OT_S_POLYMORPH, 5, lf, NULL, lf->cell, potblessed, NULL, B_TRUE); } else { // random polymorph - dospelleffects(lf, OT_S_POLYMORPH, 1, lf, NULL, lf->cell, potblessed, NULL); + dospelleffects(lf, OT_S_POLYMORPH, 1, lf, NULL, lf->cell, potblessed, NULL, B_TRUE); } break; case OT_POT_RESTORATION: @@ -11234,16 +11074,16 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE potblessed, i } break; case OT_POT_SLEEP: - dospelleffects(lf, OT_S_SLEEP, 8, lf, NULL, lf->cell, B_UNCURSED, NULL); + dospelleffects(lf, OT_S_SLEEP, 8, lf, NULL, lf->cell, B_UNCURSED, NULL, B_TRUE); if (seen) *seen = B_TRUE; break; case OT_POT_SPEED: if (potblessed == B_BLESSED) { - dospelleffects(lf, OT_S_HASTE, 5, lf, NULL, lf->cell, B_BLESSED, NULL); + dospelleffects(lf, OT_S_HASTE, 5, lf, NULL, lf->cell, B_BLESSED, NULL, B_TRUE); } else if (potblessed == B_CURSED) { - dospelleffects(lf, OT_S_SLOW, 5, lf, NULL, lf->cell, B_UNCURSED, NULL); + dospelleffects(lf, OT_S_SLOW, 5, lf, NULL, lf->cell, B_UNCURSED, NULL, B_TRUE); } else { // uncursed - dospelleffects(lf, OT_S_HASTE, 5, lf, NULL, lf->cell, B_UNCURSED, NULL); + dospelleffects(lf, OT_S_HASTE, 5, lf, NULL, lf->cell, B_UNCURSED, NULL, B_TRUE); } if (seen) *seen = B_TRUE; break; @@ -11385,8 +11225,14 @@ int readsomething(lifeform_t *lf, object_t *o) { } } else { switch (o->type->id) { - case OT_SCR_IDENTIFY: // only id if it does something - case OT_SCR_MENDING: // only id if it does something + case OT_SCR_IDENTIFY: + case OT_SCR_MENDING: + if (isblessed(o)) { + willid = B_TRUE; + } else { + // only id if it does something + willid = B_FALSE; + } case OT_SCR_ENCHANT: // only id if it does something case OT_SCR_CREATEMONSTER: // only id if it does something case OT_SCR_REMOVECURSE: // only id if it does something @@ -11403,6 +11249,12 @@ int readsomething(lifeform_t *lf, object_t *o) { switch (o->type->id) { case OT_SCR_IDENTIFY: case OT_SCR_MENDING: + if (isblessed(o)) { + needsob = B_FALSE; + } else { + needsob = B_TRUE; + } + break; case OT_SCR_ENCHANT: needsob = B_TRUE; break; @@ -11427,24 +11279,41 @@ int readsomething(lifeform_t *lf, object_t *o) { } } - if (o->type->obclass->id == OC_SCROLL) { // cast linked spell + // special scrolls + if ((o->type->id == OT_SCR_IDENTIFY) && isblessed(o)) { + int seen = B_FALSE; + if (isplayer(lf)) { + object_t *oo; + // identify evertthing! + for (oo = lf->pack->first ; oo ; oo = oo->next) { + if (!isidentified(oo)) { + dospelleffects(lf, OT_S_IDENTIFY, 10, NULL, oo, NULL, o->blessed, &seen, B_FALSE); + } + } + } + if (seen) makeknown(o->type->id); + } else if ((o->type->id == OT_SCR_MENDING) && isblessed(o)) { + int seen = B_FALSE; + object_t *oo; + int power; + // mend everything! + power = getobspellpower(o, lf); + for (oo = lf->pack->first ; oo ; oo = oo->next) { + if (isdamaged(oo)) { + dospelleffects(lf, OT_S_MENDING, power, NULL, oo, NULL, o->blessed, &seen, B_FALSE); + } + } + if (seen) makeknown(o->type->id); + } else if (o->type->obclass->id == OC_SCROLL) { // cast linked spell object_t *targob = NULL; + + f = hasflag(o->flags, F_LINKSPELL); if (f) { int seen = B_FALSE; int power; - power = f->val[1]; - if (power == NA) power = 1; - - // increase based on your magic item usage skill - power += (getskill(lf, SK_CHANNELING)*2); - - // blessed scrolls are more powerful - if (isblessed(o)) power += 4; - - // enforce maximum - limit(&power, NA, 10); + power = getobspellpower(o, lf); // for unidentified scrolls which target an object, // let player select ANY object (even if it won't @@ -11453,7 +11322,7 @@ int readsomething(lifeform_t *lf, object_t *o) { targob = askobject(lf->pack, "Target which object", NULL, AO_NONE); } - dospelleffects(lf, f->val[0], power, NULL, targob, NULL, o->blessed, &seen); + dospelleffects(lf, f->val[0], power, NULL, targob, NULL, o->blessed, &seen, B_FALSE); if (seen) { // id the scroll now makeknown(o->type->id); @@ -11857,13 +11726,13 @@ void shatter(object_t *o, int hitlf, char *damstring, lifeform_t *fromlf) { if (seen) { makeknown(o->type->id); } - potioneffects(target, o->type->id, o->blessed, &observed); + potioneffects(target, o->type->id, o, o->blessed, &observed); } break; case OT_POT_HEALING: case OT_POT_HEALINGMIN: // only make them known if it had an effect if (target) { - potioneffects(target, o->type->id, o->blessed, &observed); + potioneffects(target, o->type->id, o, o->blessed, &observed); if (observed) { makeknown(o->type->id); } @@ -12481,7 +12350,7 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed, radius = o->amt * 2; if (radius > 10) radius = 10; - spellcloud(srcloc, radius, '}', C_MAGENTA, OT_S_SLEEP, radius); + spellcloud(srcloc, radius, '}', C_MAGENTA, OT_S_SLEEP, radius, B_TRUE); } else { if (haslos(player, srcloc)) { @@ -12858,7 +12727,7 @@ void timeeffectsob(object_t *o) { cell_t *newc; int canseeloc = B_FALSE; - if (haslos(player, location)) { + if (haslos(player, location) && canseeob(player, sg)) { getobname(sg, sgname, sg->amt); canseeloc = B_TRUE; msg("The %s pulses %s!", noprefix(sgname), @@ -13253,10 +13122,10 @@ void trapeffects(object_t *trapob, enum OBTYPE oid, lifeform_t *lf) { } } else if (oid == OT_TRAPFIRE) { // can't be dodged - dospelleffects(NULL, OT_S_FLAMEPILLAR, 3, lf, NULL, lf->cell, B_UNCURSED, NULL); + dospelleffects(NULL, OT_S_FLAMEPILLAR, 3, lf, NULL, lf->cell, B_UNCURSED, NULL, B_TRUE); } else if (oid == OT_TRAPGAS) { // can't be dodged - dospelleffects(NULL, OT_S_CLOUDKILL, 3, lf, NULL, lf->cell, B_UNCURSED, NULL); + dospelleffects(NULL, OT_S_CLOUDKILL, 3, lf, NULL, lf->cell, B_UNCURSED, NULL, B_TRUE); } else if (oid == OT_TRAPMINE) { // can't be dodged explodecells(lf->cell, roll("2d6"), B_FALSE, trapob, 1, DT_ORTH, B_TRUE); diff --git a/objects.h b/objects.h index 44cd66c..b7539a5 100644 --- a/objects.h +++ b/objects.h @@ -61,6 +61,7 @@ int getmissileaccuracy(lifeform_t *thrower, cell_t *where, object_t *missile, ob int getobaccuracy(object_t *wep, lifeform_t *weilder); int getobbonus(object_t *o); skill_t *getobskill(object_t *o); +int getobspellpower(object_t *o, lifeform_t *lf); int getobvalue(object_t *o); //int getobtypevalue(objecttype_t *ot); char *getaccuracyname(int accpct); @@ -103,7 +104,7 @@ char *real_getrandomob(map_t *map, char *buf, int cond, int cval, int forcedepth char *getrandomob(map_t *map, char *buf); char *getrandomobwithdt(map_t *map, enum DAMTYPE damtype, char *buf); char *getrandomobwithclass(map_t *map, enum OBCLASS cid, char *buf, int depthmod); -int getobrarity(object_t *o); +int getobrarity(object_t *o, enum RARITY *rr); enum SPELLSCHOOL getschool(enum OBTYPE sid); char *getschoolname(enum SPELLSCHOOL sch); char *getschoolnameshort(enum SPELLSCHOOL sch); @@ -134,6 +135,7 @@ int isblessed(object_t *o); int isblessknown(object_t *o); int iscorpse(object_t *o); int iscursed(object_t *o); +int isdamaged(object_t *o); int isdangerousob(object_t *o, lifeform_t *lf, int onlyifknown); int isdeadob(object_t *o); int isdrinkable(object_t *o); @@ -190,7 +192,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 potlessed, int *seen); +void potioneffects(lifeform_t *lf, enum OBTYPE oid, object_t *o, 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 49d1623..6c3d13b 100644 --- a/spell.c +++ b/spell.c @@ -1185,7 +1185,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef case OC_RING: break; default: - msg("This doesn't seem to be a standard kind of item."); + msg("Your knowledge doesn't extend to this kind of item."); return B_TRUE; } @@ -1252,7 +1252,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef // returns TRUE on error -int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_t *target, object_t *targob, cell_t *targcell, int blessed, int *seenbyplayer) { +int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_t *target, object_t *targob, cell_t *targcell, int blessed, int *seenbyplayer, int frompot) { char buf[BUFLEN]; char castername[BUFLEN]; int rv = B_FALSE; @@ -1382,7 +1382,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ cell_t *nextc; if (targcell) { - if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE; dir = getdirtowards(caster->cell, targcell, target, B_FALSE, DT_COMPASS); } else { int dirch; @@ -1511,7 +1511,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } else if (spellid == OT_S_BLADEBURN) { object_t *wep; enum DAMTYPE dt; - if (!validatespellcell(caster, &targcell, TT_PLAYER | TT_ALLY, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_PLAYER | TT_ALLY, spellid, power, frompot)) return B_TRUE; target = targcell->lf; if (!target) { fizzle(caster); @@ -1540,7 +1540,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } else if (spellid == OT_S_BLINDNESS) { int failed = B_FALSE; // ask for target - if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE; target = targcell->lf; if (isblind(target)) { @@ -1596,7 +1596,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ cell_t *retcell[MAXRETCELLS]; int nretcell; int i; - if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE; if (cansee(player, caster)) { msg("%s shoot%s a wave of fire!",castername, isplayer(caster) ? "" : "s"); @@ -1645,7 +1645,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } else if (spellid == OT_S_CALLLIGHTNING) { int failed = B_FALSE; // ask for a target cell - if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE; target = targcell->lf; if (target) { @@ -1679,7 +1679,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ // if no target object... if (!targob) { // ask for a target cell (to take objects from) - if (!validatespellcell(caster, &targcell, TT_OBJECT, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_OBJECT, spellid, power, frompot)) return B_TRUE; if (targcell->obpile->first) { // select object from cell... @@ -1777,7 +1777,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ range = getspellrange(spellid, power); - if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE; // create a line of fire towards the target cell animline(caster->cell, targcell, B_FALSE, '/', '\\', C_WHITE); @@ -1854,7 +1854,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } // end while narccells } else if (spellid == OT_S_CLOUDKILL) { int radius; - if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE; if (targcell->type->solid) { fizzle(caster); @@ -1871,7 +1871,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } else if (spellid == OT_S_CHARM) { char targetname[BUFLEN]; - if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE; target = targcell->lf; @@ -1943,7 +1943,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } else if (spellid == OT_S_CHARMANIMAL) { char targetname[BUFLEN]; - if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE; target = targcell->lf; @@ -2016,7 +2016,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } else if (spellid == OT_S_CHILL) { char lfname[BUFLEN]; int exposedlimbs,dam; - if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE; target = targcell->lf; if (!target) { fizzle(caster); @@ -2100,7 +2100,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ cell_t *retcell[MAXRETCELLS]; int nretcell,i; - if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE; // animation anim(caster->cell, targcell, '}', C_GREY); if (isplayer(caster) || cansee(player, caster)) { @@ -2143,7 +2143,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (!targcell) { if ((power >= 5) && isplayer(caster)) { // control location - if (!validatespellcell(caster, &targcell, TT_NONE, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_NONE, spellid, power, frompot)) return B_TRUE; // make sure it's empty if (!cellwalkable(NULL, targcell, NULL)) { targcell = NULL; @@ -2235,8 +2235,20 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } return B_TRUE; } + } else if (spellid == OT_S_CREATEVAULT) { + vault_t *v; + // ask for a vaulttype + v = askvault("Create which vault?"); + + if (createvault(caster->cell->map, caster->cell->map->nrooms, v, NULL, NULL)) { + msg("Couldn't create a vault."); + } else { + msg("BAM! A vault has appeared nearby."); + needredraw = B_TRUE; + } + } else if (spellid == OT_S_CUREPOISON) { - if (!validatespellcell(caster, &targcell,TT_ALLY, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell,TT_ALLY, spellid, power, frompot)) return B_TRUE; target = targcell->lf; if (!target) { fizzle(caster); @@ -2315,7 +2327,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ int ndigs; // don't need line of fire OR sight! - if (!validatespellcell(caster, &targcell, TT_NONE, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_NONE, spellid, power, frompot)) return B_TRUE; // calculate a line from caster to the target cell calcbresnham(caster->cell->map, caster->cell->x, caster->cell->y, @@ -2457,18 +2469,56 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } // end if isplayer } else if (spellid == OT_S_DETONATE) { // don't need line of fire! - if (!validatespellcell(caster, &targcell, TT_MONSTER|TT_DOOR, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_MONSTER|TT_DOOR, spellid, power, frompot)) return B_TRUE; explodecells(targcell, 20, B_TRUE, NULL, power / 4, DT_ORTH, B_TRUE); if (haslos(player, targcell)) { if (seenbyplayer) *seenbyplayer = B_TRUE; } + } else if (spellid == OT_S_EVAPORATE) { + cell_t *cell[MAXCANDIDATES]; + int i,ncells; + int nseen = 0; + int nsteamseen = 0; + // don't need line of fire! + if (!validatespellcell(caster, &targcell, TT_OBJECT, spellid, power, frompot)) return B_TRUE; + + getradiuscells(targcell, power, DT_ORTH, LOF_NEED, B_TRUE, cell, &ncells); + for (i = 0; i < ncells; i++) { + object_t *o,*nexto; + for (o = cell[i]->obpile->first ; o ; o = nexto) { + nexto = o->next; + if (o->material->id == MT_WATER) { + int cellseen = B_FALSE; + if (haslos(player, cell[i])) { + cellseen = B_TRUE; + if (seenbyplayer) *seenbyplayer = B_TRUE; + } + // if 20kilos or more, make steam + if (getobweight(o) >= 25) { + addob(cell[i]->obpile, "cloud of steam"); + if (cellseen) nsteamseen++; + } + nseen++; + removeob(o, ALL); + } + } + } + + if (nsteamseen) { + msg("A huge cloud of steam appears!"); + } else if (nseen) { + msg("Some nearby water evaporates!"); + } else { + fizzle(caster); + } + } else if (spellid == OT_S_EXPLODEMETAL) { float totalmass = 0; object_t *o, *nexto; - if (!validatespellcell(caster, &targcell, TT_OBJECT, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_OBJECT, spellid, power, frompot)) return B_TRUE; // how much metal is there? for (o = targcell->obpile->first ; o ; o = nexto) { @@ -2499,7 +2549,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ object_t *o, *nexto; int donesomething = B_FALSE; - if (!validatespellcell(caster, &targcell,TT_MONSTER|TT_OBJECT, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell,TT_MONSTER|TT_OBJECT, spellid, power, frompot)) return B_TRUE; if (!targcell) { if (isplayer(caster)) { fizzle(caster); @@ -2558,13 +2608,13 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ c = getrandomcell(targcell->map); } - if (haslos(player, targcell)) { + if (haslos(player, targcell) && canseeob(player, o)) { msg("%s disappear%s!", buf, (o->amt == 1) ? "s" : ""); if (seenbyplayer) *seenbyplayer = B_TRUE; donesomething = B_TRUE; } moveob(o, c->obpile, o->amt); - if (haslos(player, c)) { + if (haslos(player, c) && canseeob(player, o)) { msg("%s appear%s nearby!", buf, (o->amt == 1) ? "s" : ""); } } @@ -2574,7 +2624,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ rv = B_FALSE; } else if (spellid == OT_S_DRAINLIFE) { char lfname[BUFLEN]; - if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE; target = haslf(targcell); if (target) { @@ -2644,7 +2694,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } else if (spellid == OT_S_FEAR) { char targname[BUFLEN]; // ask for target - if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE; target = targcell->lf; if (!target) { fizzle(caster); @@ -2674,7 +2724,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } else if (spellid == OT_S_FEEBLEMIND) { // ask for target - if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE; target = targcell->lf; if ((getattr(target, A_IQ) <= 3) || skillcheck(target, SC_RESISTMAG, 20 + power, 0)) { @@ -2719,23 +2769,33 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } else if (spellid == OT_S_FLOOD) { int failed = B_FALSE; // ask for a target cell - if (!validatespellcell(caster, &targcell, TT_NONE, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_NONE, spellid, power, frompot)) return B_TRUE; if (targcell) { if (!targcell->type->solid) { // create water there object_t *o; - o = addob(targcell->obpile, "deep water"); + o = addob(targcell->obpile, "water"); if (o) { enum OBTYPE badoid[2]; int i,amt; + int depth; + depth = DP_SHOULDERS + power; + amt = ((power+1) * (power+1)) - 1; + //amt = power; badoid[0] = OT_WATERDEEP; badoid[1] = OT_NONE; for (i = 0; i < amt; i++) { cell_t *c; c = real_getrandomadjcell(targcell, WE_NOTWALL, B_ALLOWEXPAND, LOF_WALLSTOP, badoid); if (c) { - addob(c->obpile, "deep water"); + object_t *water; + water = addob(c->obpile, "water"); + if (water) { + flag_t *f; + f = hasflag(water->flags, F_DEEPWATER); + if (f) f->val[0] = depth; + } } else { break; } @@ -2760,7 +2820,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ char numbuf[BUFLEN]; numtotext(power, numbuf); - if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE; // animation anim(caster->cell, targcell, '}', C_CYAN); if (isplayer(caster) || cansee(player, caster)) { @@ -2789,7 +2849,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } else if (spellid == OT_S_FIREBALL) { int failed = B_FALSE; // ask for a target cell - if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE; if (targcell) { if (!targcell->type->solid || hasflag(targcell->type->material->flags, F_FLAMMABLE)) { int dir; @@ -2881,7 +2941,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } else if (spellid == OT_S_FIREDART) { char lfname[BUFLEN]; - if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE; // animation anim(caster->cell, targcell, '}', C_RED); if (isplayer(caster) || cansee(player, caster)) { @@ -2941,7 +3001,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } else if (spellid == OT_S_FLAMEPILLAR) { int failed = B_FALSE; // ask for a target cell - if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE; if (targcell) { if (!targcell->type->solid || hasflag(targcell->type->material->flags, F_FLAMMABLE)) { flag_t *f; @@ -3006,7 +3066,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } else if (spellid == OT_S_ENDUREELEMENTS) { flag_t *f; // always targetted at caster - if (!validatespellcell(caster, &targcell,TT_ALLY, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell,TT_ALLY, spellid, power, frompot)) return B_TRUE; target = targcell->lf; if (!target) { fizzle(caster); @@ -3022,7 +3082,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ flag_t *f; object_t *o; - if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE; target = targcell->lf; if (!target) { @@ -3171,7 +3231,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } else if (spellid == OT_S_FROSTBITE) { char lfname[BUFLEN]; - if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE; target = targcell->lf; if (!target) { fizzle(caster); @@ -3219,7 +3279,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } else if (spellid == OT_S_GREASE) { int radius; - if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE; if (targcell->type->solid) { fizzle(caster); @@ -3249,7 +3309,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ limit(&power, NA, 10); } // ask for a target cell - if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE; if (targcell) { if (!targcell->type->solid) { object_t *o; @@ -3300,7 +3360,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } else if (spellid == OT_S_HASTE) { int howlong = 15; - if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE; target = targcell->lf; @@ -3325,7 +3385,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } else if ((spellid == OT_S_HEALING) || (spellid == OT_S_HEALINGMIN) || (spellid == OT_S_HEALINGMAJ)) { int donesomething = B_FALSE; - if (!validatespellcell(caster, &targcell,TT_ALLY, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell,TT_ALLY, spellid, power, frompot)) return B_TRUE; target = targcell->lf; if (!target) { fizzle(caster); @@ -3406,7 +3466,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } else if (spellid == OT_S_HOLDPORTAL) { object_t *o; - if (!validatespellcell(caster, &targcell,TT_DOOR, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell,TT_DOOR, spellid, power, frompot)) return B_TRUE; o = hasobwithflag(targcell->obpile, F_DOOR); if (!o) { @@ -3427,7 +3487,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ object_t *wep; enum DAMTYPE dt; char obname[BUFLEN]; - if (!validatespellcell(caster, &targcell, TT_PLAYER | TT_ALLY, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_PLAYER | TT_ALLY, spellid, power, frompot)) return B_TRUE; target = targcell->lf; if (!target) { fizzle(caster); @@ -3464,7 +3524,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ object_t *o; int donesomething = B_FALSE; - if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE; // create icicle o = addob(targcell->obpile, "huge icicle"); @@ -3579,7 +3639,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ char numbuf[BUFLEN]; numtotext(power, numbuf); - if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE; // animation anim(caster->cell, targcell, '}', C_CYAN); if (isplayer(caster) || cansee(player, caster)) { @@ -3750,7 +3810,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } else if (spellid == OT_S_MINDSCAN) { int failed = B_FALSE; if (isplayer(caster)) { - if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE; if (targcell && haslos(caster, targcell) && haslf(targcell)) { char targname[BUFLEN]; @@ -3794,7 +3854,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ return B_TRUE; } - if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE; // 4 is the same as ST_TITANIC strength // 10 = gun speed @@ -3802,7 +3862,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } else if (spellid == OT_S_PARALYZE) { int howlong; int saved = B_FALSE; - if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE; target = targcell->lf; if (lfhasflag(target, F_PARALYZED)) { @@ -3837,7 +3897,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } else if (spellid == OT_S_PAIN) { int failed = B_FALSE; // ask for target - if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE; target = targcell->lf; if (lfhasflag(target, F_PAIN)) { @@ -3873,7 +3933,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ fizzle(caster); } } else if (spellid == OT_S_PETRIFY) { - if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE; target = targcell->lf; // some thigns can't be stoned @@ -3903,7 +3963,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ addflag(target->flags, F_BEINGSTONED, 2, NA, NA, NULL); } else if (spellid == OT_S_POISONBOLT) { char lfname[BUFLEN]; - if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE; // animation anim(caster->cell, targcell, '}', C_GREEN); @@ -3930,7 +3990,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } else if (spellid == OT_S_POSSESSION) { char targname[BUFLEN]; - if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE; target = targcell->lf; if (!target) { @@ -4048,7 +4108,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ f = addtempflag(caster->flags, F_MAGICARMOUR, power*4, NA, NA, "psychic barrier", FROMSPELL); f->obfrom = spellid; } else if (spellid == OT_S_PULL) { - if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE; target = targcell->lf; @@ -4080,7 +4140,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } else if (spellid == OT_S_PULLMETAL) { int donesomething = B_FALSE; - if (!validatespellcell(caster, &targcell,TT_OBJECT, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell,TT_OBJECT, spellid, power, frompot)) return B_TRUE; if (targcell->lf) { object_t *o; @@ -4299,7 +4359,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (caster->race->id == R_GHOST) { targcell = caster->cell; } else { - if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE; } target = targcell->lf; @@ -4323,7 +4383,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (seenbyplayer) *seenbyplayer = B_TRUE; } } else if (spellid == OT_S_JOLT) { - if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE; target = haslf(targcell); if (target) { @@ -4343,7 +4403,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } else if (spellid == OT_S_KNOCK) { object_t *o; - if (!validatespellcell(caster, &targcell,TT_DOOR, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell,TT_DOOR, spellid, power, frompot)) return B_TRUE; target = targcell->lf; @@ -4404,7 +4464,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ // at power 8, the light is permenant if (power >= 3) { // TODO: this actually means we can cast it through walls!!! - if (!validatespellcell(caster, &targcell,TT_NONE, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell,TT_NONE, spellid, power, frompot)) return B_TRUE; } else { targcell = caster->cell; } @@ -4467,7 +4527,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ int nretcells; int i; int nhits = power; - if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE; // create a line of fire towards the target cell calcbresnham(caster->cell->map, caster->cell->x, caster->cell->y, targcell->x, targcell->y, retcell, &nretcells); @@ -4667,7 +4727,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } else if (spellid == OT_S_GRAVBOOST) { // ask for target - if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE; if (target) { int howlong = 15; @@ -4710,7 +4770,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ limit(&power, NA, 10); } - if (!validatespellcell(caster, &targcell, TT_MONSTER|TT_OBJECT, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_MONSTER|TT_OBJECT, spellid, power, frompot)) return B_TRUE; target = targcell->lf; @@ -4829,7 +4889,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } else if (spellid == OT_S_PACIFY) { char targetname[BUFLEN]; - if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE; target = targcell->lf; @@ -4883,7 +4943,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } else if (spellid == OT_S_POLYMORPH) { race_t *r = NULL; - if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE; target = targcell->lf; if (!target) { @@ -4939,7 +4999,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ // random race, but not the same! r = target->race; while ((r == target->race) || !canpolymorphto(r->id)) { - r = getrandomrace(NULL, 0); + r = getrandomrace(NULL, NA); } } } @@ -5050,7 +5110,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ object_t *o,*nexto; int ndone = 0; - if (!validatespellcell(caster, &targcell,TT_OBJECT, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell,TT_OBJECT, spellid, power, frompot)) return B_TRUE; if (!targcell) { fizzle(caster); @@ -5105,7 +5165,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } else if (spellid == OT_S_LESSENPOISON) { flag_t *f; int ndone = 0; - if (!validatespellcell(caster, &targcell,TT_ALLY, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell,TT_ALLY, spellid, power, frompot)) return B_TRUE; target = targcell->lf; if (!target) { fizzle(caster); @@ -5207,7 +5267,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ f->obfrom = spellid; } else if (spellid == OT_S_SLEEP) { int howlong; - if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE; target = targcell->lf; if (lfhasflag(target, F_ASLEEP) || !cansleep(target)) { @@ -5238,7 +5298,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ limit(&power, NA, 10); } // ask for a target cell - if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE; if (targcell) { if (!targcell->type->solid) { int radius; @@ -5263,7 +5323,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } else if (spellid == OT_S_SLOW) { int howlong = 15; - if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE; target = targcell->lf; if (skillcheck(target, SC_RESISTMAG, 20 + power, 0)) { @@ -5288,7 +5348,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ int ndone = 0; int powerleft = power; // ask for a target cell - if (!validatespellcell(caster, &targcell, TT_NONE, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_NONE, spellid, power, frompot)) return B_TRUE; if (targcell) { object_t *o; enum OBTYPE badoid[2]; @@ -5329,7 +5389,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } else if (spellid == OT_S_SPARK) { object_t *o,*nexto; int donesomething = B_FALSE; - if (!validatespellcell(caster, &targcell,TT_OBJECT | TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell,TT_OBJECT | TT_MONSTER, spellid, power, frompot)) return B_TRUE; if (haslos(player, targcell)) { msg("A small spark of flame appears."); @@ -5349,7 +5409,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } else if (spellid == OT_S_STENCH) { int howlong; - if (!validatespellcell(caster, &targcell,TT_OBJECT | TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell,TT_OBJECT | TT_MONSTER, spellid, power, frompot)) return B_TRUE; target = targcell->lf; if (!target) { @@ -5815,7 +5875,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } } else if (spellid == OT_S_TWIDDLE) { - if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE; target = targcell->lf; if (!target || (target == caster)) { @@ -5918,7 +5978,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ int seen = B_FALSE; flag_t *f; - if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE; // get vert distance @@ -6031,7 +6091,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ char lfname[BUFLEN]; cell_t *retcell[MAXRETCELLS]; int nretcell,i; - if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE; // animation //anim(caster->cell, targcell, '}', C_BLUE); if (isplayer(caster) || cansee(player, caster)) { @@ -6079,7 +6139,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ flag_t *f; int ndone = 0; - if (!validatespellcell(caster, &targcell,TT_OBJECT, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell,TT_OBJECT, spellid, power, frompot)) return B_TRUE; if (!targcell) { fizzle(caster); @@ -6131,7 +6191,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } else if (spellid == OT_S_WEAKEN) { // ask for target - if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE; target = targcell->lf; if (skillcheck(target, SC_RESISTMAG, 20 + power, 0)) { @@ -6172,7 +6232,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ int i; numtotext(power, numbuf); - if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE; // animation anim(caster->cell, targcell, '^', C_GREY); if (isplayer(caster) || cansee(player, caster)) { @@ -6223,7 +6283,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (seenbyplayer) *seenbyplayer = B_TRUE; // ask for target if (spellid == OT_S_GIFT) { - if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE; + if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE; target = targcell->lf; } else { target = caster; @@ -6502,8 +6562,14 @@ int getspellpower(lifeform_t *lf, enum OBTYPE spellid) { int spelllev; enum SKILLLEVEL spellskill,schoolskill; enum SPELLSCHOOL school; + int db = B_FALSE; int max = 10; flag_t *f; + objecttype_t *ot; + + ot = findot(spellid); + + if (db) dblog("getspellpower for lf %s, spell %s", lf->race->name, ot->name); // first: can we WILL this to occur? if so, we might have a set // spellpower @@ -6511,6 +6577,9 @@ int getspellpower(lifeform_t *lf, enum OBTYPE spellid) { if (f && strlen(f->text)) { texttospellopts(f->text, &power, NULL, NULL, NULL); if (power > 0) { + if (db) { + dblog("-->power = %d (from canwill)", power); + } return power; } } @@ -6518,6 +6587,9 @@ int getspellpower(lifeform_t *lf, enum OBTYPE spellid) { // player can only ever cast spells up to your level. if (isplayer(lf) && !hasjob(lf, J_GOD)) { if (getspelllevel(spellid) > lf->level) { + if (db) { + dblog("-->power = 0 (spell level > lf level)", power); + } return 0; } } @@ -6545,6 +6617,9 @@ int getspellpower(lifeform_t *lf, enum OBTYPE spellid) { break; default: if (spellskill == PR_INEPT) { + if (db) { + dblog("-->power = 0 (inept in SORCERY)"); + } return 0; } break; @@ -6553,10 +6628,12 @@ int getspellpower(lifeform_t *lf, enum OBTYPE spellid) { if (hasjob(lf, J_DRUID)) { power = (lf->level/3) + statmod; + if (db) dblog("-->(druid) basepower from level+iq is %d", power); } else { // every 6 levels you get 1 more power // ie. at level 30 you get +5 power power = (lf->level/6) + statmod; + if (db) dblog("-->basepower from level+iq is %d", power); } switch (school) { @@ -6564,6 +6641,7 @@ int getspellpower(lifeform_t *lf, enum OBTYPE spellid) { case SS_MENTAL: break; default: + if (db) dblog("--> + %d from skill in Sorcery", spellskill); power += spellskill; break; } @@ -6579,6 +6657,7 @@ int getspellpower(lifeform_t *lf, enum OBTYPE spellid) { } if (divamt > 0) { + if (db) dblog("--> divided by %d (based on spelllevel %d)", divamt, spelllev); power /= divamt; } } @@ -6586,12 +6665,16 @@ int getspellpower(lifeform_t *lf, enum OBTYPE spellid) { // specialised school skill - apply this AFTER dividing by spell level schoolskill = getskill(lf, getschoolskill(school)); if (schoolskill != PR_INEPT) { - power += ((float)schoolskill * 1.5); + float addamt; + addamt = (float)schoolskill * 1.5; + if (db) dblog("--> + %0.1f from skill in %s", addamt, getschoolname(school)); + power += addamt; } // enforce maximum max = getspellmaxpower(spellid); if (power > max) power = max; + if (db) dblog("==> final power: %d", power); return power; } @@ -6782,7 +6865,7 @@ int schoolappearsinbooks(enum SPELLSCHOOL ss) { return B_TRUE; } -void spellcloud(cell_t *srcloc, int radius, char ch, enum COLOUR col, enum OBTYPE sid, int power) { +void spellcloud(cell_t *srcloc, int radius, char ch, enum COLOUR col, enum OBTYPE sid, int power, int frompot) { int x,y; if (ch != '\0') { if (haslos(player, srcloc)) { @@ -6798,7 +6881,7 @@ void spellcloud(cell_t *srcloc, int radius, char ch, enum COLOUR col, enum OBTYP haslof(srcloc, c, LOF_WALLSTOP, NULL)) { if (getcelldistorth(srcloc, c) <= radius) { // fall asleep - dospelleffects(NULL, sid, power, c->lf, NULL, c, B_UNCURSED, NULL); + dospelleffects(NULL, sid, power, c->lf, NULL, c, B_UNCURSED, NULL, frompot); } } } @@ -6940,7 +7023,7 @@ lifeform_t *validateabillf(lifeform_t *user, enum OBTYPE aid, lifeform_t **targe return *target; } -cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, enum OBTYPE spellid, int power) { +cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, enum OBTYPE spellid, int power, int frompot) { int maxrange = UNLIMITED; int done = B_FALSE; cell_t *where = NULL; @@ -6972,7 +7055,7 @@ cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, e cell_t *newwhere = NULL; // validate it if (where && needlos && !haslos(caster, where) && (where != caster->cell)) { - if (isplayer(caster)) { + if (isplayer(caster) && !frompot) { msg("You cannot see there!"); more(); } where = NULL; @@ -6981,7 +7064,7 @@ cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, e // line of fire interrupted? if (where && needlof && !haslof(caster->cell, where, needlof, &newwhere)) { if (newwhere) { - if (isplayer(caster)) { + if (isplayer(caster) && !frompot) { // warn! int ch; ch = askchar("Your have no clear line of fire - really target here?","yn","n", B_TRUE); @@ -6999,13 +7082,13 @@ cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, e } if (where && (maxrange != UNLIMITED) && (getcelldist(caster->cell, where) > maxrange)) { // out of range - if (isplayer(caster)) { + if (isplayer(caster) && !frompot) { msg("Too far away - max range is %d.",maxrange); more(); } where = NULL; } - if (where && where->lf && haslos(caster, where) && isplayer(caster) && areallies(caster, where->lf)) { + if (!frompot && where && where->lf && haslos(caster, where) && isplayer(caster) && areallies(caster, where->lf)) { // warn before targetting yourself! if (getiqname(getattr(caster, A_IQ), NULL) >= IQ_AVERAGE) { objecttype_t *sp; diff --git a/spell.h b/spell.h index 2632ba8..2f0b6c0 100644 --- a/spell.h +++ b/spell.h @@ -3,7 +3,7 @@ #include "defs.h" int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifeform_t *target, flag_t *cwflag); -int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_t *target, object_t *targob, cell_t *targcell, int blessed, int *seenbyplayer); +int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_t *target, object_t *targob, cell_t *targcell, int blessed, int *seenbyplayer, int frompot); objecttype_t *findspelln(char *buf); void fizzle(lifeform_t *caster); //int getiqreq(enum OBTYPE oid); @@ -22,12 +22,12 @@ int getspellrange(enum OBTYPE spellid, int power); char *getvarpowerspelldesc(enum OBTYPE spellid, int power, char *buf); void pullobto(object_t *o, lifeform_t *lf); int schoolappearsinbooks(enum SPELLSCHOOL ss); -void spellcloud(cell_t *srcloc, int radius, char ch, enum COLOUR col, enum OBTYPE sid, int power); +void spellcloud(cell_t *srcloc, int radius, char ch, enum COLOUR col, enum OBTYPE sid, int power, int frompot); void stopspell(lifeform_t *caster, enum OBTYPE spellid); void stopallspells(lifeform_t *lf); int summonlfs(lifeform_t *caster, enum RACECLASS wantrc, enum LFSIZE wantsize, int howmany, int lifetime); lifeform_t *validateabillf(lifeform_t *user, enum OBTYPE aid, lifeform_t **target); -cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, enum OBTYPE spellid, int power); +cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, enum OBTYPE spellid, int power, int frompot); //lifeform_t *validatespelllf(lifeform_t *caster, lifeform_t **lf); #endif diff --git a/text.c b/text.c index 2254ec1..dd73cdf 100644 --- a/text.c +++ b/text.c @@ -289,6 +289,36 @@ char *gettimetextfuzzy(char *retbuf, int wantpm) { return retbuf; } +char *getwaterdepthname(enum DEPTH d) { + switch (d) { + case DP_NONE: + return "shallow"; + case DP_TOE: + return "toe-deep"; + case DP_ANKLE: + return "ankle-deep"; + case DP_FEET: + return "foot-deep"; + case DP_CALF: + return "calf-deep"; + case DP_KNEE: + return "knee-deep"; + case DP_THIGH: + return "thigh-deep"; + case DP_WAIST: + return "waist-deep"; + case DP_BELLY: + return "belly-deep"; + case DP_CHEST: + return "chest-deep"; + case DP_SHOULDERS: + return "shoulder-deep"; + default: + return "very deep"; + } + return "?unknowndepth?"; +} + char *getweighttext(float weight, char *buf) { if (weight == 0) { sprintf(buf, "nothing"); diff --git a/text.h b/text.h index ae4f072..a25edfa 100644 --- a/text.h +++ b/text.h @@ -14,6 +14,7 @@ char *getrarityname(enum RARITY rr); char *getsizetext(enum LFSIZE sz); char *gettimetext(char *retbuf); char *gettimetextfuzzy(char *retbuf, int wantpm); +char *getwaterdepthname(enum DEPTH d); char *getweighttext(float weight, char *buf); char *is(lifeform_t *lf); int isvowel(char c); diff --git a/vaults/cavein.vlt b/vaults/cavein.vlt index 0a16560..e796d07 100644 --- a/vaults/cavein.vlt +++ b/vaults/cavein.vlt @@ -8,7 +8,7 @@ random(4,4) @end @flags -autodoors +autodoors:25 autopop scatter(1,1,-2,-2) ob:boulder:25% scatter(1,1,-2,-2) ob:25-75 stones:50% diff --git a/vaults/circle.vlt b/vaults/circle.vlt index b68f117..e41ebbc 100644 --- a/vaults/circle.vlt +++ b/vaults/circle.vlt @@ -12,12 +12,12 @@ @end @legend -#:ob:stone wall +#:cell:rock wall +:ob:wooden door @end @flags -autodoors +autodoors:50 autopop @end diff --git a/vaults/diningroom.vlt b/vaults/diningroom.vlt index 0c0fbd5..e3641b3 100644 --- a/vaults/diningroom.vlt +++ b/vaults/diningroom.vlt @@ -8,11 +8,11 @@ random(4,4) @end @flags -autodoors +autodoors:75 autopop ! tables & chairs scatter(1,1,-2,-2) ob:wooden table:20% -scatter(1,1,-2,-2) ob:wooden chair:20% +scatter(1,1,-2,-2) ob:wooden footstool:20% scatter(1,1,-2,-2) ob:random food:5-10 scatter(1,1,-2,-2) ob:steak knife:1-5 ! mayrotate diff --git a/vaults/floodroom1.vlt b/vaults/floodroom1.vlt index 721b264..3b2b726 100644 --- a/vaults/floodroom1.vlt +++ b/vaults/floodroom1.vlt @@ -1,4 +1,5 @@ -! a room filled with deep water +! a room completely filled with deep water +! the water will explode outwards when you open the door @id:flooded_room @map random(5,5) @@ -8,11 +9,10 @@ random(5,5) @end @flags -autodoors +! 100% chance of doors - don't want the water escaping +autodoors:100 autopop -! sometimes there will be a walkway around the edge -box(1,1,-2,-2) ob:shallow water:50 -fill(2,2,-3,-3) ob:deep water:100 +fill(1,1,-2,-2) ob:very deep water:100 scatter(1,1,-2,-2) mon:piranha:3:100 @end diff --git a/vaults/floodroom2.vlt b/vaults/floodroom2.vlt index 2362bca..97b04d9 100644 --- a/vaults/floodroom2.vlt +++ b/vaults/floodroom2.vlt @@ -8,10 +8,10 @@ random(5,5) @end @flags -autodoors +autodoors:50 autopop -! sometimes there will be a walkway around the edge -fill(2,2,-3,-3) ob:shallow water:100 +fill(2,2,-3,-3) cell:low rock floor:100 +fill(2,2,-3,-3) ob:waist-deep water:100 scatter(2,2,-3,-3) mon:piranha:50%:100 @end diff --git a/vaults/lair_cockatrice.vlt b/vaults/lair_cockatrice.vlt index 086fba7..f5f0cb9 100644 --- a/vaults/lair_cockatrice.vlt +++ b/vaults/lair_cockatrice.vlt @@ -8,7 +8,8 @@ random(5,5) @end @flags -autodoors +! don't want cockatrice escaping +autodoors:100 scatter(1,1,-2,-2) ob:statue:25% scatter(1,1,-2,-2) mon:cockatrice:1 scatter(1,1,-2,-2) ob:1-10 stones:1-5 diff --git a/vaults/monsterzoo.vlt b/vaults/monsterzoo.vlt index 305250b..c27723e 100644 --- a/vaults/monsterzoo.vlt +++ b/vaults/monsterzoo.vlt @@ -8,7 +8,7 @@ random(4,4) @end @flags -autodoors +autodoors:100 ! every cell in here has 1-3 objects and a monster scatter(1,1,-2,-2) mon:random:100% scatter(1,1,-2,-2) ob:random:100% diff --git a/vaults/mudroom.vlt b/vaults/mudroom.vlt index a9806f2..febfa46 100644 --- a/vaults/mudroom.vlt +++ b/vaults/mudroom.vlt @@ -8,7 +8,7 @@ random(4,4) @end @flags -autodoors +autodoors:50 autopop ! add mud to 50% of room cells scatter(1,1,-2,-2) ob:pool of mud:50% diff --git a/vaults/pillar.vlt b/vaults/pillar.vlt index edcece8..cb6f539 100644 --- a/vaults/pillar.vlt +++ b/vaults/pillar.vlt @@ -7,8 +7,8 @@ random(5,5) @end @flags -autodoors +autodoors:50 autopop -scatter(1,1,-2,-2) cell:stone wall:25% +scatter(1,1,-2,-2) cell:rock wall:25% @end diff --git a/vaults/pillarglass.vlt b/vaults/pillarglass.vlt index f0b7f6c..bc6e057 100644 --- a/vaults/pillarglass.vlt +++ b/vaults/pillarglass.vlt @@ -8,7 +8,7 @@ random(5,5) @end @flags -autodoors +autodoors:50 autopop scatter(1,1,-2,-2) cell:glass wall:25% @end diff --git a/vaults/traproom.vlt b/vaults/traproom.vlt index b983007..687e1ea 100644 --- a/vaults/traproom.vlt +++ b/vaults/traproom.vlt @@ -8,7 +8,7 @@ random(3,3) @end @flags -autodoors +autodoors:100 ! half the cells are trapped! scatter(1,1,-2,-2) ob:random trap:50% ! corpses diff --git a/vaults/vault.vlt b/vaults/vault.vlt index eb9fef1..aa8c943 100644 --- a/vaults/vault.vlt +++ b/vaults/vault.vlt @@ -8,7 +8,7 @@ @end @legend -#:ob:metal wall +#:cell:metal wall $:ob:25-200 gold ! 30% chance of a door on each side +:ob:secret locked iron door:30