From b18dea83a38b3958e39fe8ff0e5af684ce7514e2 Mon Sep 17 00:00:00 2001 From: Rob Pearce Date: Sat, 23 Apr 2011 04:27:42 +0000 Subject: [PATCH] * [+] bug: secret doors revealed when we walk away from them. - [+] make lamps last heaps longer * [+] web spell * [+] spider monstrer * [+] funnelweb: * [+] redback: - [+] if you are wracked with pain, don't clear msg - [+] check rarity for spiders * [+] attack/defense mod if there is stickiness in your square - [+] replace "sticky" with "restrictive" * [+] make some mosnters start hidden - [+] adjust spot checks basd on distance - [+] ensure that attacking stops you hiding - [+] casting spells stops you from being hidden - [+] hidden mosnters shouldn't move unless their victim is ADJACENT. - [+] hidden mosnters shouldn't cast spells, throw missiles, etc unless their victim is ADJACENT. - [-] XP CALC - [+] funnelweb and redback are the same. - [+] check this is right...... i want funnel web to be worse. - [+] make hitconfer check in calcxpval take lifetime into account - [+] ALSO assign an xp rating to each hitconferred flag. - [+] hardcode this. * [+] entangle spell - [+] reveal secret doors if you see them get damaged. * [+] make askcoords list restrivitce objects - [+] ACTUALLY make vines not damaged by struggling * [+] object descriptions, a/an needs to change if showing condition: "a battered entangling vine" - [+] wizard levelled up and was prompted for "WISH, GIFT"! shouldn't happen! - [+] The human diety reads a blessed scroll of create monster! -- but nothing happens?? * [+] throw code - [+] wizard: ask for school specialty at start, from: fire, ice, xxx ? You get this + WILD. - [+] describe varpower spells - [+] fix mp cost for varpower spells - [+] we're not stopping running at staircases anymore for some reason. - [+] CHARGE ability (like swoop but don't return to original positino) - [+] need to honor f_canlearn when displaying new skills to learn! - [+] ai: if we are going to player's last known loc (via targetcell), abandon if we can SEE the player! - [+] make shatter() into a function - [+] oil potion makes oil puddle whan smashed - [+] make flammable objects be able to convert to others - [+] replace 'magic item usage' with 'channeling' - [+] a cloud of darkness descends. this is a *cursed* wand of light. - [+] spiders shouldn't be able to be stuck in a web! * [+] spells should be able to have MULTIPLE schools. - [+] don't bleed into walls - [+] in @M, use colours to show which spells are too hard so far (ie cost > maxmp) * [+] in @M, use schools that you know * [+] after loading game, barbarian is getting an extra attack? You miss the eyebat. You punch the eyebat. - [+] show objects on top of stairs - [+] stuck mosnters must pass a saving throw to follow you up/down stairs - [+] genericise: trytomove(lf) * [+] add more snakes - [+] undead can't eat or drink? or MOST undead can't. * [+] why can MONSTERS shoot webs through things? (but I can't) - [+] barkskin - doesn't reduce max mp enough? - [+] The skeleton touches a fuming aqua potion [tried] then recoils in pain! The skeleton drops a blessed fuming aqua potion [tried]. The skeleton drinks a fuming aqua potion! - [+] why can't i use abilites anymore? - [+] infinite loop bug due to ai only having one ignorecell. - [+] make sleet storms rust all armour - [+] make a kind of walkdam that hits armour - [+] add this as well as walkdam for: acid, fire, water - [+] Takeoff isn't prompting properly. only showing weapons! * [+] waterproof obs (ie cloak) * [+] walkdambp doesn't hurt body if you have a cloak NATURE SPELLS: - [+] mending, heals 1d6 damage - [+] spark - [+] purify food - [+] sticks to snakes - [+] calm animals (power_d4 hd) * [+] charm animal (works on one animal up to power hit dice, temporary) - [+] airblast - [+] barkskin (power +2 AR, firevuln, ongoing) - [+] soften earth (makes ground into mud) - [+] warp wood (damages wooden objects) - [+] repel insects - [+] reduce poison - [+] web - [+] windshield - [+] call lightning, air - [+] resist elements, ongoing - [+] passwall - [+] poisonbolt - [+] quench (puts out a fire) - [+] sleet storm (lowers movement, vision) - [+] healing - [+] cure poison * [+] calming scent - [+] dig - [+] entangle - [+] levitate - [+] flamepillar - [+] hailstorm. like sleetstorm but hurts more. power d 6. - [+] burning wave - [+] gaseous form * [+] knowledge skills: * [+] force makespellchoicelist() to show spells in level order. * [+] druid - [+] check OBJECT rarity list (dumplev) - [+] fix bug where heaps of books suddently appear from dlev 3 onwards - [+] gain skills on level up for some jobs - [+] f_levspellschool, v0=lev, v1 = school or ANY - select one from that school --- ai.c | 370 +++-- ai.h | 3 +- attack.c | 81 +- defs.h | 248 +++- doc/add_skill.txt | 2 + flag.c | 10 + io.c | 568 +++++-- io.h | 1 + lf.c | 1317 ++++++++++++----- lf.h | 16 +- log.txt | 3615 +++------------------------------------------ map.c | 161 +- map.h | 3 +- move.c | 255 +++- move.h | 5 +- nexus.c | 16 +- objects.c | 1440 ++++++++++-------- objects.h | 2 + save.c | 6 +- spell.c | 1029 ++++++++++++- spell.h | 2 + text.c | 37 + text.h | 2 + 23 files changed, 4221 insertions(+), 4968 deletions(-) diff --git a/ai.c b/ai.c index 6a74669..b3e8e97 100644 --- a/ai.c +++ b/ai.c @@ -19,6 +19,12 @@ extern enum ERROR reason; int wantdb = B_TRUE; +void addignorecell(lifeform_t *lf, cell_t *c) { + if (c) { + addflag(lf->flags, F_IGNORECELL, c->x, c->y, NA, NULL); + } +} + void aiattack(lifeform_t *lf, lifeform_t *victim, int timelimit) { int db = B_FALSE; flag_t *f; @@ -251,8 +257,10 @@ object_t *aigetwand(lifeform_t *lf, enum FLAG purpose) { return NULL; } -void aigoto(lifeform_t *lf, cell_t *c, int timelimit) { +flag_t *aigoto(lifeform_t *lf, cell_t *c, enum MOVEREASON why, void *data, int timelimit) { int db = B_FALSE; + char whybuf[BUFLEN]; + flag_t *f = NULL; if (lfhasflag(lf, F_DEBUG)) { db = B_TRUE; @@ -267,12 +275,22 @@ void aigoto(lifeform_t *lf, cell_t *c, int timelimit) { killflagsofid(lf->flags, F_TARGET); killflagsofid(lf->flags, F_TARGETCELL); + if (why == MR_LF) { + sprintf(whybuf, "%d", ((lifeform_t *)data)->id); + } else if (why == MR_OB) { + sprintf(whybuf, "%ld", ((object_t *)data)->id); + } else { + strcpy(whybuf, ""); + } + + if ((timelimit == PERMENANT) || (timelimit == UNLIMITED)) { - addflag(lf->flags, F_TARGETCELL, c->x, c->y, NA, NULL); + f = addflag(lf->flags, F_TARGETCELL, c->x, c->y, why, whybuf); } else { - addtempflag(lf->flags, F_TARGETCELL, c->x, c->y, NA, NULL,timelimit); + f = addtempflag(lf->flags, F_TARGETCELL, c->x, c->y, why, whybuf,timelimit); } + return f; } void aimovetotargetcell(lifeform_t *lf, flag_t *f) { @@ -296,7 +314,7 @@ void aimovetotargetcell(lifeform_t *lf, flag_t *f) { if (db) dblog(".oO { couldn't walk towards f_targetcell. abandoning it. }"); killflag(f); // remember NOT to target this one. - lf->ignorecell = c; + addignorecell(lf, c); } else { if (db) dblog(".oO { successfully walked towards f_targetcell. arrived at %d,%d }",lf->cell->x, lf->cell->y); // moved towards it. @@ -314,7 +332,7 @@ void aimovetotargetcell(lifeform_t *lf, flag_t *f) { // destination doesn't exist! killflag(f); // remember NOT to target this one. - lf->ignorecell = c; + addignorecell(lf, c); } } @@ -508,10 +526,12 @@ void aiturn(lifeform_t *lf) { // look for any object which we _covet_. // ie. if we covet something, we will pick it up // instead of attacking our target. - if (db) dblog(".oO { looking for covetted objects... }"); - if (lookforobs(lf, B_COVETS)) { - if (db) dblog(".oO { found covetted object. returning. }"); - return; + if (!lfhasflag(lf, F_HIDING)) { + if (db) dblog(".oO { looking for covetted objects... }"); + if (lookforobs(lf, B_COVETS)) { + if (db) dblog(".oO { found covetted object. returning. }"); + return; + } } /////////////////////////////////////////////// @@ -552,154 +572,156 @@ void aiturn(lifeform_t *lf) { if (goingtomove && (getcelldist(lf->cell, target->cell) == 1)) { } - // can we attack with spells (ie. ones which target the victim)? - // if target is adjacent, we will normally just attack rather than try a spell. - spell = aigetattackspell(lf, target); - if ( (spell != OT_NONE) && // found a valid spell/ability to use - ((getcelldist(lf->cell, target->cell) != 1) || (rnd(1,3) == 1)) - ) { - int spellfailed = B_FALSE; - lifeform_t *spelllf = NULL; - cell_t *spellcell = NULL; - object_t *spellob = NULL; - objecttype_t *st; - st = findot(spell); - if (db) { - dblog(".oO { will cast attack spell: %s }", st->name); - } - - // special cases: eg. spells like telekenesis - if (spell == OT_S_TELEKINESIS) { - float maxweight; - object_t *poss[MAXPILEOBS]; - int nposs; - int i; - // find nearest object which can be picked up - - // this is copied out of the telekenesis spell code! - maxweight = getlfweight(lf, B_NOOBS) + - (getlfweight(lf, B_NOOBS) * (getstatmod(lf, A_IQ) / 100)); - - nposs = 0; - for (i = 0; i < lf->nlos; i++) { - object_t *o; - for (o = lf->los[i]->obpile->first ; o ; o = o->next) { - if (!hasflag(o->flags, F_NOPICKUP) && - getobweight(o) <= maxweight) { - poss[nposs] = o; - nposs++; - if (nposs >= MAXPILEOBS) break; - } - } - if (nposs >= MAXPILEOBS) break; - } - if (nposs > 0) { - spellob = poss[rnd(0,nposs-1)]; - } else { - spellfailed = B_TRUE; - } - - // cast spell at the player - spelllf = target; - spellcell = target->cell; - } else { - // pick targets based on spell flags - aigetspelltarget(lf, st, target, &spelllf, &spellcell, &spellob, F_AICASTTOATTACK); - } - - if (spellfailed) { - if (db) dblog(".oO { cast spell/ability failed (1)! }"); - } else { - if (getschool(spell) == SS_ABILITY) { - spellfailed = useability(lf, spell, spelllf, spellcell); - } else { - spellfailed = castspell(lf, spell, spelllf, spellob, spellcell); - } - } - if (spellfailed) { - if (db) dblog(".oO { cast spell/ability tried but failed (2)! reason = %d }", reason); - } else { - // spell succesful - return; - } - } - - // if not adjacent, check for guns, wands, throwing - if (goingtomove && // if we are still planning on moving - (getcelldist(lf->cell, target->cell) > 1) && // and we're not adjacent to target - haslof(lf->cell, target->cell, LOF_NEED, NULL) && // and we have line of fire to them - (iqb > IQ_ANIMAL) ) { // and we are smarter than an animal - // can we attack by firing a weapon? - gun = getfirearm(lf); - if (goingtomove && gun && getammo(lf)) { + if (!lfhasflag(lf, F_HIDING)) { + // can we attack with spells (ie. ones which target the victim)? + // if target is adjacent, we will normally just attack rather than try a spell. + spell = aigetattackspell(lf, target); + if ( (spell != OT_NONE) && // found a valid spell/ability to use + ((getcelldist(lf->cell, target->cell) != 1) || (rnd(1,3) == 1)) + ) { + int spellfailed = B_FALSE; + lifeform_t *spelllf = NULL; + cell_t *spellcell = NULL; + object_t *spellob = NULL; + objecttype_t *st; + st = findot(spell); if (db) { - char gunname[BUFLEN]; - getobname(gun, gunname, gun->amt); - dblog(".oO { will fire my gun (%s) at target. }",gunname); + dblog(".oO { will cast attack spell: %s }", st->name); } - setguntarget(lf, target); - if (!shoot(lf)) { - // succesful - return; - } else { - if (db) dblog(".oO { shoot gun failed! reason = %d }", reason); - } - } else { - if (db) dblog(".oO { not firing out gun }"); - } - // can we attack by throwing something? - if (goingtomove && hasbp(lf, BP_HANDS)) { - o = getbestthrowmissile(lf); - if (o) { - if (db) dblog(".oO { will throw %s at my target instead of moving }", o->type->name); - // try to throw it! - if (!throwat(lf, o, target->cell)) { - // succesful - goingtomove = B_FALSE; - } else { - if (db) dblog(".oO { throw failed! }"); - } - } - } + // special cases: eg. spells like telekenesis + if (spell == OT_S_TELEKINESIS) { + float maxweight; + object_t *poss[MAXPILEOBS]; + int nposs; + int i; + // find nearest object which can be picked up - // do we have a wand we can zap? - if (lfhasflag(lf, F_HUMANOID) || hasbp(lf, BP_HANDS)) { - if (lfhasflag(lf, F_FLEEFROM)) { - o = aigetwand(lf, F_AICASTTOFLEE); - } else { - o = aigetwand(lf, F_AICASTTOATTACK); - } - if (o) { - objecttype_t *st; - cell_t *zapcell = NULL; + // this is copied out of the telekenesis spell code! + maxweight = getlfweight(lf, B_NOOBS) + + (getlfweight(lf, B_NOOBS) * (getstatmod(lf, A_IQ) / 100)); - st = getlinkspell(o); - if (st) { - enum FLAG purpose; - if (lfhasflag(lf, F_FLEEFROM)) { - purpose = F_AICASTTOFLEE; - } else { - purpose = F_AICASTTOATTACK; + nposs = 0; + for (i = 0; i < lf->nlos; i++) { + object_t *o; + for (o = lf->los[i]->obpile->first ; o ; o = o->next) { + if (!hasflag(o->flags, F_NOPICKUP) && + getobweight(o) <= maxweight) { + poss[nposs] = o; + nposs++; + if (nposs >= MAXPILEOBS) break; + } } - aigetspelltarget(lf, st, target, NULL, &zapcell, NULL, purpose); + if (nposs >= MAXPILEOBS) break; + } + if (nposs > 0) { + spellob = poss[rnd(0,nposs-1)]; } else { - // no linkspell - just zap it. - zapcell = NULL; + spellfailed = B_TRUE; } - // zap it - if (db) dblog(".oO { will zap %s instead of moving }", o->type->name); + // cast spell at the player + spelllf = target; + spellcell = target->cell; + } else { + // pick targets based on spell flags + aigetspelltarget(lf, st, target, &spelllf, &spellcell, &spellob, F_AICASTTOATTACK); + } - if (!operate(lf, o, zapcell)) { - // succesful - goingtomove = B_FALSE; + if (spellfailed) { + if (db) dblog(".oO { cast spell/ability failed (1)! }"); + } else { + if (getschool(spell) == SS_ABILITY) { + spellfailed = useability(lf, spell, spelllf, spellcell); } else { - if (db) dblog(".oO { zap failed! }"); + spellfailed = castspell(lf, spell, spelllf, spellob, spellcell); + } + } + if (spellfailed) { + if (db) dblog(".oO { cast spell/ability tried but failed (2)! reason = %d }", reason); + } else { + // spell succesful + return; + } + } + + // if not adjacent, check for guns, wands, throwing + if (goingtomove && // if we are still planning on moving + (getcelldist(lf->cell, target->cell) > 1) && // and we're not adjacent to target + haslof(lf->cell, target->cell, LOF_NEED, NULL) && // and we have line of fire to them + (iqb > IQ_ANIMAL) ) { // and we are smarter than an animal + // can we attack by firing a weapon? + gun = getfirearm(lf); + if (goingtomove && gun && getammo(lf)) { + if (db) { + char gunname[BUFLEN]; + getobname(gun, gunname, gun->amt); + dblog(".oO { will fire my gun (%s) at target. }",gunname); + } + setguntarget(lf, target); + if (!shoot(lf)) { + // succesful + return; + } else { + if (db) dblog(".oO { shoot gun failed! reason = %d }", reason); + } + } else { + if (db) dblog(".oO { not firing out gun }"); + } + + // can we attack by throwing something? + if (goingtomove && hasbp(lf, BP_HANDS)) { + o = getbestthrowmissile(lf); + if (o) { + if (db) dblog(".oO { will throw %s at my target instead of moving }", o->type->name); + // try to throw it! + if (!throwat(lf, o, target->cell)) { + // succesful + goingtomove = B_FALSE; + } else { + if (db) dblog(".oO { throw failed! }"); + } + } + } + + // do we have a wand we can zap? + if (lfhasflag(lf, F_HUMANOID) || hasbp(lf, BP_HANDS)) { + if (lfhasflag(lf, F_FLEEFROM)) { + o = aigetwand(lf, F_AICASTTOFLEE); + } else { + o = aigetwand(lf, F_AICASTTOATTACK); + } + if (o) { + objecttype_t *st; + cell_t *zapcell = NULL; + + st = getlinkspell(o); + if (st) { + enum FLAG purpose; + if (lfhasflag(lf, F_FLEEFROM)) { + purpose = F_AICASTTOFLEE; + } else { + purpose = F_AICASTTOATTACK; + } + aigetspelltarget(lf, st, target, NULL, &zapcell, NULL, purpose); + } else { + // no linkspell - just zap it. + zapcell = NULL; + } + + // zap it + if (db) dblog(".oO { will zap %s instead of moving }", o->type->name); + + if (!operate(lf, o, zapcell)) { + // succesful + goingtomove = B_FALSE; + } else { + if (db) dblog(".oO { zap failed! }"); + } } } } - } + } // end if !hiding // do we have a valid melee attack? if (!icanattack) { @@ -707,6 +729,12 @@ void aiturn(lifeform_t *lf) { goingtomove = B_FALSE; } + // if we are hiding, only attack when adjacent to maximise damage + if (lfhasflag(lf, F_HIDING) && + (getcelldist(lf->cell, target->cell) != 1)) { + goingtomove = B_FALSE; + } + if (goingtomove) { if (!movetowards(lf, target->cell, DT_ORTH)) { // success @@ -723,7 +751,7 @@ void aiturn(lifeform_t *lf) { // move towards their last known location instead targcell = getcellat(lf->cell->map, lastx, lasty); if (targcell) { - aigoto(lf, targcell, PERMENANT); + aigoto(lf, targcell, MR_LF, target, PERMENANT); } else { if (db) dblog(".oO { go to target's last known loc failed! }"); } @@ -747,7 +775,38 @@ void aiturn(lifeform_t *lf) { // do we have a target cell? f = hasflag(lf->flags, F_TARGETCELL); if (f) { - aimovetotargetcell(lf, f); + int valid = B_TRUE; + cell_t *c; + // is it still valid? + c = getcellat(lf->cell->map, f->val[0], f->val[1]); + if (!c) { + valid = B_FALSE; + } else if (f->val[2] == MR_LF) { + lifeform_t *who; + who = findlf(lf->cell->map, atoi(f->text)); + // lf doesn't exist? + if (!who) { + valid = B_FALSE; + } else if (cansee(lf, who) && (lf->cell != c)) { + // can see them and they're not where we are going? + valid = B_FALSE; + } + } else if (f->val[2] == MR_OB) { + object_t *what; + what = findobidinmap(lf->cell->map, atol(f->text)); + if (!what) { + valid = B_FALSE; + } else if (haslos(lf, c) && (what->pile->where != c)) { + // if you can see the cell and object isn't there anymore + valid = B_FALSE; + } + } + + if (valid) { + aimovetotargetcell(lf, f); + } else { + killflag(f); + } return; } @@ -870,8 +929,11 @@ void aiturn(lifeform_t *lf) { } else { // try to move towards master's last known loc if (mf->val[1] != NA) { + cell_t *newcell; + newcell = getcellat(lf->cell->map, mf->val[1], mf->val[2]); + if (db) dblog(".oO { cannot see my master - adding F_TARGETCELL for last known loc }"); - f = addflag(lf->flags, F_TARGETCELL, mf->val[1], mf->val[2], NA, NULL); + f = aigoto(lf, newcell, MR_LF, master, PERMENANT); aimovetotargetcell(lf, f); } else { if (db) dblog(".oO { cannot see my master and dont have a last known location. randommove. }"); @@ -1105,6 +1167,18 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG if ((ot->id == OT_A_SPRINT) && lfhasflag(lf, F_SPRINTING)) { specificcheckok = B_FALSE; } + if ((ot->id == OT_S_WARPWOOD)) { + specificcheckok = B_FALSE; + if (victim) { + object_t *oo; + for (oo = victim->pack->first ; oo ; oo = oo->next) { + if ((oo->type->material->id == MT_WOOD) && isequipped(oo)) { + specificcheckok = B_TRUE; + break; + } + } + } + } if ((ot->id == OT_S_WEAKEN)) { flag_t *lff; for (lff = lf->flags->first; lff ; lff = lff->next) { @@ -1254,7 +1328,7 @@ int lookforobs(lifeform_t *lf, int covetsonly) { int gothere = B_FALSE; c = lf->los[i]; - if (!c->lf && (c != lf->ignorecell)) { + if (!c->lf && !lfhasflagval(lf, F_IGNORECELL, c->x, c->y, NA, NULL)) { o = hasobmulti(c->obpile, oid, noids); if (o && !isdangerousob(o, lf, B_TRUE) && (canpickup(lf, o, 1) || caneat(lf,o)) ) { if (db) dblog(".oO { remote cell has ob i want (%s). setting f_targetcell. }",o->type->name); @@ -1306,7 +1380,7 @@ int lookforobs(lifeform_t *lf, int covetsonly) { if (gothere) { // start walking towards target cell - aigoto(lf, c, AI_FOLLOWTIME); + aigoto(lf, c, MR_OB, o, AI_FOLLOWTIME); return B_TRUE; } } diff --git a/ai.h b/ai.h index 5f5df35..85b213e 100644 --- a/ai.h +++ b/ai.h @@ -1,11 +1,12 @@ #include "defs.h" +void addignorecell(lifeform_t *lf, cell_t *c); void aiattack(lifeform_t *lf, lifeform_t *victim, int timelimit); enum OBTYPE aigetattackspell(lifeform_t *lf, lifeform_t *victim); enum OBTYPE aigetfleespell(lifeform_t *lf); void aigetspelltarget(lifeform_t *lf, objecttype_t *spelltype, lifeform_t *victim, lifeform_t **spelllf, cell_t **spellcell, object_t **spellob, enum FLAG purpose); object_t * aigetwand(lifeform_t *lf, enum FLAG purpose); -void aigoto(lifeform_t *lf, cell_t *c, int timelimit); +flag_t *aigoto(lifeform_t *lf, cell_t *c, enum MOVEREASON why, void *data, int timelimit); void aimovetotargetcell(lifeform_t *lf, flag_t *f); int aipickup(lifeform_t *lf, object_t *o); int aiobok(lifeform_t *lf, object_t *o, lifeform_t *target); diff --git a/attack.c b/attack.c index 03c551e..bf6b4ae 100644 --- a/attack.c +++ b/attack.c @@ -183,6 +183,12 @@ int attackcell(lifeform_t *lf, cell_t *c) { } } + // stop sprinting + f = lfhasflag(lf, F_SPRINTING); + if (f && f->val[0]) { + killflag(f); + } + // take time attacktime = getattackspeed(lf); taketime(lf, attacktime); @@ -266,6 +272,9 @@ int attackcell(lifeform_t *lf, cell_t *c) { if (op) { killobpile(op); } + + // now stop hiding + killflagsofid(lf->flags, F_HIDING); return B_FALSE; } @@ -323,6 +332,18 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) getobname(wep, wepname, 1); if (aidb) dblog(".oO { my weapon is %s }", wepname); + + if (lf->race->raceclass->id == RC_INSECT) { + if (hasactivespell(victim, OT_S_REPELINSECTS)) { + if (isplayer(lf)) { + msg("Something prevents you from attacking %s!", victimname); + } else if (cansee(player, lf)) { + msg("Something prevents %s from attacking %s!", attackername, victimname); + } + taketime(lf, getattackspeed(lf)); + return B_FALSE; + } + } // did you hit? ndam = 0; @@ -406,6 +427,12 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) dam[0] += pctof(pctextra, dam[0]); } } + // bonus for knowledge about the other lf's race? applied LAST. + if (getlorelevel(lf, victim->race->raceclass->id) >= PR_MASTER) { + dam[0] = (int) ( (float)dam[0] * 1.5 ); + } else if (getlorelevel(lf, victim->race->raceclass->id) >= PR_SKILLED) { + dam[0] = (int) ( (float)dam[0] * 1.25 ); + } } if (aidb) dblog(".oO { dealing %d %s damage }", dam[0], getdamname(damtype[0])); @@ -690,7 +717,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) if (adj) { flag_t *f; f = addflag(victim->flags, F_NOTIME, B_TRUE, NA, NA, NULL); - moveto(victim, adj, B_FALSE); + moveto(victim, adj, B_FALSE, B_FALSE); msg("%s dodge%s!",victimname,isplayer(victim) ? "" : "s"); killflag(f); } @@ -1629,7 +1656,9 @@ void wepeffects(flagpile_t *fp, cell_t *where, flag_t *damflag, int dam) { // only works if we did damage if (dam) { enum FLAG fid; - int min,max,howlong; + int howlong; + flag_t *valflag = NULL; + fid = f->val[0]; // the f_poisoned flag stacks, others don't. if (!lfhasflag(victim, fid) || (fid == F_POISONED)) { @@ -1648,31 +1677,15 @@ void wepeffects(flagpile_t *fp, cell_t *where, flag_t *damflag, int dam) { } if (!passedcheck) { - if (f->text) { - char loctext[BUFLEN]; - char *word, *dummy; - strcpy(loctext,f->text); - word = strtok_r(loctext, "-", &dummy); - if (word) { - min = atoi(word); - word = strtok_r(NULL, "-", &dummy); - if (word) { - max = atoi(word); - howlong = rnd(min,max); - } else { - howlong = PERMENANT; - } - } else { - howlong = PERMENANT; - } - } else { - howlong = PERMENANT; - } + + howlong = gethitconferlifetime(f->text, NULL, NULL); + + // get conferred flag values + valflag = hasflag(f->pile, F_HITCONFERVALS); if (fid == F_POISONED) { // need to fill in the name of what poisoned us char frombuf[BUFLEN]; - flag_t *typeflag; enum POISONTYPE ptype; int ppower; if (wep) { @@ -1692,13 +1705,14 @@ void wepeffects(flagpile_t *fp, cell_t *where, flag_t *damflag, int dam) { } else { strcpy(frombuf, "something unknown"); } - typeflag = hasflag(f->pile, F_HITPOISONTYPE); - if (typeflag) { - ptype = typeflag->val[0]; - if (typeflag->val[1] == NA) { + + + if (valflag) { + ptype = valflag->val[0]; + if (valflag->val[1] == NA) { ppower = 1; } else { - ppower = typeflag->val[1]; + ppower = valflag->val[1]; } } else { // should never happen. @@ -1708,7 +1722,16 @@ void wepeffects(flagpile_t *fp, cell_t *where, flag_t *damflag, int dam) { poison(victim, howlong, ptype, ppower, frombuf); } else { - addtempflag(victim->flags, fid, NA, NA, NA, NULL, howlong); + flag_t *conferredflag; + conferredflag = addtempflag(victim->flags, fid, NA, NA, NA, NULL, howlong); + // flag values + if (valflag) { + conferredflag->val[0] = valflag->val[0]; + conferredflag->val[1] = valflag->val[1]; + conferredflag->val[2] = valflag->val[2]; + free(conferredflag->text); + conferredflag->text = strdup(valflag->text); + } } } // end if passedcheck } // end (if victim doesn't already have the flag) diff --git a/defs.h b/defs.h index 606ab72..a377430 100644 --- a/defs.h +++ b/defs.h @@ -34,6 +34,64 @@ enum COLOUR { C_BOLDGREEN = 14, }; +enum SKILL { + SK_NONE = 0, + SK_ARMOUR = 1, + SK_ATHLETICS, + SK_BACKSTAB, + SK_FIRSTAID, + SK_LISTEN, + SK_LOCKPICKING, + SK_CHANNELING, + SK_SHIELDS, + SK_SPELLCASTING, + SK_SPOTHIDDEN, + SK_STEALTH, + SK_TECHUSAGE, + // knowledge + SK_LORE_ARCANA, + SK_LORE_DEMONS, + SK_LORE_HUMANOID, + SK_LORE_NATURE, + SK_LORE_UNDEAD, + // weaponry + SK_AXES, + SK_CLUBS, + SK_LONGBLADES, + SK_POLEARMS, + SK_SHORTBLADES, + SK_STAVES, + SK_UNARMED, + // spell schools + SK_SS_ALLOMANCY, + SK_SS_AIR, + SK_SS_DEATH, + SK_SS_DIVINATION, + SK_SS_FIRE, + SK_SS_ICE, + SK_SS_GRAVITY, + SK_SS_LIFE, + SK_SS_MODIFICATION, + SK_SS_MENTAL, + SK_SS_NATURE, + SK_SS_SUMMONING, + SK_SS_TRANSLOCATION, + SK_SS_WILD, +}; +#define MAXSKILLS 39 + +// proficiency levels +enum SKILLLEVEL { + PR_INEPT = 0, + PR_NOVICE = 1, + PR_BEGINNER = 2, + PR_ADEPT = 3, + PR_SKILLED = 4, + PR_EXPERT = 5, + PR_MASTER = 6, +}; + + // save/load #define MAPDIR "data/maps" #define SAVEDIR "data/save" @@ -161,6 +219,8 @@ enum LFCONDITION { #define MAXPILEOBS 52 +#define MAXSPELLLEV 9 + #define MAXRETCELLS 80 #define MAXCHOICES 150 @@ -217,12 +277,14 @@ enum LFCONDITION { #define AO_WEARABLE 16 #define AO_OPERABLE 32 #define AO_POURABLE 64 -#define AO_EQUIPPEDARMOUR 128 +#define AO_EQUIPPEDNONWEAPON 128 #define AO_WEILDABLE 256 #define AO_SPECIFIED 512 #define AO_READABLE 1024 #define AO_ARMOUR 2048 #define AO_NOTKNOWN 4096 +#define AO_DAMAGED 8192 +#define AO_DRINKABLE 16384 // askcoords target types #define TT_NONE 0 @@ -230,6 +292,7 @@ enum LFCONDITION { #define TT_OBJECT 2 #define TT_DOOR 4 #define TT_PLAYER 8 +#define TT_ALLY 16 // target requirements #define TR_NONE 0 @@ -326,13 +389,13 @@ enum SPELLSCHOOL { SS_AIR, SS_DEATH, SS_DIVINATION, - SS_EARTH, SS_FIRE, SS_ICE, SS_GRAVITY, SS_LIFE, SS_MODIFICATION, SS_MENTAL, + SS_NATURE, SS_SUMMONING, SS_TRANSLOCATION, SS_WILD, @@ -460,7 +523,8 @@ enum HABITAT { H_ALL = 999 }; -#define RARITYVARIANCE (25) +#define RARITYVARIANCELF (5) +#define RARITYVARIANCEOB (10) /* enum RARITY { @@ -474,6 +538,16 @@ enum RARITY { }; */ +enum RACECLASS { + RC_ANIMAL, + RC_DEMON, + RC_HUMANOID, + RC_INSECT, + RC_SLIME, + RC_MAGIC, + RC_OTHER, + RC_UNDEAD, +}; enum RACE { R_NONE, R_RANDOM, @@ -524,7 +598,12 @@ enum RACE { R_NEWT, R_RAT, R_SNAKE, + R_SNAKECARPET, + R_SPIDER, + R_SPIDERFUNNELWEB, + R_SPIDERREDBACK, R_WOLF, + R_WOLFYOUNG, // insects R_BUTTERFLY, R_CENTIPEDE, @@ -549,6 +628,7 @@ enum JOB { J_ALLOMANCER, J_BARBARIAN, J_COMMANDO, + J_DRUID, J_PIRATE, J_PLUMBER, J_PRINCE, @@ -589,6 +669,8 @@ enum MATERIAL { MT_SLIME = 21, MT_WAX = 22, MT_ACID = 23, + MT_SILK = 24, + MT_OIL = 25, }; // Object Types @@ -681,6 +763,7 @@ enum OBTYPE { OT_SCR_KNOCK, OT_SCR_LIGHT, OT_SCR_MAPPING, + OT_SCR_MENDING, OT_SCR_MINDSCAN, OT_SCR_PERMENANCE, OT_SCR_ENCHANT, @@ -697,12 +780,17 @@ enum OBTYPE { OT_MAN_LISTEN, OT_MAN_LOCKPICKING, OT_MAN_MAGITEMUSAGE, - OT_MAN_RESEARCH, OT_MAN_SHIELDS, OT_MAN_SPELLCASTING, OT_MAN_SPOTHIDDEN, OT_MAN_STEALTH, OT_MAN_TECHUSAGE, + // manuals of knowledge + OT_MAN_LORE_ARCANA, + OT_MAN_LORE_DEMONS, + OT_MAN_LORE_HUMANOID, + OT_MAN_LORE_NATURE, + OT_MAN_LORE_UNDEAD, // manuals of weaponry OT_MAN_AXES, OT_MAN_CLUBS, @@ -716,7 +804,7 @@ enum OBTYPE { OT_MAN_SS_AIR, OT_MAN_SS_DEATH, OT_MAN_SS_DIVINATION, - OT_MAN_SS_EARTH, + OT_MAN_SS_NATURE, OT_MAN_SS_FIRE, OT_MAN_SS_ICE, OT_MAN_SS_GRAVITY, @@ -747,6 +835,7 @@ enum OBTYPE { OT_SB_MAPPING, // -- elemental - air OT_SB_AIRBLAST, + OT_SB_CALLLIGHTNING, OT_SB_CLOUDKILL, // -- elemental - fire OT_SB_SPARK, @@ -786,9 +875,11 @@ enum OBTYPE { OT_SB_INVISIBILITY, OT_SB_LIGHT, OT_SB_DARKNESS, + OT_SB_MENDING, OT_SB_PASSWALL, OT_SB_PETRIFY, OT_SB_POLYMORPH, + OT_SB_STICKTOSNAKE, // -- summoning OT_SB_CREATEMONSTER, // -- translocation @@ -840,8 +931,6 @@ enum OBTYPE { OT_S_COLDBURST, OT_S_CONECOLD, OT_S_FREEZEOB, - // -- elemental - earth - OT_S_DIG, // -- gravity OT_S_GRAVLOWER, OT_S_GRAVBOOST, @@ -861,17 +950,39 @@ enum OBTYPE { OT_S_PSYARMOUR, OT_S_CHARM, // -- modification + OT_S_DARKNESS, OT_S_ENCHANT, OT_S_GASEOUSFORM, OT_S_INSCRIBE, OT_S_INVISIBILITY, OT_S_KNOCK, OT_S_LIGHT, - OT_S_DARKNESS, + OT_S_MENDING, OT_S_PASSWALL, OT_S_PETRIFY, OT_S_POLYMORPH, OT_S_POLYMORPHRND, + // nature + OT_S_BARKSKIN, + OT_S_CALLLIGHTNING, + OT_S_CALMANIMALS, + OT_S_CALMINGSCENT, + OT_S_CHARMANIMAL, + OT_S_CUREPOISON, + OT_S_DETECTPOISON, + OT_S_DIG, + OT_S_WEB, + OT_S_ENDUREELEMENTS, + OT_S_ENTANGLE, + OT_S_HAILSTORM, + OT_S_PURIFYFOOD, + OT_S_QUENCH, + OT_S_LESSENPOISON, + OT_S_REPELINSECTS, + OT_S_SLEETSTORM, + OT_S_SOFTENEARTH, + OT_S_STICKTOSNAKE, + OT_S_WARPWOOD, // -- summoning OT_S_CREATEMONSTER, // -- translocation @@ -895,9 +1006,11 @@ enum OBTYPE { OT_A_LEVELUP, // abilities OT_A_GRAB, + OT_A_CHARGE, OT_A_CRUSH, OT_A_JUMP, OT_A_SPRINT, + OT_A_STINGACID, // need to define dam in f_canwill OT_A_SWOOP, OT_A_EMPLOY, OT_A_HEAVYBLOW, @@ -905,7 +1018,6 @@ enum OBTYPE { OT_A_INSPECT, OT_A_HURRICANESTRIKE, OT_A_POLYREVERT, - OT_A_STINGACID, // need to define dam in f_canwill OT_A_WARCRY, // uses F_NOISETEXT -> N_WARCRY if it is there. // otherwise 'shouts a blood-curdling war cry' // wands @@ -959,6 +1071,8 @@ enum OBTYPE { OT_BROKENGLASS, OT_ICECHUNK, OT_ICESHEET, + OT_MUDPOOL, + OT_PUDDLEOIL, OT_SPLASHWATER, OT_PUDDLEWATER, OT_PUDDLEWATERL, @@ -977,13 +1091,17 @@ enum OBTYPE { OT_FIRELARGE, OT_FIREMED, OT_FIRESMALL, + OT_HAILSTORM, OT_MAGICBARRIER, OT_STEAMCLOUD, OT_STEAMPUFF, + OT_SLEETSTORM, OT_SMOKECLOUD, OT_SMOKEPUFF, OT_POISONCLOUD, OT_POISONPUFF, + OT_VINE, + OT_WEB, // armour - body OT_ARMOURLEATHER, OT_ARMOURRING, @@ -1039,6 +1157,7 @@ enum OBTYPE { OT_RING_CONTROL, OT_RING_CON, OT_RING_DEX, + OT_RING_HUNGER, OT_RING_IQ, OT_RING_STR, OT_RING_MANA, @@ -1151,6 +1270,7 @@ enum BODYPART { #define WE_WALKABLE 1 #define WE_EMPTY 2 #define WE_PORTAL 3 +#define WE_NOTWALL 4 enum NOISETYPE { N_GETANGRY, @@ -1196,6 +1316,7 @@ enum FLAG { F_CONTAINSOB, // for vending machiens. v0 is ob letter // text is an object it contains. F_IDWHENUSED, // fully identify an object when worn/weilded/operated/etc + F_STARTBLESSED, // v0 = b_blessed or b_cursed // 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) @@ -1213,7 +1334,9 @@ enum FLAG { F_CRUSHABLE, // if you are bigger than size v0, walking on this crushes it F_BLOCKSVIEW, // cannot see past this F_BLOCKSTHROW, // cannot throw past this - F_DIETEXT, // text when the object dies + F_THEREISHERE, // announce "there is xx here!", not "you see xx here" + // text[0] is punctuation to use. + F_OBDIETEXT, // text when the object dies F_DIECONVERTTEXT, // text when the object converts. eg. "melts" F_DIECONVERTTEXTPL, // text when the object converts, if there are more than 1. eg. "melt" F_DIECONVERT, // val0 = what this turns into when dying @@ -1241,9 +1364,7 @@ enum FLAG { F_HITCONFER, // hitting with this gives flagid=v0 // unless you pass a val1 skillcheck, diff val2 // with timeleft = text ("min-max") - F_HITPOISONTYPE, // used when you have f_hitconfer->f_poisoned. - // v0 is type of poison. - // v1 is power (NA means 1) + F_HITCONFERVALS,// specifies values for conferred flag. F_ACTIVATED, // val0 = is this object turned on? F_GRENADE, // this obkejct will drain charge when activated, then die F_EXPLODEONDEATH, // explodes when it dies, deals TEXT damage. @@ -1299,14 +1420,25 @@ enum FLAG { // ob interaction flags F_HARD, // object is hard (ie. punching it will hurt!) + 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. + // + // for multiple objects, each one adds half its difficulty + + F_RODSHAPED, // for sticks-to-snakes F_SHARP, // does damage when you step on it. v0/1 are min/max dam F_SCARY, // gives other lfs a penalty to morale checks against you, // v0 = penalty amt. F_SLIPPERY, // you might slip when stepping on it. v0 is amt F_SLIPMOVE, // if someone slips on this, it will move to an adj cell F_FLAMMABLE, // object will catch alight if burnt (ie fire damage) + // v0 = how long it will burn for + // text (optional) = what it will convert to + // instead of just being set alight F_CANGETWET, // object will get F_WET if hit by water // v0 = enum WETNESS. v1 = how long + F_WATERPROOF, // object doesn't get wet. note: overrides CANGETWET! F_WET, // object is wet F_RUSTED, // object is rusty // v0 = enum RUSTINESS. @@ -1378,6 +1510,9 @@ enum FLAG { F_IDENTIFIED, // whether this object is fully identified // bad flags F_WALKDAM, // val0 = damtype, text = dam per sec + F_WALKDAMBP, // v0 = bodypart, v1 = damtype, text = dam per sec + // if v2 == FALLTHRU, damage falls through to lf if + // no armour is there. // abilities F_NEEDSGRAB, // this ability needs to to grab someone first. F_NOANNOUNCE, // don't announce when you gain/lose this ability @@ -1409,6 +1544,7 @@ enum FLAG { // lifeform flags / lf flags F_DEBUG, // debugging enabled F_ACCURACYMOD, // modify your accuracy by val0 + F_VEGETARIAN, // this lf will not eat meat. F_SHIELDPENALTY, // lower your accuracy by val0 due to a cumbersome // shield F_LEVRACE, // at level v0, this race is promoted to race v1 @@ -1430,6 +1566,8 @@ enum FLAG { F_STARTOBCLASS, // val0 = %chance of starting with obclass val1 F_STARTJOB, // val0 = %chance of starting with it, v1 = jobid F_STARTATT, // val0 = A_xxx, val0 = start bracket (ie. IQ_GENIUS) + F_STARTHIDDENPCT, // val0 = pct chance auto-generated monster will + // start off hidden F_CORPSETYPE, // text field specifies what corpse obtype to leave F_MYCORPSE, // text field contains obid of my corpse. // (for ghosts) @@ -1444,7 +1582,7 @@ enum FLAG { // (text is a long) // ABILITY/SPELL FLAGS / ability flags / spell flags F_FAILEDINSPECT, // lf has failed an inspect check for item id v0 - F_BOOSTSPELL, // v0 is active boost spell + F_BOOSTSPELL, // v0 is active boost spell, v1 is ongoing mpcost, v2 is power F_SWOOPRANGE, // v0 = how far a flying creature can swoop // MONSTER AI FLAGS F_XPVAL, // force xp val for killing this lf to v0 @@ -1466,7 +1604,10 @@ enum FLAG { F_FLEEONHPPCT, // lf will run away if its hp drop to v0% or lower F_NOFLEE, // lf will not run away F_TARGET, // lf will attack lfid v0. lastknown x/y is v1/v2 + F_IGNORECELL, // won't accept targetcells of v0=x v1=y + // this is cleared at start of turn. F_TARGETCELL, // lf will go towards this place. val0=x,val1=y + // optional: v2 = mr_lf or mr_ob. text=lf or ob id. F_STABBEDBY, // lf has been stabbed by lfid v0. can't be stabbed // by them again until they go out of sight. F_FLEEFROM, // lf will run away from this lf id @@ -1479,6 +1620,8 @@ enum FLAG { // text is "verb^noun" // eg. "shouts^a shout" F_SPELLCASTTEXT, // text is announcement for spellcast + // if text is empty, then don't announce + // this lf's spell casting at all. F_NODEATHANNOUNCE, // don't say 'the xx dies' if this lf dies F_BEHEADED, // use special corpse drop code F_SILENTMOVE, // lf makes no noise when walking/flying @@ -1523,6 +1666,7 @@ enum FLAG { // INTRINSICS F_MAGICARMOUR,// armour is magically boosted. f->text is the description // ie 'magic armour', 'force field' + // v0 is power left. F_ASLEEP, // is asleep F_BEINGSTONED,// turn to stone when v0 drops to zero. (drops 1/turn) F_BLIND, // cannot see anything @@ -1557,6 +1701,8 @@ enum FLAG { F_EXTRAMP, // lf has +v0 % extra maxmp F_FLYING, // lf is flying F_FASTACT, // modifier for action speed + F_FASTMETAB, // hunger counter increases faster, poison cures faster. + // v0 is multiplier. F_FASTMOVE, // modifier for move speed F_FASTACTMOVE, // modifier for action and move speed F_POISONED, // has poisoning. v0 = poison type, @@ -1573,6 +1719,7 @@ enum FLAG { // (bypasses armour) F_GRAVBOOSTED,// cannot walk or throw stuff F_PAIN, // take damage if you walk. v0=damtype,text is damage (xdy+z). + // if text not set, default dam is 1d2 F_PARALYZED,// cannot do anything F_FROZEN, // made of ice F_LEVITATING, // like flying but uncontrolled @@ -1655,6 +1802,13 @@ enum FLAG { F_NULL = -1 }; +// move reasons +enum MOVEREASON { + MR_OTHER, + MR_LF, + MR_OB, +}; + // hunger levels enum HUNGER { @@ -1678,6 +1832,8 @@ enum HUNGER { #define B_FALSE (0) #define B_TRUE (-1) +#define FALLTHRU (-8765) + //#define B_TEMP (-1) //#define B_PERM (-2) //#define B_NOT (-3) @@ -1797,6 +1953,7 @@ enum ERROR { E_DRUNK = 47, // E_NOBP = 48, + E_VEGETARIAN = 49, }; @@ -1908,9 +2065,18 @@ typedef struct celltype_s { } celltype_t; +typedef struct raceclass_s { + enum RACECLASS id; + char *name; + char *pluralname; + enum SKILL skill; + struct raceclass_s *next, *prev; +} raceclass_t; + typedef struct race_s { enum RACE id; enum RACE baseid; + struct raceclass_s *raceclass; struct material_s *material; char *name; struct glyph_s glyph; @@ -1962,7 +2128,6 @@ typedef struct lifeform_s { int born; // for ai movement - don't need to save. - struct cell_s *ignorecell; struct cell_s *cell; struct lifeform_s *next, *prev; @@ -2010,59 +2175,6 @@ typedef struct material_s { } material_t; -enum SKILL { - SK_NONE = 0, - SK_ARMOUR = 1, - SK_ATHLETICS, - SK_BACKSTAB, - SK_FIRSTAID, - SK_LISTEN, - SK_LOCKPICKING, - SK_MAGITEMUSAGE, - SK_RESEARCH, - SK_SHIELDS, - SK_SPELLCASTING, - SK_SPOTHIDDEN, - SK_STEALTH, - SK_TECHUSAGE, - // weaponry - SK_AXES, - SK_CLUBS, - SK_LONGBLADES, - SK_POLEARMS, - SK_SHORTBLADES, - SK_STAVES, - SK_UNARMED, - // spell schools - SK_SS_ALLOMANCY, - SK_SS_AIR, - SK_SS_DEATH, - SK_SS_DIVINATION, - SK_SS_EARTH, - SK_SS_FIRE, - SK_SS_ICE, - SK_SS_GRAVITY, - SK_SS_LIFE, - SK_SS_MODIFICATION, - SK_SS_MENTAL, - SK_SS_SUMMONING, - SK_SS_TRANSLOCATION, - SK_SS_WILD, -}; -#define MAXSKILLS 35 - -// proficiency levels -enum SKILLLEVEL { - PR_INEPT = 0, - PR_NOVICE = 1, - PR_BEGINNER = 2, - PR_ADEPT = 3, - PR_SKILLED = 4, - PR_EXPERT = 5, - PR_MASTER = 6, -}; - - typedef struct skill_s { enum SKILL id; char *name; diff --git a/doc/add_skill.txt b/doc/add_skill.txt index fb96ec2..54824c5 100644 --- a/doc/add_skill.txt +++ b/doc/add_skill.txt @@ -9,3 +9,5 @@ objects.c: lf.c: add addskill() + + if it is a lroe skill, update isloreskill() diff --git a/flag.c b/flag.c index 5167871..86c5a9d 100644 --- a/flag.c +++ b/flag.c @@ -395,7 +395,17 @@ void killflagpile(flagpile_t *fp) { void timeeffectsflag(flag_t *f, int howlong) { if ((f->lifetime != PERMENANT) && (f->lifetime > 0)) { + // special case - fast metabolism speeds up poison too. + if (f->id == F_POISONED) { + int multiplier; + sumflags(f->pile, F_FASTMETAB, &multiplier, NULL, NULL); + if (multiplier > 0) { + howlong *= multiplier; + } + } + f->lifetime -= howlong; + if (f->lifetime <= 0) { killflag(f); return; diff --git a/io.c b/io.c index f4146de..ce58795 100644 --- a/io.c +++ b/io.c @@ -382,6 +382,8 @@ cell_t *askcoords(char *prompt, int targettype) { int valid = B_FALSE; if ((targettype & TT_MONSTER) && haslf(c) && cansee(player, c->lf) && (c->lf->controller != C_PLAYER)) { valid = B_TRUE; + } else if ((targettype & TT_ALLY) && haslf(c) && cansee(player, c->lf) && areallies(c->lf, player)) { + valid = B_TRUE; } else if ((targettype & TT_PLAYER) && haslf(c) && cansee(player, c->lf) && isplayer(c->lf)) { valid = B_TRUE; } else if ((targettype & TT_OBJECT) && hasobject(c)) { @@ -443,7 +445,7 @@ cell_t *askcoords(char *prompt, int targettype) { if (c->lf) { if (cansee(player, c->lf)) { flag_t *f; - object_t *wep; + object_t *wep,*o; char extrainfo[BUFLEN]; strcpy(extrainfo, ""); getlfnamea(c->lf, buf); @@ -488,8 +490,47 @@ cell_t *askcoords(char *prompt, int targettype) { if (strlen(extrainfo)) strcat(extrainfo, ", "); strcat(extrainfo, "asleep"); } + + if ((getallegiance(c->lf) == AL_HOSTILE) && + (getlorelevel(player, c->lf->race->raceclass->id) >= PR_ADEPT)) { + char dangerbuf[BUFLEN]; + float rating; + rating = comparelfs(player, c->lf); + if (rating >= 4) { + sprintf(dangerbuf, "trivial"); + } else if (rating >= 3) { + sprintf(dangerbuf, "very easy"); + } else if (rating >= 2) { + sprintf(dangerbuf, "easy"); + } else if (rating >= 1) { + sprintf(dangerbuf, "average"); + } else if (rating >= 0.5) { + sprintf(dangerbuf, "challenging"); + } else if (rating >= 0.25) { + sprintf(dangerbuf, "formidable"); + } else if (rating >= 0.125) { + sprintf(dangerbuf, "dangerous"); + } else { + sprintf(dangerbuf, "very dangerous"); + } + if (strlen(extrainfo)) strcat(extrainfo, ", "); + strcat(extrainfo, dangerbuf); + } + + o = hasobwithflag(c->obpile, F_RESTRICTMOVEMENT); + if (o) { + char buf2[BUFLEN]; + char obname[BUFLEN]; + + if (strlen(extrainfo)) strcat(extrainfo, ", "); + getobname(o, obname, o->amt); + sprintf(buf2, "stuck in %s", obname); + strcat(extrainfo, buf2); + } // hp - if (isgenius(player) || (getseenlfconditioncutoff(player) == C_HEALTHY) ) { + if (isgenius(player) || (getseenlfconditioncutoff(player) == C_HEALTHY) || + (getlorelevel(player, c->lf->race->raceclass->id) >= PR_ADEPT) + ) { char buf2[BUFLEN]; // show actual hp sprintf(buf2, "hp %d/%d",c->lf->hp, c->lf->maxhp); @@ -505,6 +546,7 @@ cell_t *askcoords(char *prompt, int targettype) { } } + wep = getweapon(c->lf); if (wep && (c->lf->race->id != R_DANCINGWEAPON)) { object_t *secwep; @@ -957,6 +999,12 @@ int announceflaggain(lifeform_t *lf, flag_t *f) { msg("%s %s",lfname, isplayer(lf) ? "feel accelerated!" : "looks accelerated!"); donesomething = B_TRUE; break; + case F_FASTMETAB: + if (isplayer(lf)) { // don't know if monsters get it + msg("You feel ravenous!"); + donesomething = B_TRUE; + } + break; case F_FASTMOVE: msg("%s %s faster.",lfname, isplayer(lf) ? "feel yourself moving" : "is now moving"); donesomething = B_TRUE; @@ -1240,6 +1288,9 @@ int announceflagloss(lifeform_t *lf, flag_t *f) { char buf[BUFLEN]; getlfname(lf2, buf); msg("%s break%s free of %s%s control!",lfname, isplayer(lf) ? "" : "s", buf,getpossessive(buf)); + if (isplayer(lf2)) { + more(); + } donesomething = B_TRUE; } break; @@ -1299,6 +1350,12 @@ int announceflagloss(lifeform_t *lf, flag_t *f) { msg("%s %s",lfname, isplayer(lf) ? "are no longer accelerated." : "is no longer accelerated."); donesomething = B_TRUE; break; + case F_FASTMETAB: + if (isplayer(lf)) { // don't know if monsters lose it + msg("Your metabolic rate has returned to normal."); + donesomething = B_TRUE; + } + break; case F_FASTMOVE: msg("%s %s slower.",lfname, isplayer(lf) ? "feel yourself moving" : "is now moving"); donesomething = B_TRUE; @@ -1581,6 +1638,7 @@ int announceobflaggain(object_t *o, flag_t *f) { int donesomething = B_FALSE; char obname[BUFLEN]; char prefix[BUFLEN]; + int wantpremods = B_TRUE; cell_t *loc; loc = getoblocation(o); @@ -1590,7 +1648,14 @@ int announceobflaggain(object_t *o, flag_t *f) { if (!haslos(player, loc)) { return B_FALSE; } - real_getobname(o, obname, o->amt, B_TRUE, B_FALSE, B_TRUE, B_TRUE); + + + if (f->id == F_ONFIRE) { + // don't want "the flaming sword catches on fire" + wantpremods = B_FALSE; + } + + real_getobname(o, obname, o->amt, wantpremods, B_FALSE, B_TRUE, B_TRUE); if (o->pile->owner) { if (isplayer(o->pile->owner)) { @@ -1608,8 +1673,6 @@ int announceobflaggain(object_t *o, flag_t *f) { switch (f->id) { case F_ONFIRE: donesomething = B_TRUE; - // don't want "the flaming sword catches on fire" - real_getobname(o, obname, o->amt, B_FALSE, B_FALSE, B_TRUE, B_TRUE); if (o->birthtime != curtime) msg("%s catch%s on fire.",prefix, (o->amt == 1) ? "es" : ""); break; case F_PRODUCESLIGHT: @@ -1626,6 +1689,7 @@ void announceobflagloss(object_t *o, flag_t *f) { char obname[BUFLEN]; char prefix[BUFLEN]; char isare[BUFLEN]; + char *temp; cell_t *loc; loc = getoblocation(o); @@ -1657,7 +1721,12 @@ void announceobflagloss(object_t *o, flag_t *f) { switch (f->id) { case F_ONFIRE: - msg("%s %s no longer on fire.",prefix,isare); + // replace "the flaming xxx is no longer on fire" + // with "the xxx is no longer on fire" + temp = strdup(prefix); + temp = strrep(temp, "flaming ","",NULL); + msg("%s %s no longer on fire.",temp,isare); + free(temp); break; case F_PRODUCESLIGHT: msg("%s %s no longer glowing.",prefix,isare); @@ -2544,9 +2613,11 @@ void describeob(object_t *o) { } - // now special flags... + // skip line y++; + + // physical properties f = hasflag(o->flags, F_MASTERWORK); if (f && f->known) { mvwprintw(mainwin, y, 0, "It is extremely well crafted."); @@ -2569,17 +2640,22 @@ void describeob(object_t *o) { y++; } - f = hasflag(o->flags, F_WET); - if (f) { - mvwprintw(mainwin, y, 0, "It is wet."); - y++; - } f = hasflag(o->flags, F_RUSTED); if (f) { mvwprintw(mainwin, y, 0, "It is rusty."); y++; } + f = hasflag(o->flags, F_WATERPROOF); + if (f) { + mvwprintw(mainwin, y, 0, "It is waterproof."); + y++; + } + f = hasflag(o->flags, F_WET); + if (f) { + mvwprintw(mainwin, y, 0, "It is wet."); + y++; + } f = hasflag(o->flags, F_ACTIVATED); if (f) { @@ -2650,6 +2726,9 @@ void describeob(object_t *o) { case F_FASTACT: mvwprintw(mainwin, y, 0, "%s will speed up your actions.", buf); y++; break; + case F_FASTMETAB: + mvwprintw(mainwin, y, 0, "%s will increase your metabolic rate.", buf); y++; + break; case F_FASTMOVE: mvwprintw(mainwin, y, 0, "%s will speed up your movement.", buf); y++; break; @@ -2796,13 +2875,39 @@ void describeob(object_t *o) { y++; } + + // requirements + i = B_FALSE; + for (f = o->flags->first ; f ; f = f->next) { + if (f->id == F_ATTREQ) { + int usable = B_TRUE; + if (!meetsattreq(player, f, o)) { + usable = B_FALSE; + } + if (!usable) setcol(mainwin, C_RED); + mvwprintw(mainwin, y, 0, "It requires at least %d %s to use.", f->val[1], getattrname(f->val[0])); + y++; + if (!usable) unsetcol(mainwin, C_RED); + i = B_TRUE; + } + } + + // blank line y++; + // skill type? f = hasflag(o->flags, F_USESSKILL); if (f) { - mvwprintw(mainwin, y, 0, "It falls into the '%s' category (your skill: %s).",getskillname(f->val[0]), - getskilllevelname(getskill(player, f->val[0])) ); + enum SKILLLEVEL slev; + enum COLOUR col; + slev = getskill(player, f->val[0]); + mvwprintw(mainwin, y, 0, "It falls into the '%s' category (your skill: ",getskillname(f->val[0])); + col = getskilllevelcolour(slev); + setcol(mainwin, col); + wprintw(mainwin, "%s", getskilllevelname(getskill(player, f->val[0])) ); + unsetcol(mainwin, col); + wprintw(mainwin, ")"); y++; } @@ -2839,7 +2944,6 @@ void describeob(object_t *o) { void describespell(objecttype_t *ot) { char buf[BUFLEN]; - int y; flag_t *f; int i; int power; @@ -2851,36 +2955,31 @@ void describespell(objecttype_t *ot) { capitalise(buf); mvwprintw(mainwin, 0, 0, buf); - sprintf(buf, "%s",ot->desc); - mvwprintw(mainwin, 2, 0, buf); + mvwprintw(mainwin, 2, 0,"%s\n\n", ot->desc); // properties - y = 5; f = hasflag(ot->flags, F_SPELLLEVEL); if (f) { flag_t *sf; sf = hasflag(ot->flags, F_SPELLSCHOOL); assert(sf); - mvwprintw(mainwin, y, 0, "It is a level %d %s spell.",f->val[0], getschoolname(sf->val[0])); - y++; + wprintw(mainwin, "It is a level %d %s spell.\n",f->val[0], getschoolname(sf->val[0])); } i = getmpcost(NULL, ot->id); if (i > 0) { if (hasflag(ot->flags, F_ONGOING)) { - mvwprintw(mainwin, y, 0, "It takes %d MP to keep active - this is an ongoing cost.",i); + wprintw(mainwin, "It takes %d MP to keep active - this is an ongoing cost.\n",i); } else { - mvwprintw(mainwin, y, 0, "It costs %d MP to cast.",i); + wprintw(mainwin, "It costs %d MP to cast.\n",i); } - y++; } - y++; + wprintw(mainwin, "\n"); power = getspellpower(player, ot->id); - mvwprintw(mainwin, y, 0, "You can cast it at power level %d (maximum %d).",power, getspellmaxpower(ot->id)); - y++; + wprintw(mainwin, "You can cast it at power level %d (maximum %d).\n",power, getspellmaxpower(ot->id)); wrefresh(mainwin); @@ -3044,7 +3143,7 @@ void docomms(void) { // find adjacent cell c = getrandomadjcell(player->cell, WE_WALKABLE, B_ALLOWEXPAND); if (c) { - aigoto(lf, c, AI_FOLLOWTIME); + aigoto(lf, c, MR_OTHER, NULL, AI_FOLLOWTIME); } break; case 'n': @@ -3227,7 +3326,7 @@ void doeat(obpile_t *op) { // edible objects here? for (o = player->cell->obpile->first; o ; o = o->next) { - if (isedible(o)) { + if (caneat(player, o)) { getobname(o, obname, o->amt); sprintf(buf, "There %s %s here. Eat %s", (o->amt == 1) ? "is" : "are", @@ -3491,6 +3590,24 @@ void dolook(cell_t *where) { char buf[BUFLEN]; char seeverb[BUFLEN]; int seensomething = B_FALSE; + object_t *o,*firstob = NULL; + flag_t *f; + + // first announce "there is xxx" objects + // (also count objects without this flag) + numobs = 0; + for (o = where->obpile->first ; o ; o = o->next) { + f = hasflag(o->flags, F_THEREISHERE); + if (f) { + // doens't matter if you're blind + getobname(o, buf, o->amt); + msg("There is %s here%c", buf, f->text[0]); + seensomething = B_TRUE; + } else { + if (!numobs) firstob = o; + numobs++; + } + } //if (isblind(player)) { if (!haslos(player, player->cell)) { @@ -3499,11 +3616,12 @@ void dolook(cell_t *where) { strcpy(seeverb, "see"); } - numobs = countobs(where->obpile); if (numobs > 0) { if (numobs == 1) { - getobname(where->obpile->first, buf, where->obpile->first->amt); - msg("You %s %s here.", seeverb, buf); + if (!hasflag(firstob->flags, F_THEREISHERE)) { + getobname(firstob, buf, firstob->amt); + msg("You %s %s here.", seeverb, buf); + } } else if ((numobs > 1) && (numobs <= 3)) { msg("You %s a few objects here.", seeverb); } else if ((numobs > 3) && (numobs <= 6)) { @@ -3514,8 +3632,6 @@ void dolook(cell_t *where) { seensomething = B_TRUE; } - - // writing here? if (where->writing && !isblind(player)) { msg("There is a magical inscription here:"); @@ -3523,7 +3639,6 @@ void dolook(cell_t *where) { seensomething = B_TRUE; } - if (!seensomething) { // just clear the message buffer //clearmsg(); @@ -3549,7 +3664,7 @@ void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2, int validspell[MAXCANDIDATES]; int deactspell[MAXCANDIDATES]; int nposs = 0; - int i,n; + int i,n,lev; enum SPELLSCHOOL lastschool; objecttype_t *ot; @@ -3559,91 +3674,99 @@ void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2, if ((wantschool != SS_NONE) && (i != wantschool)) { continue; } + // only god gets divine ones + 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; } } - // get list of spells/abilities we can cast at will - for (ot = objecttype ; ot ; ot = ot->next) { - if ((ot->obclass->id == OC_SPELL) || (ot->obclass->id == OC_ABILITY)) { - f = lfhasflagval(lf, F_CANWILL, ot->id, NA, NA, NULL); - if (!wantunknown && f) { - if (hasflagval(ot->flags, F_SPELLSCHOOL, i, NA, NA, NULL)) { - poss[nposs] = ot->id; - deactspell[nposs] = B_FALSE; // default - mpcost[nposs] = -1; - if (f->val[2] == NA) { - sprintf(mpdesc[nposs], "(ready)"); - validspell[nposs] = B_TRUE; - } else { - if (f->val[1] == f->val[2]) { - sprintf(mpdesc[nposs], "(ready)"); - validspell[nposs] = B_TRUE; - } else { - sprintf(mpdesc[nposs], "(%d/%d)",f->val[1],f->val[2]); - validspell[nposs] = B_FALSE; - } - } - - nposs++; - } - } - } - } - - - if (!lfhasflag(lf, F_NOSPELLS)) { - // get list of spells we can cast using mp + for (lev = 0; lev <= MAXSPELLLEV; lev++) { + // get list of spells/abilities we can cast at will for (ot = objecttype ; ot ; ot = ot->next) { - if (ot->obclass->id == OC_SPELL) { // is it a spell? - if (hasflagval(ot->flags, F_SPELLSCHOOL, i, NA, NA, NULL)) { // from the current school? - // not using 'cancast' here because we want to list spells - // even if we don't have enough mp - f = lfhasflagval(lf, F_CANCAST, ot->id, NA, NA, NULL); - if ((f && !wantunknown) || (!f && wantunknown)) { - int cost; - int found = B_FALSE; - cost = getmpcost(lf, ot->id); - for (n = 0; n < nposs; n++) { - if (poss[n] == ot->id) { - found = B_TRUE; - break; - } - } - if (!found) { - int power; - // add to list + if ((ot->obclass->id == OC_SPELL) || (ot->obclass->id == OC_ABILITY)) { + // doesn't match the current level? + if (getspelllevel(ot->id) == lev) { + f = lfhasflagval(lf, F_CANWILL, ot->id, NA, NA, NULL); + if (!wantunknown && f) { + if (hasflagval(ot->flags, F_SPELLSCHOOL, i, NA, NA, NULL)) { poss[nposs] = ot->id; - mpcost[nposs] = cost; deactspell[nposs] = B_FALSE; // default - power = getspellpower(lf, ot->id); - if (power > 0) { - if (hasactivespell(lf, ot->id)) { - cost = 0; - mpcost[nposs] = 0; - strcpy(mpdesc[nposs], "(Deactivate, at will)"); - deactspell[nposs] = B_TRUE; - } else { - getspellcosttext(lf, ot->id, power, mpdesc[nposs]); - } - if (lf->mp >= mpcost[nposs]) { + mpcost[nposs] = -1; + if (f->val[2] == NA) { + sprintf(mpdesc[nposs], "(ready)"); + validspell[nposs] = B_TRUE; + } else { + if (f->val[1] == f->val[2]) { + sprintf(mpdesc[nposs], "(ready)"); validspell[nposs] = B_TRUE; } else { + sprintf(mpdesc[nposs], "(%d/%d)",f->val[1],f->val[2]); validspell[nposs] = B_FALSE; } - } else { - sprintf(mpdesc[nposs], "(too hard)"); - validspell[nposs] = B_FALSE; } + nposs++; } } + } // end if level ok + } // end if spell/ability + } // end foreach objecttype + + if (!lfhasflag(lf, F_NOSPELLS)) { + // get list of spells we can cast using mp + for (ot = objecttype ; ot ; ot = ot->next) { + if ((ot->obclass->id == OC_SPELL) && (getspelllevel(ot->id) == lev)) { // is it a spell? + if (hasflagval(ot->flags, F_SPELLSCHOOL, i, NA, NA, NULL)) { // from the current school? + // not using 'cancast' here because we want to list spells + // even if we don't have enough mp + f = lfhasflagval(lf, F_CANCAST, ot->id, NA, NA, NULL); + if ((f && !wantunknown) || (!f && wantunknown)) { + int cost; + int found = B_FALSE; + cost = getmpcost(lf, ot->id); + for (n = 0; n < nposs; n++) { + if (poss[n] == ot->id) { + found = B_TRUE; + break; + } + } + if (!found) { + int power; + // add to list + poss[nposs] = ot->id; + mpcost[nposs] = cost; + deactspell[nposs] = B_FALSE; // default + power = getspellpower(lf, ot->id); + if (power > 0) { + if (hasactivespell(lf, ot->id)) { + cost = 0; + mpcost[nposs] = 0; + strcpy(mpdesc[nposs], "(Deactivate, at will)"); + deactspell[nposs] = B_TRUE; + } else { + getspellcosttext(lf, ot->id, power, mpdesc[nposs]); + } + if (lf->mp >= mpcost[nposs]) { + validspell[nposs] = B_TRUE; + } else { + validspell[nposs] = B_FALSE; + } + } else { + sprintf(mpdesc[nposs], "(too hard)"); + validspell[nposs] = B_FALSE; + } + nposs++; + } + } + } } } } - } + } // end foreach spell level } // end foreach spell school @@ -3661,16 +3784,16 @@ void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2, lastschool = SS_LAST; for (i = 0; i < nposs; i++) { int power; + enum SPELLSCHOOL thisschool = SS_NONE; ot = findot(poss[i]); assert(ot); power = getspellpower(lf, poss[i]); // heading - f = hasflag(ot->flags, F_SPELLSCHOOL); - assert(f); - if (f->val[0] != lastschool) { - lastschool = f->val[0]; + thisschool = getspellschoolknown(lf, poss[i]); + if (thisschool != lastschool) { + lastschool = thisschool; addheading(pr, getschoolname(lastschool)); } @@ -4322,7 +4445,7 @@ int dotakeoff(obpile_t *op) { int rv = B_TRUE; // ask which object to read - o = askobject(op, "Take off what", NULL, AO_EQUIPPEDARMOUR ); + o = askobject(op, "Take off what", NULL, AO_EQUIPPEDNONWEAPON ); if (o) { if (isarmour(o)) { f = hasflag(o->flags, F_EQUIPPED); @@ -5086,6 +5209,24 @@ int getkey(void) { return keycodetokey(key_code); } +enum COLOUR getskilllevelcolour(enum SKILLLEVEL slev) { + switch (slev) { + case PR_INEPT: + return C_RED; + case PR_BEGINNER: + case PR_NOVICE: + return C_BROWN; + case PR_ADEPT: + return C_GREEN; + case PR_SKILLED: + case PR_EXPERT: + return C_BOLDGREEN; + case PR_MASTER: + return C_BOLDCYAN; + } + return C_GREY; +} + void handleinput(void) { int ch; //char buf[BUFLEN]; @@ -5103,8 +5244,10 @@ void handleinput(void) { object_t *o; + // certain objects will stop us from running. for (o = player->cell->obpile->first ; o ; o = o->next) { - if (!hasflag(o->flags, F_NOPICKUP)) { + if (!hasflag(o->flags, F_NOPICKUP) || + hasflag(o->flags, F_CLIMBABLE) ) { hasgettableobs = B_TRUE; break; } @@ -5503,7 +5646,6 @@ void warn(char *format, ... ) { // like msg, but interrupts rest ect interrupt(player); - va_start(args, format); vsprintf( buf, format, args ); @@ -6012,16 +6154,26 @@ void showlfarmour(lifeform_t *lf) { for (bp = BP_WEAPON; bp < MAXBODYPARTS; bp++) { char rhs[BUFLEN]; // default - sprintf(rhs, "-"); + strcpy(rhs, ""); if (!lfhasflagval(lf, F_NOBODYPART, bp, NA, NA, NULL)) { + object_t *outerob; sprintf(buf, "%15s:%3s",getbodypartname(bp), " "); - o = hasobwithflagval(lf->pack, F_EQUIPPED, bp, NA, NA, NULL); + o = getequippedob(lf->pack, bp); + outerob = getouterequippedob(lf, bp); if (o) { char obname[BUFLEN]; getobname(o, obname, o->amt); strcpy(rhs, obname); - } else { + } + + if (outerob && (outerob != o)) { + char outerobname[BUFLEN]; + getobname(outerob, outerobname, outerob->amt); + if (strlen(rhs)) strcat(rhs, " "); + strcat(rhs, "(covered) "); + } + if (!strlen(rhs)) { strcpy(rhs, "-"); } @@ -6088,17 +6240,33 @@ void showlfstats(lifeform_t *lf, int showall) { char prompt[BUFLEN]; char cmdchars[BUFLEN]; int done = B_FALSE; + enum SKILLLEVEL lorelev; + enum COLOUR lorecol; h = getmaxy(mainwin); + + // determine knowledge about this monster + lorelev = getlorelevel(player, lf->race->raceclass->id); + if (isplayer(lf)) { + lorecol = C_GREY; // ie. no colour + } else if (lorelev == PR_MASTER) { + lorecol = C_GREY; // ie. no colour + } else { + lorecol = C_BROWN; + } + + + // override showall sometimes... // need 'player == lf' to cope with mind scans // where we update the player pointer, but don't // change the target's '->controller' setting (meaning // that isplayer(target) still returns false). - if (isplayer(lf) || isgenius(player) || (player == lf)) { + if (isplayer(lf) || isgenius(player) || (player == lf) || (lorelev >= PR_MASTER)) { showall = B_TRUE; } + if (showall) { sprintf(prompt, "[@=stats S=skills/abilities M=magic E=effects %sESC=quit]", isplayer(lf) ? "" : "I=items " ); @@ -6140,7 +6308,8 @@ void showlfstats(lifeform_t *lf, int showall) { j = getjob(lf); if (j) { mvwprintw(mainwin, y, 0, ftext, "Job"); - wprintw(mainwin, "%-20s", j->name); y++; + sprintf(buf, "Level %d %s", lf->level, j->name); + wprintw(mainwin, "%-20s", buf); y++; } @@ -6159,9 +6328,13 @@ void showlfstats(lifeform_t *lf, int showall) { - if (showall || (getseenlfconditioncutoff(player) == C_HEALTHY)) { + if (showall || + (getseenlfconditioncutoff(player) == C_HEALTHY) || + (lorelev >= PR_ADEPT)) { + if (lorelev >= PR_ADEPT) setcol(mainwin, lorecol); mvwprintw(mainwin, y, 0, ftext, "Hit Points"); wprintw(mainwin, "%d / %d", lf->hp , lf->maxhp); y++; + if (lorelev >= PR_ADEPT) unsetcol(mainwin, lorecol); } else { char hpinfo[BUFLEN]; sprintf(hpinfo, "%s",getseenlfconditionname(lf, player)); @@ -6222,14 +6395,16 @@ void showlfstats(lifeform_t *lf, int showall) { if (str != lf->baseatt[A_STR]) strcat(buf, "*"); mvwprintw(mainwin, y, 0, ftext, "STR"); wprintw(mainwin, "%s", buf); y++; - } else if (!isplayer(lf)) { + } else if (!isplayer(lf) && (lorelev >= PR_NOVICE)) { int str; // just show name str = getattr(lf, A_STR); getstrname(str, buf); if (str != lf->baseatt[A_STR]) strcat(buf, "*"); + setcol(mainwin, lorecol); mvwprintw(mainwin, y, 0, ftext, "STR"); wprintw(mainwin, "%s", buf); y++; + unsetcol(mainwin, lorecol); } if (showall) { @@ -6249,14 +6424,16 @@ void showlfstats(lifeform_t *lf, int showall) { if (dex != lf->baseatt[A_DEX]) strcat(buf, "*"); mvwprintw(mainwin, y, 0, ftext, "DEX"); wprintw(mainwin, "%s", buf); y++; - } else if (!isplayer(lf)) { + } else if (!isplayer(lf) && (lorelev >= PR_NOVICE)) { int dex; // just show name dex = getattr(lf, A_DEX); getdexname(dex, buf); if (dex != lf->baseatt[A_DEX]) strcat(buf, "*"); + setcol(mainwin, lorecol); mvwprintw(mainwin, y, 0, ftext, "DEX"); wprintw(mainwin, "%s", buf); y++; + unsetcol(mainwin, lorecol); } if (showall) { @@ -6268,14 +6445,16 @@ void showlfstats(lifeform_t *lf, int showall) { if (iq != lf->baseatt[A_IQ]) strcat(buf, "*"); mvwprintw(mainwin, y, 0, ftext, "IQ"); wprintw(mainwin, "%s", buf); y++; - } else if (!isplayer(lf)) { + } else if (!isplayer(lf) && (lorelev >= PR_NOVICE)) { int iq; // just show name iq = getattr(lf, A_IQ); getiqname(iq, buf); if (iq != lf->baseatt[A_IQ]) strcat(buf, "*"); + setcol(mainwin, lorecol); mvwprintw(mainwin, y, 0, ftext, "IQ"); wprintw(mainwin, "%s", buf); y++; + unsetcol(mainwin, lorecol); } if (showall) { @@ -6287,14 +6466,16 @@ void showlfstats(lifeform_t *lf, int showall) { if (con != lf->baseatt[A_CON]) strcat(buf, "*"); mvwprintw(mainwin, y, 0, ftext, "CON"); wprintw(mainwin, "%s", buf); y++; - } else if (!isplayer(lf)) { + } else if (!isplayer(lf) && (lorelev >= PR_NOVICE)) { int con; // just show name con = getattr(lf, A_CON); getconname(con, buf); if (con != lf->baseatt[A_CON]) strcat(buf, "*"); + setcol(mainwin, lorecol); mvwprintw(mainwin, y, 0, ftext, "CON"); wprintw(mainwin, "%s", buf); y++; + unsetcol(mainwin, lorecol); } //mvwprintw(mainwin, y, 0, ftext, "XP"); @@ -6357,6 +6538,14 @@ void showlfstats(lifeform_t *lf, int showall) { acc = getlfaccuracy(lf, w); mvwprintw(mainwin, y2, x2, ftext, "Wep.Accuracy"); wprintw(mainwin, "%d%%", acc); y2++; + + // attack speed + speed = getattackspeed(lf); + getspeedname(speed, buf); + capitalise(buf); + mvwprintw(mainwin, y2, x2, ftext, "Attack Speed"); + wprintw(mainwin, "%-20s", buf); y2++; + } } else { // no damage @@ -6386,10 +6575,11 @@ void showlfstats(lifeform_t *lf, int showall) { ot = findot(f->val[0]); o = addob(op, ot->name); if (o) { + char dambuf[BUFLEN]; + strcpy(dambuf, ""); sprintf(buf, "%s", o->type->name); // damage - if (showall) { - char dambuf[BUFLEN]; + if (showall || (lorelev >= PR_BEGINNER)) { int mindam,maxdam; getdamrange(f, &mindam, &maxdam); @@ -6403,11 +6593,16 @@ void showlfstats(lifeform_t *lf, int showall) { if (maxdam < 0) maxdam = 0; sprintf(dambuf, " (%d-%d dmg)",(int)mindam,(int)maxdam); - strcat(buf, dambuf); } mvwprintw(mainwin, y2, x2, ftext, "Innate Attack"); - wprintw(mainwin, "%-20s", buf); y2++; + wprintw(mainwin, "%s", buf); + if (strlen(dambuf)) { + if (lorelev >= PR_BEGINNER) setcol(mainwin, lorecol); + wprintw(mainwin, "%s", dambuf); + if (lorelev >= PR_BEGINNER) unsetcol(mainwin, lorecol); + } + y2++; } // end if o } // end if fid == hasattack @@ -6424,28 +6619,24 @@ void showlfstats(lifeform_t *lf, int showall) { // skip line y2++; - // attack speed - if (w || op->first) { - speed = getattackspeed(lf); - getspeedname(speed, buf); - capitalise(buf); - mvwprintw(mainwin, y2, x2, ftext, "Attack Speed"); - wprintw(mainwin, "%-20s", buf); y2++; - } - killobpile(op); - y2++; // skip line - // ARMOUR STUFF - if (showall) { + if (showall || (lorelev >= PR_NOVICE)) { arating = getarmourrating(lf); - mvwprintw(mainwin, y2, x2, ftext, "Armour"); + + if (lorelev >= PR_NOVICE) setcol(mainwin, lorecol); + + mvwprintw(mainwin, y2, x2, ftext, "Armour Rating"); if (arating > 0) { wprintw(mainwin, "%d (-%0.0f%% dmg)", arating, getdamreducepct(arating)); y2++; } else { wprintw(mainwin, "%d", arating); y2++; } + if (lorelev >= PR_NOVICE) unsetcol(mainwin, lorecol); + } + + if (showall) { evasion = getevasion(lf); mvwprintw(mainwin, y2, x2, ftext, "Evasion"); wprintw(mainwin, "%d%%", evasion); y2++; @@ -6488,8 +6679,77 @@ void showlfstats(lifeform_t *lf, int showall) { } - // back to first column - y++; + // now show bottom information. + if (y2 > y) { + y = y2 + 1; + } else { + y++; + } + + // knowledge? + if (lf != player) { + char knowstring[BUFLEN]; + switch (lorelev ){ + case PR_NOVICE: + strcpy(knowstring, "You have heard of this creature."); + break; + case PR_BEGINNER: + strcpy(knowstring, "You know a little about this creature."); + break; + case PR_ADEPT: + strcpy(knowstring, "You are fairly knowledgable about this creature."); + break; + case PR_SKILLED: + strcpy(knowstring, "You have studied this creature in depth."); + break; + case PR_EXPERT: + strcpy(knowstring, "You are an expert on this creature."); + break; + case PR_MASTER: + strcpy(knowstring, "You are an absolute authority on this creature."); + break; + default: + strcpy(knowstring, ""); + break; + } + + if (strlen(knowstring)) { + setcol(mainwin, lorecol); + mvwprintw(mainwin, y, 0, "%s", knowstring); + unsetcol(mainwin, lorecol); + y++; + } + + // extra info from lore? + if (lorelev >= PR_ADEPT) { + float rating; + // get threat rating + rating = comparelfs(player, lf); + setcol(mainwin, lorecol); + if (rating >= 4) { + sprintf(buf, "It is not a threat."); + } else if (rating >= 3) { + sprintf(buf, "You could defeat it very easily."); + } else if (rating >= 2) { + sprintf(buf, "You could defeat it quite easily."); + } else if (rating >= 1) { + sprintf(buf, "It would present an average challenge."); + } else if (rating >= 0.5) { + sprintf(buf, "It would be challenging to defeat."); + } else if (rating >= 0.25) { + sprintf(buf, "It would present a formidable opponent."); + } else if (rating >= 0.125) { + sprintf(buf, "It is very dangerous to you."); + } else { + sprintf(buf, "It is EXTREMELY dangerous to you."); + } + //mvwprintw(mainwin, y, 0, "Threat rating: %0.1f",comparelfs(player, lf)); + mvwprintw(mainwin, y, 0, "%s", buf); + unsetcol(mainwin, lorecol); + y++; + } + + } // obvious physical effects here. f = lfhasknownflag(lf, F_ASLEEP); @@ -6875,6 +7135,7 @@ void showlfstats(lifeform_t *lf, int showall) { char powerbuf[BUFLEN]; int power; int mpcost; + int castable = B_TRUE; // power power = getspellpower(lf, ot->id); @@ -6907,10 +7168,15 @@ void showlfstats(lifeform_t *lf, int showall) { } } + if ((mpcost > getmaxmp(lf)) || (power <= 0)) { + castable = B_FALSE; + } getspellname(ot->id, lf, spellname); - sprintf(buf, " %-4d%-26s%-15s%-13s%s",thislev, spellname, getschoolnameshort(getspellschool(ot->id)), powerbuf, mpbuf); + if (!castable) setcol(mainwin, C_RED); + sprintf(buf, " %-4d%-26s%-15s%-13s%s",thislev, spellname, getschoolnameshort(getspellschoolknown(lf, ot->id)), powerbuf, mpbuf); mvwprintw(mainwin, y, 0, "%s\n", buf); + if (!castable) unsetcol(mainwin, C_RED); anyfound = B_TRUE; if (downline(&y, h, "MAGIC", subheading, prompt, cmdchars, &ch)) { exitnow = B_TRUE; @@ -6925,6 +7191,7 @@ void showlfstats(lifeform_t *lf, int showall) { mvwprintw(mainwin, y, 0, "%s cannot cast any spells.", you(lf)); } } else if (mode == 'e') { + int nfound = 0; x = 0; // override // down a line. centre(mainwin, y, "EFFECTS"); @@ -6945,6 +7212,26 @@ void showlfstats(lifeform_t *lf, int showall) { y++; } + // spells + nfound = 0; + for (f = lf->flags->first ; f ; f = f->next) { + if (f->id == F_BOOSTSPELL) { + objecttype_t *sp; + sp = findot(f->val[0]); + if (sp) { + if (nfound == 0) { + mvwprintw(mainwin, y, 0, "%s %s the following spells active:", you(lf), + isplayer(lf) ? "have" : "has"); + y++; + } + mvwprintw(mainwin, y, 0, " - %s", sp->name); + y++; + nfound++; + } + } + } + if (nfound) y++; + // obvious physical effects first. f = lfhasknownflag(lf, F_BEINGSTONED); if (f) { @@ -6966,6 +7253,13 @@ void showlfstats(lifeform_t *lf, int showall) { y++; } + // flags which aren't really intrinsics + if (lfhasflag(lf, F_VEGETARIAN)) { + mvwprintw(mainwin, y, 0, "%s %s a vegetarian.", you(lf), isplayer(lf) ? "are" : "is"); + y++; + } + + // show intrinsics f = lfhasknownflag(lf, F_ATTRSET); if (f && (f->known)) { diff --git a/io.h b/io.h index 52799f0..5ca47ff 100644 --- a/io.h +++ b/io.h @@ -74,6 +74,7 @@ int drop(object_t *o, int count); char getchoice(prompt_t *prompt); char getchoicestr(prompt_t *prompt, int useshortcuts, int showlallatstart); int getkey(void); +enum COLOUR getskilllevelcolour(enum SKILLLEVEL slev); void handleinput(void); void doheading(WINDOW *win, int *y, int x, char *what); void initgfx(void); diff --git a/lf.c b/lf.c index 1ddc496..e941e1d 100644 --- a/lf.c +++ b/lf.c @@ -21,6 +21,7 @@ extern FILE *logfile; extern map_t *firstmap; extern race_t *firstrace, *lastrace; +extern raceclass_t *firstraceclass, *lastraceclass; extern job_t *firstjob, *lastjob; extern skill_t *firstskill, *lastskill; extern objecttype_t *objecttype; @@ -141,7 +142,6 @@ lifeform_t *real_addlf(cell_t *cell, enum RACE rid, int level, int controller) { a->los = NULL; // for ai - a->ignorecell = NULL; // avoid messages when equipping initial obs a->created = B_FALSE; @@ -182,7 +182,7 @@ lifeform_t *real_addlf(cell_t *cell, enum RACE rid, int level, int controller) { -race_t *addrace(enum RACE id, char *name, float weight, char glyph, int glyphcolour, enum MATERIAL mat) { +race_t *addrace(enum RACE id, char *name, float weight, char glyph, int glyphcolour, enum MATERIAL mat, enum RACECLASS raceclass) { race_t *a; assert(!findrace(id)); @@ -206,7 +206,8 @@ race_t *addrace(enum RACE id, char *name, float weight, char glyph, int glyphcol // props a->id = id; a->baseid = id; // default - + a->raceclass = findraceclass(raceclass); + a->material = findmaterial(mat); assert(a->material); a->name = strdup(name); @@ -218,6 +219,36 @@ race_t *addrace(enum RACE id, char *name, float weight, char glyph, int glyphcol return a; } +raceclass_t *addraceclass(enum RACECLASS id, char *name, char *pluralname, enum SKILL skill) { + raceclass_t *a; + + assert(!findraceclass(id)); + + // add to the end of the list + if (firstraceclass == NULL) { + firstraceclass = malloc(sizeof(raceclass_t)); + a = firstraceclass; + a->prev = NULL; + } else { + // go to end of list + a = lastraceclass; + a->next = malloc(sizeof(raceclass_t)); + a->next->prev = a; + a = a->next; + } + lastraceclass = a; + a->next = NULL; + + + // props + a->id = id; + a->name = strdup(name); + a->pluralname = strdup(pluralname); + a->skill = skill; + + return a; +} + skill_t *addskill(enum SKILL id, char *name, char *desc) { skill_t *a; @@ -302,6 +333,27 @@ void adjustdamlf(lifeform_t *lf, int *amt, enum DAMTYPE damtype) { if (*amt < 0) *amt = 0; } +void makepeaceful(lifeform_t *who) { + char lfname[BUFLEN]; + + getlfname(who, lfname); + if (lfhasflag(who, F_DEBUG)) { + msg("Making %s friendly.",lfname); + } + + if (lfhasflag(who, F_HOSTILE)) { + if (cansee(player, who)) { + char lfname[BUFLEN]; + getlfname(who, lfname); + msg("%s calms down.", lfname); + } + } + + killflagsofid(who->flags, F_HOSTILE); + killflagsofid(who->flags, F_TARGET); // stop targetting anyone + +} + lifeform_t *makezombie(object_t *o) { flag_t *f; race_t *r; @@ -413,6 +465,40 @@ int areenemies(lifeform_t *lf1, lifeform_t *lf2) { return B_TRUE; } +void applywalkdam(lifeform_t *lf, int dam, enum DAMTYPE damtype, object_t *o) { + flag_t *fromlfflag; + lifeform_t *fromlf = NULL; + char damstring[BUFLEN],buf[BUFLEN]; + + getobname(o, buf, o->amt); + + fromlfflag = hasflag(o->flags, F_CREATEDBY); + if (fromlfflag) { + sprintf(damstring, "%s^created by %s",buf, fromlfflag->text); + } else { + strcpy(damstring, buf); + } + + dam = losehp(lf, dam, damtype, fromlf, damstring); + if (dam > 0) { + if (damtype == DT_POISONGAS) { + if (isplayer(lf) || cansee(player, lf)) { + char lfname[BUFLEN]; + getlfname(lf, lfname); + msg("%s choke%s on %s!", lfname, isplayer(lf) ? "" : "s", buf); + } + } else { + if (isplayer(lf)) { + msg("%s %ss you!", buf, getattackverb(NULL, NULL, damtype, dam,lf->maxhp)); + } else if (cansee(player, lf)) { + char lfname[BUFLEN]; + getlfname(lf, lfname); + msg("%s %ss %s!", buf, getattackverb(NULL, NULL, damtype, dam,lf->maxhp), lfname); + } + } + } +} + int areallies(lifeform_t *lf1, lifeform_t *lf2) { if (getallegiance(lf1) == getallegiance(lf2)) { if (isplayer(lf1) || isplayer(lf2)) { @@ -600,6 +686,11 @@ int appearsrandomly(enum RACE rid) { void bleed(lifeform_t *lf) { flag_t *f; char obname[BUFLEN]; + + if (lf->cell->type->solid) { + return; + } + f = lfhasflag(lf, F_BLOODOB); if (f) { if (f->text) { @@ -623,8 +714,6 @@ int calcxp(lifeform_t *lf) { float offense = 0; float defence = 0; float spells = 0; - object_t *o; - obpile_t *op; flag_t *f; float avgdam = 0; int db = B_FALSE; @@ -653,82 +742,10 @@ int calcxp(lifeform_t *lf) { // attack // - get average attack damage - op = addobpile(NULL, NULL); - avgdam = 0; - for (f = lf->race->flags->first ; f ; f = f->next) { - if (f->id == F_HASATTACK) { - int min,max; - float thisavg; - float acc; - flag_t *of; - - objecttype_t *ot; - ot = findot(f->val[0]); - o = addob(op, ot->name); - - getdamrange(f, &min,&max); - thisavg = ((float)min + (float)max) / 2.0; - - // confers anything? - for (of = o->flags->first ; of ; of = of->next) { - if (of->id == F_HITCONFER) { - thisavg += 10; - } - } - - // modify for accuracy - acc = getlfaccuracy(lf, o); - thisavg = pctof(acc, thisavg); - - avgdam += thisavg; - if (db) { - char obname[BUFLEN]; - getobname(o,obname,1); - if (db) dblog("calcxp: %s: == %d-%d dam, avg is %0.1f",obname, min, max, thisavg); - } - } else if (f->id == F_STARTOB) { - object_t *o; - int min,max; - float thisavg; - float acc; - flag_t *of; - obpile_t *op; - - op = addobpile(NULL,NULL); - - o = addob(op, f->text); - - getdamrange(hasflag(o->flags, F_DAM), &min,&max); - thisavg = ((float)min + (float)max) / 2.0; - - // confers anything? - for (of = o->flags->first ; of ; of = of->next) { - if (of->id == F_HITCONFER) { - thisavg += 10; - } - } - - // modify for accuracy - acc = getlfaccuracy(lf, o); - thisavg = pctof(acc, thisavg); - - avgdam += thisavg; - if (db) { - char obname[BUFLEN]; - getobname(o,obname,1); - if (db) dblog("calcxp: %s: == %d-%d dam, avg is %0.1f",obname, min, max, thisavg); - } - - killobpile(op); - } - } - - + avgdam = getavgdam(lf, B_TRUE); if (db) dblog("calcxp: avg damage dealt is %0.1f",avgdam); - if (op) killobpile(op); - // defense // -- hitdice f = lfhasflag(lf, F_HITDICE); @@ -964,18 +981,37 @@ int cancast(lifeform_t *lf, enum OBTYPE oid, int *mpcost) { } int candrink(lifeform_t *lf, object_t *o) { - if (!isdrinkable(o)) { + // undead won't drink + if (getraceclass(lf) == RC_UNDEAD) { + reason = E_UNDEAD; return B_FALSE; } + if (!isdrinkable(o)) { + reason = E_WRONGOBTYPE; + return B_FALSE; + } + reason = E_OK; return B_TRUE; } // if false, returns why you can't eat it in 'reason' int caneat(lifeform_t *lf, object_t *o) { + // undead won't eat + if (getraceclass(lf) == RC_UNDEAD) { + reason = E_UNDEAD; + return B_FALSE; + } + if (!isedible(o)) { reason = E_WRONGOBTYPE; return B_FALSE; } + + // ai won't eat bad food + if (!isplayer(lf) && isrotting(o)) { + reason = E_WONT; + return B_FALSE; + } if ((o->type->id == OT_CORPSE) || (o->type->id == OT_HEAD)) { flag_t *f; f = hasflag(o->flags, F_CORPSEOF); @@ -994,6 +1030,11 @@ int caneat(lifeform_t *lf, object_t *o) { } } + if (lfhasflag(lf, F_VEGETARIAN) && (o->material->id == MT_FLESH)) { + reason = E_VEGETARIAN; + return B_FALSE; + } + // ai lifeforms won't eat tainted food if (!isplayer(lf)) { if (hasflag(o->flags, F_TAINTED)) { @@ -1350,44 +1391,8 @@ int canweild(lifeform_t *lf, object_t *o) { if (o) { for (f = o->flags->first ; f; f = f->next) { if (f->id == F_ATTREQ) { - enum ATTRIB att; - int brackneeded; - int myatt; - int mybrack; - enum ERROR why; - att = f->val[0]; - brackneeded = f->val[1]; - - // modify for masterwork - if (hasflag(o->flags, F_MASTERWORK)) { - brackneeded--; - if (brackneeded < 0) brackneeded = 0; - } - - myatt = getattr(lf, att); - - switch (att) { - case A_DEX: - mybrack = getdexname(myatt, NULL); - why = E_LOWDEX; - break; - case A_CON: - mybrack = getconname(myatt, NULL); - why = E_LOWCON; - break; - case A_IQ: - mybrack = getiqname(myatt, NULL); - why = E_LOWIQ; - break; - case A_STR: - mybrack = getstrname(myatt, NULL); - why = E_LOWSTR; - break; - case A_NONE: - break; - } - if (mybrack < brackneeded) { - reason = why; + // meetsattreq will set 'reason' for us. + if (!meetsattreq(lf, f, o)) { return B_FALSE; } } else if (f->id == F_TWOHANDED) { @@ -1485,7 +1490,7 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar if (isplayer(lf) && (power > 1) && hasflag(sp->flags, F_VARPOWER)) { if (!hasactivespell(lf, sp->id)) { int max; - char buf[BUFLEN]; + char buf[BUFLEN],desc[BUFLEN]; int i; char ch; // ask what power @@ -1494,10 +1499,18 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar initprompt(&prompt, buf); for (i = 1; i <= max; i++) { sprintf(buf, "Power %s (%d MP)", roman(i), getmpcost(lf, sid) * i); + getvarpowerspelldesc(sp->id, i, desc); + if (strlen(desc)) { + strcat(buf, "\t"); + strcat(buf, desc); + } addchoice(&prompt, '0' + i, buf, buf, NULL); } ch = getchoice(&prompt); power = ch - '0'; + + // modify cost + cost *= i; } } @@ -1525,7 +1538,9 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar getlfname(lf, lfname); f = lfhasflag(lf,F_SPELLCASTTEXT); if (f) { - msg("%s %s.", lfname, f->text); + if (strlen(f->text)) { + msg("%s %s.", lfname, f->text); + } } else { msg("%s casts a spell.", lfname); } @@ -1545,6 +1560,10 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar willflag->val[1] = -1; } } + + // stop hiding + killflagsofid(lf->flags, F_HIDING); + return rv; } @@ -1586,6 +1605,39 @@ void checkxp(enum RACE rid) { } */ +// how dangerous is lf2 to lf1? +// < 0 = harder +// > 0 = easier +float comparelfs(lifeform_t *lf1, lifeform_t *lf2) { + float avgdam[2]; + lifeform_t *lf[2]; + float turnstokill[2]; + int i; + float ratio; + lf[0] = lf1; + lf[1] = lf2; + for (i = 0; i < 2; i++) { + float otherevasion; + // get avg damage + avgdam[i] = getavgdam(lf[i], B_FALSE); + // mod this by other lf's evasion + otherevasion = ((float)getevasion(lf[1-i])); + avgdam[i] -= pctof(otherevasion, avgdam[i]); + // divide other lf's hit points by this lf's avg dam + if (avgdam[i] == 0) { + turnstokill[1-i] = 9999; + } else { + turnstokill[1-i] = (float)lf[1-i]->hp / avgdam[i]; + } + } + + // compare turnstokill values + ratio = (turnstokill[0] / turnstokill[1]); + + + return ratio; +} + int countmoney(lifeform_t *lf) { object_t *o; int amt = 0; @@ -1967,45 +2019,85 @@ void dumpxp(void) { } } -void dumpmonsters(void) { +// dump which level random things will appear at +void dumplev(void) { int i; race_t *r; + objecttype_t *ot; flag_t *f; dblog("Start monster dump"); dblog("------------------\n"); // 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, 5); - getrarity(i, &min, &max, 5); + getrarity(i-1, &prevmin, &prevmax, RARITYVARIANCELF); + getrarity(i, &min, &max, RARITYVARIANCELF); fprintf(logfile, "Dlev %d (rar >= %d): ",i,min); for (r = firstrace ; r; r = r->next) { int rarity = 0; f = hasflag(r->flags, F_RARITY); if (f) { rarity = f->val[1]; - } - // ok this lev? - if ((rarity >= min) && (rarity <= max)) { - char buf[BUFLEN]; - strcpy(buf, ""); - // ok on previous lev too? - if ((rarity >= prevmin) && (rarity <= prevmax)) { - // only print if dlev is 1 - if (i == 1) { + // ok this lev? + if ((rarity >= min) && (rarity <= max)) { + char buf[BUFLEN]; + strcpy(buf, ""); + // ok on previous lev too? + if ((rarity >= prevmin) && (rarity <= prevmax)) { + // only print if dlev is 1 + if (i == 1) { + sprintf(buf, "%s, ", r->name); + } + } else { + // ie. new mosnter for this lev + //sprintf(buf, "*%s*, ", r->name); + //makeuppercase(buf); sprintf(buf, "%s, ", r->name); - } - } else { - // ie. new mosnter for this lev - //sprintf(buf, "*%s*, ", r->name); - //makeuppercase(buf); - sprintf(buf, "%s, ", r->name); + } + fprintf(logfile, "%s", buf); } - fprintf(logfile, "%s", buf); } } fprintf(logfile, "\n"); } + + + dblog("Start object dump"); + dblog("------------------\n"); + // 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); + getrarity(i, &min, &max, RARITYVARIANCEOB); + fprintf(logfile, "Dlev %d (rar >= %d): ",i,min); + for (ot = objecttype ; ot; ot = ot->next) { + int rarity = 0; + f = hasflag(ot->flags, F_RARITY); + if (f) { + rarity = f->val[1]; + // ok this lev? + if ((rarity >= min) && (rarity <= max)) { + char buf[BUFLEN]; + strcpy(buf, ""); + // ok on previous lev too? + if ((rarity >= prevmin) && (rarity <= prevmax)) { + // only print if dlev is 1 + if (i == 1) { + sprintf(buf, "%s, ", ot->name); + } + } else { + // ie. new object for this lev + //sprintf(buf, "*%s*, ", r->name); + //makeuppercase(buf); + sprintf(buf, "%s, ", ot->name); + } + fprintf(logfile, "%s", buf); + } + } + } + fprintf(logfile, "\n"); + } + fflush(logfile); } @@ -2026,7 +2118,15 @@ int eat(lifeform_t *lf, object_t *o) { if (drinking) { if (!candrink(lf, o)) { if (isplayer(lf)) { - msg("You can't drink that!"); + switch (reason) { + case E_UNDEAD: + msg("You are undead and don't need to drink."); + break; + default: + case E_WRONGOBTYPE: + msg("You can't drink that!"); + break; + } } return B_TRUE; } @@ -2037,6 +2137,12 @@ int eat(lifeform_t *lf, object_t *o) { case E_NOCANNIBUL: msg("The idea of eating your own race is abhorrent to you."); break; + case E_UNDEAD: + msg("You are undead and don't need to eat."); + break; + case E_VEGETARIAN: + msg("The thought of eating flesh disgusts you."); + break; case E_WRONGOBTYPE: default: msg("You can't eat that!"); @@ -2335,8 +2441,7 @@ void enhanceskills(lifeform_t *lf) { ch = 'a'; for (sk = firstskill ; sk ; sk = sk->next) { - // TODO: && canlearn(player, sk->id) - if (!getskill(player, sk->id)) { + if (!getskill(player, sk->id) && canlearn(player, sk->id)) { char buf[BUFLEN]; sprintf(buf, "%-18s(%s)", getskillname(sk->id), getskilldesc(sk->id)); addchoice(&prompt, ch++, getskillname(sk->id), buf, sk); @@ -2562,6 +2667,16 @@ race_t *findracebyname(char *name) { return NULL; } +raceclass_t *findraceclass(enum RACECLASS id) { + raceclass_t *r; + for (r = firstraceclass; r ; r = r->next) { + if (r->id == id) { + return r; + } + } + + return NULL; +} skill_t *findskill(enum SKILL id) { @@ -2769,6 +2884,7 @@ void gainhp(lifeform_t *lf, int amt) { void gainlevel(lifeform_t *lf) { flag_t *f; race_t *mybaserace; + int skillready = B_FALSE; //int preready,postready; if (isplayer(lf)) { @@ -2783,13 +2899,6 @@ void gainlevel(lifeform_t *lf) { lf->newlevel++; - if (isplayer(lf)) { - msg("You feel ready for a training session!"); - more(); - } else if (cansee(player, lf)) { - //getlfname(lf, buf); - //msg("%s looks more confident!",buf); - } // stat gain (str etc) every 3 levels if ((lf->newlevel % 3) == 0) { @@ -2804,10 +2913,11 @@ void gainlevel(lifeform_t *lf) { } // skill gain - // new skill at level 3, 5, 7, etc - if (((lf->newlevel - 1) % 2) == 0) { + // new skill at level 2, 4, 6, etc + //if ((lf->newlevel % 2) == 0) { lf->skillpoints++; - } + skillready = B_TRUE; +// } //if (postready && !preready) { /* @@ -2816,6 +2926,18 @@ void gainlevel(lifeform_t *lf) { } */ + if (isplayer(lf)) { + if (skillready) { + msg("You feel ready to learn a new skill!"); + } else { + msg("You feel ready for a training session!"); + } + more(); + } else if (cansee(player, lf)) { + //getlfname(lf, buf); + //msg("%s looks more confident!",buf); + } + // you can now re-attempt identification of objects killflagsofid(lf->flags, F_FAILEDINSPECT); @@ -3091,6 +3213,154 @@ int real_getattr(lifeform_t *lf, enum ATTRIB attr, int ignoreattrset) { return val; } +// returns average damage per turn, modified by accuracy +int getavgdam(lifeform_t *lf, int forxp) { + obpile_t *op; + int avgdam = 0; + int db = B_FALSE; + flag_t *f; + + if (lfhasflag(lf, F_DEBUG)) { + db = B_TRUE; + } + + op = addobpile(NULL, NULL); + for (f = lf->race->flags->first ; f ; f = f->next) { + if (f->id == F_HASATTACK) { + int min,max; + float thisavg; + object_t *o; + float acc; + flag_t *of; + + objecttype_t *ot; + ot = findot(f->val[0]); + o = addob(op, ot->name); + + getdamrange(f, &min,&max); + thisavg = ((float)min + (float)max) / 2.0; + + // confers anything? + for (of = o->flags->first ; of ; of = of->next) { + if (of->id == F_HITCONFER) { + flag_t *valflag; + int maxlifetime; + // get max lifetime + gethitconferlifetime(f->text, NULL, &maxlifetime); + valflag = hasflag(o->flags, F_HITCONFERVALS); + assert(valflag); + // assign xp based on what is conferred + switch (of->val[0]) { + case F_POISONED: + // sum up poison power + thisavg += (maxlifetime * valflag->val[1]); + break; + default: + thisavg += 10; + break; + } + } + } + + // modify for accuracy + acc = getlfaccuracy(lf, o); + thisavg = pctof(acc, thisavg); + + avgdam += thisavg; + if (db) { + char obname[BUFLEN]; + getobname(o,obname,1); + if (db) dblog("getavgdam: %s: == %d-%d dam, avg is %0.1f",obname, min, max, thisavg); + } + } else if (forxp && (f->id == F_STARTOB)) { + object_t *o; + int min,max; + float thisavg; + float acc; + flag_t *of; + obpile_t *op2; + + op2 = addobpile(NULL,NULL); + + o = addob(op2, f->text); + + getdamrange(hasflag(o->flags, F_DAM), &min,&max); + thisavg = ((float)min + (float)max) / 2.0; + + // confers anything? + for (of = o->flags->first ; of ; of = of->next) { + if (of->id == F_HITCONFER) { + thisavg += 10; + } + } + + // modify for accuracy + acc = getlfaccuracy(lf, o); + thisavg = pctof(acc, thisavg); + + avgdam += thisavg; + if (db) { + char obname[BUFLEN]; + getobname(o,obname,1); + if (db) dblog("getavgdam: %s: == %d-%d dam, avg is %0.1f",obname, min, max, thisavg); + } + + killobpile(op2); + } + } + + + if (!forxp) { + object_t *w; + // current weapon... + w = getweapon(lf); + if (w) { + float thisavg,acc; + float dammod; + int bonus = 0,mindam,maxdam; + // damage + f = hasflag(w->flags, F_BONUS); + if (f) { + // only tell player about bonuses if they are known.! + bonus = f->val[0]; + } else { + bonus = 0; + } + + f = hasflag(w->flags, F_DAM); + if (f) { + getdamrange(f, &mindam, &maxdam); + } else { + mindam = 0; + maxdam = 0; + } + + mindam += bonus; + maxdam += bonus; + + dammod = getstrdammod(lf); + // apply damage mod for strength + if (!hasflag(w->flags, F_NOSTRDAMMOD) && !lfhasflag(lf, F_NOSTRDAMMOD)) { + mindam = (int)((float)mindam * dammod); + maxdam = (int)((float)maxdam * dammod); + } + + if (mindam < 0) mindam = 0; + if (maxdam < 0) maxdam = 0; + + thisavg = (((float)(mindam + maxdam)) / 2); + acc = getlfaccuracy(lf, w); + thisavg = pctof(acc, thisavg); + + avgdam += thisavg; + } + } + + if (op) killobpile(op); + + return (int)avgdam; +} + int getevasion(lifeform_t *lf) { object_t *o; flag_t *f; @@ -3136,6 +3406,12 @@ int getevasion(lifeform_t *lf) { if (ev < 0) ev = 0; } + // modify for stickiness + if (hasobwithflag(lf->cell->obpile, F_RESTRICTMOVEMENT)) { + ev -= 50; + } + if (ev < 0) ev = 0; + // modify for blindness if (isblind(lf)) { ev -= 15; @@ -3352,6 +3628,34 @@ int gethearingrange(lifeform_t *lf) { return range; } +int gethidemodifier(lifeform_t *lf) { + int modifier = 0; + + reason = E_OK; + if (!safetorest(lf)) { + if (getskill(lf, SK_STEALTH) == PR_EXPERT) { + // can still hide, but with a modifier + modifier = -4; + } else if (getskill(lf, SK_STEALTH) == PR_MASTER) { + // can still hide, but with a modifier + modifier = -2; + } else { + reason = E_IMPOSSIBLE; + modifier = -100; // special case + } + } + + // no stealth skill? + if (!getskill(lf, SK_STEALTH)) { + modifier = -5; + } + return modifier; +} + +int gethitdice(lifeform_t *lf) { + return (lf->maxhp / 4); +} + int gethppct(lifeform_t *lf) { float pct; pct = (int)(((float)lf->hp / (float)lf->maxhp) * 100); @@ -3477,6 +3781,13 @@ int getlfaccuracy(lifeform_t *lf, object_t *wep) { acc -= 25; } + // modify for stickiness + if (gamemode == GM_GAMESTARTED) { + if (hasobwithflag(lf->cell->obpile, F_RESTRICTMOVEMENT)) { + acc -= 25; + } + } + if (acc < 0) acc = 0; return acc; } @@ -3543,6 +3854,26 @@ char *getlfconditionname(enum LFCONDITION cond) { return "?unknown condition?"; } +object_t *getouterequippedob(lifeform_t *lf, enum BODYPART bp) { + object_t *o; + switch (bp) { + case BP_RIGHTHAND: + case BP_LEFTHAND: + o = getequippedob(lf->pack, BP_HANDS); + if (o) return o; + else return getequippedob(lf->pack, bp); + break; + case BP_BODY: + o = getequippedob(lf->pack, BP_SHOULDERS); + if (o) return o; + else return getequippedob(lf->pack, bp); + break; + default: + break; + } + return getequippedob(lf->pack, bp); +} + // return the healthiest possible hurt condition that 'lf' will // recognise when looking at someone else. // @@ -3616,6 +3947,16 @@ enum MATERIAL getlfmaterial(lifeform_t *lf) { return lf->race->material->id; } +enum SKILLLEVEL getlorelevel(lifeform_t *lf, enum RACECLASS rcid) { + enum SKILLLEVEL slev = PR_INEPT; + raceclass_t *rc; + rc = findraceclass(rcid); + if (rc) { + slev = getskill(lf, rc->skill); + } + return slev; +} + float getmaxcarryweight(lifeform_t *lf) { float max; float mod; @@ -3697,7 +4038,7 @@ int getmaxmp(lifeform_t *lf) { activemp = 0; for (f = lf->flags->first ; f ; f = f->next) { if (f->id == F_BOOSTSPELL) { - activemp += getmpcost(NULL, f->val[0]); + activemp += f->val[1]; } } maxmp -= activemp; @@ -3749,6 +4090,7 @@ int getvisrange(lifeform_t *lf) { int getmovespeed(lifeform_t *lf) { int speed = 0; + object_t *o; flag_t *f; f = lfhasflag(lf, F_MOVESPEED); @@ -3787,9 +4129,15 @@ int getmovespeed(lifeform_t *lf) { break; } - if (speed < 1) speed = 1; + for (o = lf->cell->obpile->first ; o ; o = o->next) { + f = hasflag(o->flags, F_REDUCEMOVEMENT); + if (f) { + speed *= f->val[0]; + } + } + return speed; } @@ -4053,6 +4401,10 @@ char *getpoisonname(enum POISONTYPE ptype) { return ""; } +int getraceclass(lifeform_t *lf) { + return lf->race->raceclass->id; +} + int getracerarity(enum RACE rid) { race_t *r; int rarity = -1; @@ -4151,7 +4503,7 @@ race_t *getrandomrace(map_t *map, int forcedepth) { } } - getrarity(depth, &raritymin, &raritymax, 5); + getrarity(depth, &raritymin, &raritymax, RARITYVARIANCELF); if (db) dblog("finding random lf with rarity val %d-%d\n",raritymin,raritymax); @@ -4481,6 +4833,14 @@ char *getskilllevelname(enum SKILLLEVEL sl) { // get throw speed (ie. damage multiplier) // based on strength. +// +// cube the number to get km/h. +// ie. 1 = 1km/h +// ie. 2 = 16km/h +// ie. 3 = 27km/h +// ie. 4 = 64km/h +// ie. 5 = 125km/h +// ie. 10 = 1000km/h int getthrowspeed(int str) { enum STRBRACKET sb; int speed = 0; @@ -4488,23 +4848,25 @@ int getthrowspeed(int str) { switch (sb) { case ST_HELPLESS: case ST_FEEBLE: - speed = 0; + speed = 1; break; case ST_VWEAK: case ST_WEAK: - speed = 1; - break; - default: - case ST_AVERAGE: - case ST_STRONG: speed = 2; break; - case ST_MIGHTY: + case ST_AVERAGE: speed = 3; break; - case ST_TITANIC: + case ST_STRONG: speed = 4; break; + case ST_MIGHTY: + speed = 5; + break; + default: + case ST_TITANIC: + speed = 6; + break; // gun is 10 } return speed; @@ -4526,7 +4888,7 @@ long getxpforlev(int level) { long needxp = 0; // 2.8 float multiplier = 10; - float constant = 3.8; + float constant = 3.5; // no xp needed for level 1 /* @@ -4817,7 +5179,7 @@ int giveskill(lifeform_t *lf, enum SKILL id) { if (id == SK_ATHLETICS) { newf = addflag(lf->flags, F_CANWILL, OT_A_SPRINT, NA, NA, NULL); newf->lifetime = FROMJOB; - } else if (id == SK_RESEARCH) { + } else if (id == SK_LORE_ARCANA) { newf = addflag(lf->flags, F_CANWILL, OT_A_INSPECT, NA, NA, NULL); newf->lifetime = FROMJOB; } @@ -4832,6 +5194,13 @@ int giveskill(lifeform_t *lf, enum SKILL id) { newf = addflag(lf->flags, F_CANWILL, OT_A_JUMP, NA, NA, NULL); newf->lifetime = FROMJOB; } + } else if (id == SK_FIRSTAID) { + if ((gamemode == GM_GAMESTARTED) && isplayer(lf)) { + if (f->val[1] == PR_ADEPT) { + msg("You can now recgonise when poison is potentially fatal."); + statdirty = B_TRUE; + } + } } else if (id == SK_LISTEN) { if ((gamemode == GM_GAMESTARTED) && isplayer(lf)) { if (f->val[1] == PR_BEGINNER) { @@ -4877,6 +5246,37 @@ int giveskill(lifeform_t *lf, enum SKILL id) { if (!lfhasflagval(lf, F_CANCAST, OT_S_MINDSCAN, NA, NA, NULL)) { addflag(lf->flags, F_CANCAST, OT_S_MINDSCAN, NA, NA, NULL); } + } else if (isloreskill(id) && (gamemode == GM_GAMESTARTED) && isplayer(lf)) { + raceclass_t *rc; + // find raceclass for this one + for (rc = firstraceclass ; rc ; rc = rc->next) { + if (rc->skill == id) { + break; + } + } + + if (rc) { + // announce. + if (f->val[1] >= PR_MASTER) { + msg("You now know everything there is to know about %s.", rc->pluralname); + } else if (f->val[1] >= PR_EXPERT) { + msg("You now deal extra damage to %s.", rc->pluralname); + } else if (f->val[1] >= PR_SKILLED) { + msg("You can now anticipate how %s will react.", rc->pluralname); + } else if (f->val[1] >= PR_ADEPT) { + msg("You can now determine how dangerous %s are.", rc->pluralname); + } else if (f->val[1] >= PR_BEGINNER) { + msg("You can now determine how much damage %s will deal.", rc->pluralname); + } else if (f->val[1] >= PR_NOVICE) { + msg("You now know basic information about %s.", rc->pluralname); + } + } + + } + + if ((gamemode == GM_GAMESTARTED) && statdirty) { + // redraw it right away. + drawstatus(); } return B_FALSE; @@ -5572,7 +5972,7 @@ void initjobs(void) { addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "10 blessed potions of experience"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "ring of miracles"); addflag(lastjob->flags, F_STARTSKILL, SK_SPELLCASTING, PR_MASTER, NA, NULL); - addflag(lastjob->flags, F_STARTSKILL, SK_RESEARCH, PR_NOVICE, NA, NULL); + addflag(lastjob->flags, F_STARTSKILL, SK_LORE_ARCANA, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_SS_DEATH, PR_MASTER, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_SS_TRANSLOCATION, PR_MASTER, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_SS_DIVINATION, PR_MASTER, NA, NULL); @@ -5605,6 +6005,8 @@ void initjobs(void) { addflag(lastjob->flags, F_STARTSKILL, SK_SPELLCASTING, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_TECHUSAGE, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_ARMOUR, PR_NOVICE, 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); for (i = 1; i < MAXSKILLS; i++) { addflag(lastjob->flags, F_CANLEARN, i, NA, NA, NULL); } @@ -5649,6 +6051,7 @@ 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_CANLEARN, SK_LISTEN, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_LOCKPICKING, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_STEALTH, NA, NA, NULL); @@ -5659,6 +6062,7 @@ void initjobs(void) { addflag(lastjob->flags, F_CANLEARN, SK_POLEARMS, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_STAVES, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_UNARMED, NA, NA, NULL); + addflag(lastjob->flags, F_LEVABIL, 4, OT_A_CHARGE, 3, NULL); addflag(lastjob->flags, F_LEVABIL, 7, OT_A_WARCRY, NA, NULL); addflag(lastjob->flags, F_LEVABIL, 10, OT_A_HURRICANESTRIKE, 5, NULL); addjob(J_COMMANDO, "Commando"); @@ -5688,6 +6092,30 @@ void initjobs(void) { addflag(lastjob->flags, F_CANLEARN, SK_TECHUSAGE, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_SHORTBLADES, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_UNARMED, NA, NA, NULL); + addjob(J_DRUID, "Druid"); + addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "quarterstaff"); + addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "robe"); + addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "pair of sandals"); + addflag(lastjob->flags, F_HITDICE, 1, 1, NA, NULL); // low hp + addflag(lastjob->flags, F_MPDICE, 1, 1, NA, NULL); + addflag(lastjob->flags, F_STARTATT, A_STR, ST_AVERAGE, NA, NULL); + addflag(lastjob->flags, F_STARTATT, A_DEX, DX_AVERAGE, NA, NULL); + addflag(lastjob->flags, F_STARTATT, A_IQ, IQ_ENLIGHTENED, NA, NULL); + // skills + addflag(lastjob->flags, F_STARTSKILL, SK_LORE_NATURE, PR_ADEPT, NA, NULL); + addflag(lastjob->flags, F_STARTSKILL, SK_STAVES, PR_NOVICE, NA, NULL); + // learnable skills + addflag(lastjob->flags, F_CANLEARN, SK_LISTEN, NA, NA, NULL); + addflag(lastjob->flags, F_CANLEARN, SK_FIRSTAID, NA, NA, NULL); + // gained skills + addflag(lastjob->flags, F_LEVFLAG, 3, F_DETECTMAGIC, B_TRUE, NULL); + addflag(lastjob->flags, F_LEVFLAG, 7, F_DETECTAURAS, B_TRUE, NULL); + addflag(lastjob->flags, F_LEVFLAG, 10, F_CONTROL, B_TRUE, NULL); + // abilities + mayusespellschool(lastjob->flags, SS_NATURE, F_CANCAST); + addflag(lastjob->flags, F_HASPET, NA, NA, NA, "young wolf"); + addflag(lastjob->flags, F_VEGETARIAN, B_TRUE, NA, NA, NULL); + addjob(J_PLUMBER, "Plumber"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "spanner"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "10 gold coins"); @@ -5716,10 +6144,11 @@ void initjobs(void) { addflag(lastjob->flags, F_STARTSKILL, SK_SHIELDS, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_SHORTBLADES, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_LONGBLADES, PR_NOVICE, NA, NULL); + addflag(lastjob->flags, F_STARTSKILL, SK_LORE_HUMANOID, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_ATHLETICS, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_LISTEN, NA, NA, NULL); - addflag(lastjob->flags, F_CANLEARN, SK_MAGITEMUSAGE, NA, NA, NULL); - addflag(lastjob->flags, F_CANLEARN, SK_RESEARCH, NA, NA, NULL); + addflag(lastjob->flags, F_CANLEARN, SK_CHANNELING, NA, NA, NULL); + addflag(lastjob->flags, F_CANLEARN, SK_LORE_ARCANA, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_POLEARMS, NA, NA, NULL); addjob(J_PIRATE, "Pirate"); @@ -5749,8 +6178,8 @@ void initjobs(void) { 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); - addflag(lastjob->flags, F_CANLEARN, SK_MAGITEMUSAGE, NA, NA, NULL); - addflag(lastjob->flags, F_CANLEARN, SK_RESEARCH, NA, NA, NULL); + addflag(lastjob->flags, F_CANLEARN, SK_CHANNELING, NA, NA, NULL); + addflag(lastjob->flags, F_CANLEARN, SK_LORE_ARCANA, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_POLEARMS, NA, NA, NULL); // TODO: in-built "hook" weapon ? but have to replace 'fists' somehow. // maybe hardcode after character creation. @@ -5771,7 +6200,7 @@ void initjobs(void) { 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_CANLEARN, SK_ATHLETICS, NA, NA, NULL); - addflag(lastjob->flags, F_CANLEARN, SK_MAGITEMUSAGE, NA, NA, NULL); + addflag(lastjob->flags, F_CANLEARN, SK_CHANNELING, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_STAVES, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_UNARMED, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_SS_DIVINATION, NA, NA, NULL); @@ -5779,6 +6208,7 @@ void initjobs(void) { addflag(lastjob->flags, F_CANLEARN, SK_SS_MODIFICATION, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_SS_MENTAL, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_SS_TRANSLOCATION, NA, NA, NULL); + addflag(lastjob->flags, F_CANLEARN, SK_LORE_ARCANA, NA, NA, NULL); addjob(J_WIZARD, "Wizard"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "knife"); @@ -5799,7 +6229,7 @@ void initjobs(void) { addflag(lastjob->flags, F_STARTOBCLASS, 100, OC_BOOK, NA, NULL); addflag(lastjob->flags, F_ENDIFMONSTER, NA, NA, NA, NULL); addflag(lastjob->flags, F_HITDICE, 1, 1, NA, NULL); // low hp - addflag(lastjob->flags, F_MPDICE, 2, 1, NA, NULL); + addflag(lastjob->flags, F_MPDICE, 1, 1, NA, NULL); addflag(lastjob->flags, F_STARTATT, A_STR, ST_WEAK, NA, NULL); addflag(lastjob->flags, F_STARTATT, A_DEX, DX_AVERAGE, NA, NULL); addflag(lastjob->flags, F_STARTATT, A_IQ, IQ_ENLIGHTENED, NA, NULL); @@ -5807,13 +6237,13 @@ void initjobs(void) { addflag(lastjob->flags, F_RESTHEALTIME, 6, NA, NA, NULL); //addflag(lastjob->flags, F_MPREGEN, 1, SK_SPELLCASTING, 35, NULL); // can detect magic objects - addflag(lastjob->flags, F_STARTSKILL, SK_RESEARCH, PR_BEGINNER, NA, NULL); + addflag(lastjob->flags, F_STARTSKILL, SK_LORE_ARCANA, PR_BEGINNER, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_SPELLCASTING, PR_NOVICE, NA, NULL); - addflag(lastjob->flags, F_STARTSKILL, SK_MAGITEMUSAGE, 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); addflag(lastjob->flags, F_STARTSKILL, SK_SS_WILD, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_LISTEN, NA, NA, NULL); - addflag(lastjob->flags, F_CANLEARN, SK_MAGITEMUSAGE, NA, NA, NULL); + addflag(lastjob->flags, F_CANLEARN, SK_CHANNELING, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_SHORTBLADES, NA, NA, NULL); // wizards can learn all spell schools except psionics and allomancy addflag(lastjob->flags, F_CANLEARN, SK_SS_AIR, NA, NA, NULL); @@ -5825,11 +6255,13 @@ void initjobs(void) { addflag(lastjob->flags, F_CANLEARN, SK_SS_MODIFICATION, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_SS_SUMMONING, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_SS_TRANSLOCATION, NA, NA, NULL); + addflag(lastjob->flags, F_CANLEARN, SK_LORE_DEMONS, NA, NA, NULL); + addflag(lastjob->flags, F_CANLEARN, SK_LORE_UNDEAD, NA, NA, NULL); // gained skills addflag(lastjob->flags, F_LEVFLAG, 3, F_DETECTMAGIC, B_TRUE, NULL); addflag(lastjob->flags, F_LEVFLAG, 7, F_DETECTAURAS, B_TRUE, NULL); addflag(lastjob->flags, F_LEVFLAG, 10, F_CONTROL, B_TRUE, NULL); - addflag(lastjob->flags, F_LEVSPELLSCHOOL, 101, SS_NONE, B_TRUE, NULL); + addflag(lastjob->flags, F_LEVSPELLSCHOOL, 101, SS_NONE, B_TRUE, NULL); // new spell every 1 level // for monster wizards only: addflag(lastjob->flags, F_IFMONSTER, NA, NA, NA, NULL); @@ -5851,8 +6283,17 @@ void initjobs(void) { } void initrace(void) { + // race classes + addraceclass(RC_ANIMAL, "animal", "animals and insects", SK_LORE_NATURE); + addraceclass(RC_DEMON, "demon", "animals", SK_LORE_DEMONS); + addraceclass(RC_HUMANOID, "humanoid", "humanoid creates", SK_LORE_HUMANOID); + addraceclass(RC_INSECT, "insect", "insects and animals", SK_LORE_NATURE); + addraceclass(RC_SLIME, "slime", "slimes", SK_NONE); + addraceclass(RC_MAGIC, "magical creature", "magical creatures", SK_LORE_ARCANA); + addraceclass(RC_UNDEAD, "undead", "the undead", SK_LORE_UNDEAD); + // races / monsters - addrace(R_HUMAN, "human", 75, '@', C_GREY, MT_FLESH); + 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_SIZE, SZ_HUMAN, NA, NA, NULL); addflag(lastrace->flags, F_HITDICE, 2, 2, NA, NULL); @@ -5874,8 +6315,7 @@ void initrace(void) { addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); // monsters - - addrace(R_BEHOLDER, "beholder", 5, 'e', C_MAGENTA, MT_FLESH); + addrace(R_BEHOLDER, "beholder", 5, 'e', C_MAGENTA, MT_FLESH, RC_MAGIC); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_GENIUS, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); @@ -5904,7 +6344,7 @@ void initrace(void) { addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); - addrace(R_BUGBEAR, "bugbear", 120, 'G', C_BROWN, MT_FLESH); + addrace(R_BUGBEAR, "bugbear", 120, 'G', C_BROWN, MT_FLESH, RC_HUMANOID); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 63, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL); @@ -5925,7 +6365,7 @@ void initrace(void) { addflag(lastrace->flags, F_MINIONS, 50, 1, 3, "goblin"); addflag(lastrace->flags, F_MINIONS, 20, 1, 3, "goblin warrior"); - addrace(R_COCKATRICE, "cockatrice", 5, 'c', C_YELLOW, MT_FLESH); + addrace(R_COCKATRICE, "cockatrice", 5, 'c', C_YELLOW, MT_FLESH, RC_MAGIC); addflag(lastrace->flags, F_STARTATT, A_DEX, DX_SWIFT, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); addflag(lastrace->flags, F_COLDBLOOD, B_TRUE, NA, NA, NULL); @@ -5946,7 +6386,8 @@ void initrace(void) { addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); // special attack handled in attack.c - addrace(R_DARKMANTLE, "darkmantle", 70, 'Q', C_BLUE, MT_FLESH); + addrace(R_DARKMANTLE, "darkmantle", 70, 'Q', C_BLUE, MT_FLESH, RC_MAGIC); + addflag(lastrace->flags, F_STARTHIDDENPCT, 80, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, ST_MIGHTY, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_DEX, DX_SUPERSONIC, NA, NULL); @@ -5978,7 +6419,7 @@ void initrace(void) { addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); - addrace(R_EYEBAT, "eyebat", 5, 'e', C_BLUE, MT_FLESH); + addrace(R_EYEBAT, "eyebat", 5, 'e', C_BLUE, MT_FLESH, RC_MAGIC); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_SMART, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); @@ -6006,7 +6447,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOISETEXT, N_FLY, NA, NA, "^flapping wings"); addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); - addrace(R_GIANTHILL, "hill giant", 160, 'H', C_BROWN, MT_FLESH); + addrace(R_GIANTHILL, "hill giant", 160, 'H', C_BROWN, MT_FLESH, RC_HUMANOID); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 55, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_HUGE, NA, NA, NULL); @@ -6034,7 +6475,7 @@ void initrace(void) { addflag(lastrace->flags, F_FLEEONHPPCT, 50, NA, NA, NULL); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addrace(R_GIANTFIRE, "fire giant", 160, 'H', C_RED, MT_FLESH); + addrace(R_GIANTFIRE, "fire giant", 160, 'H', C_RED, MT_FLESH, RC_HUMANOID); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_HUGE, NA, NA, NULL); @@ -6064,7 +6505,7 @@ void initrace(void) { addflag(lastrace->flags, F_FLEEONHPPCT, 50, NA, NA, NULL); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addrace(R_GIANTFIREFC, "fire giant forgecaller", 160, 'H', C_RED, MT_FLESH); + addrace(R_GIANTFIREFC, "fire giant forgecaller", 160, 'H', C_RED, MT_FLESH, RC_HUMANOID); lastrace->baseid = R_GIANTFIRE; addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "fire giant corpse"); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 48, NA, NULL); @@ -6100,7 +6541,7 @@ void initrace(void) { addflag(lastrace->flags, F_HASSKILL, SK_SS_FIRE, PR_ADEPT, NA, NULL); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addrace(R_GIANTFIRETITAN, "fire titan", 160, 'H', C_RED, MT_FLESH); + addrace(R_GIANTFIRETITAN, "fire titan", 160, 'H', C_RED, MT_FLESH, RC_HUMANOID); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 40, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_ENORMOUS, NA, NA, NULL); @@ -6131,7 +6572,7 @@ void initrace(void) { // TODO: storm giant // TODO: storm titan - addrace(R_GNOLL, "gnoll", 130, 'h', C_BROWN, MT_FLESH); + addrace(R_GNOLL, "gnoll", 130, 'h', C_BROWN, MT_FLESH, RC_HUMANOID); addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "gnoll corpse"); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NUMAPPEAR, 2, 3, NA, ""); @@ -6153,7 +6594,7 @@ void initrace(void) { addflag(lastrace->flags, F_PACKATTACK, 5, NA, 2, "gnoll"); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addrace(R_GNOLLHM, "gnoll huntmaster", 130, 'h', C_BROWN, MT_FLESH); + addrace(R_GNOLLHM, "gnoll huntmaster", 130, 'h', C_BROWN, MT_FLESH, RC_HUMANOID); lastrace->baseid = R_GNOLL; addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "gnoll corpse"); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -6179,7 +6620,7 @@ void initrace(void) { addflag(lastrace->flags, F_MINIONS, 75, 1, 2, "gnoll"); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addrace(R_GNOLLMR, "gnoll marauder", 130, 'h', C_BROWN, MT_FLESH); + addrace(R_GNOLLMR, "gnoll marauder", 130, 'h', C_BROWN, MT_FLESH, RC_HUMANOID); lastrace->baseid = R_GNOLL; addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "gnoll corpse"); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -6204,7 +6645,7 @@ void initrace(void) { addflag(lastrace->flags, F_MINIONS, 75, 1, 2, "gnoll"); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addrace(R_GOBLIN, "goblin", 20, 'g', C_BROWN, MT_FLESH); + 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_SIZE, SZ_MEDIUM, NA, NA, NULL); @@ -6229,7 +6670,7 @@ void initrace(void) { addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addrace(R_GOBLINWAR, "goblin warrior", 30, 'g', C_BROWN, MT_FLESH); + addrace(R_GOBLINWAR, "goblin warrior", 30, 'g', C_BROWN, MT_FLESH, RC_HUMANOID); lastrace->baseid = R_GOBLIN; addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "goblin corpse"); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -6254,7 +6695,7 @@ void initrace(void) { addflag(lastrace->flags, F_MINIONS, 90, 1, 2, "goblin"); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addrace(R_GOBLINSHOOTER, "goblin sharpshooter", 20, 'g', C_BROWN, MT_FLESH); + addrace(R_GOBLINSHOOTER, "goblin sharpshooter", 20, 'g', C_BROWN, MT_FLESH, RC_HUMANOID); lastrace->baseid = R_GOBLIN; addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "goblin corpse"); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -6278,11 +6719,11 @@ void initrace(void) { addflag(lastrace->flags, F_DODGES, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_PACKATTACK, 2, DT_SLASH, 3, "goblin"); addflag(lastrace->flags, F_MINIONS, 70, 1, 2, "goblin"); - // TODO: can hide in shadows (need cansee function first) + addflag(lastrace->flags, F_CANWILL, OT_A_HIDE, NA, NA, NULL); + addflag(lastrace->flags, F_STARTHIDDENPCT, 75, NA, NA, NULL); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - - addrace(R_GOBLINHEXER, "goblin hexer", 20, 'g', C_BROWN, MT_FLESH); + addrace(R_GOBLINHEXER, "goblin hexer", 20, 'g', C_BROWN, MT_FLESH, RC_HUMANOID); lastrace->baseid = R_GOBLIN; addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "goblin corpse"); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -6310,7 +6751,7 @@ void initrace(void) { addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_MINIONS, 90, 1, 2, "goblin"); - addrace(R_HOBGOBLIN, "hobgoblin", 90, 'g', C_GREEN, MT_FLESH); + 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_NUMAPPEAR, 1, 2, NA, NULL); @@ -6338,7 +6779,7 @@ void initrace(void) { addflag(lastrace->flags, F_MINIONS, 50, 1, 2, "goblin"); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addrace(R_HOBGOBLINWAR, "hobgoblin warrior", 90, 'g', C_GREEN, MT_FLESH); + addrace(R_HOBGOBLINWAR, "hobgoblin warrior", 90, 'g', C_GREEN, MT_FLESH, RC_HUMANOID); lastrace->baseid = R_HOBGOBLIN; addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 60, NA, NULL); @@ -6371,7 +6812,7 @@ void initrace(void) { // TODO: hobgoblin archer // TODO: hobgoblin warcaster - addrace(R_KOBOLD, "kobold", 18, 'k', C_BROWN, MT_FLESH); + addrace(R_KOBOLD, "kobold", 18, 'k', C_BROWN, MT_FLESH, RC_HUMANOID); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 95, NA, NULL); addflag(lastrace->flags, F_POISONOUS, B_TRUE, NA, NA, NULL); @@ -6397,7 +6838,7 @@ void initrace(void) { addflag(lastrace->flags, F_SEEINDARK, 2, NA, NA, NULL); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addrace(R_TROGLODYTE, "troglodyte", 20, 'z', C_GREY, MT_FLESH); + addrace(R_TROGLODYTE, "troglodyte", 20, 'z', C_GREY, MT_FLESH, RC_HUMANOID); addflag(lastrace->flags, F_COLDBLOOD, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_POISONOUS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -6421,7 +6862,7 @@ void initrace(void) { addflag(lastrace->flags, F_STENCH, 3, 3, NA, NULL); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addrace(R_LIZARDMAN, "lizardman", 100, 'z', C_GREEN, MT_FLESH); + addrace(R_LIZARDMAN, "lizardman", 100, 'z', C_GREEN, MT_FLESH, RC_HUMANOID); addflag(lastrace->flags, F_COLDBLOOD, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL); @@ -6443,7 +6884,7 @@ void initrace(void) { addflag(lastrace->flags, F_SPELLCASTTEXT, NA, NA, NA, "spits"); addflag(lastrace->flags, F_CANWILL, OT_S_POISONBOLT, 5, 5, "pw:5;"); - addrace(R_LURKINGHORROR, "lurking horror", 100, 'U', C_MAGENTA, MT_FLESH); + addrace(R_LURKINGHORROR, "lurking horror", 100, 'U', C_MAGENTA, MT_FLESH, RC_DEMON); addflag(lastrace->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL); @@ -6469,7 +6910,7 @@ void initrace(void) { addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); - addrace(R_OGRE, "ogre", 160, 'O', C_BROWN, MT_FLESH); + addrace(R_OGRE, "ogre", 160, 'O', C_BROWN, MT_FLESH, RC_HUMANOID); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 60, NA, NULL); @@ -6497,7 +6938,7 @@ void initrace(void) { addflag(lastrace->flags, F_MINIONS, 20, 1, 2, "orc warrior"); addflag(lastrace->flags, F_MORALE, 20, NA, NA, NULL); - addrace(R_OGRESAVAGE, "ogre savage", 160, 'O', C_BROWN, MT_FLESH); + addrace(R_OGRESAVAGE, "ogre savage", 160, 'O', C_BROWN, MT_FLESH, RC_HUMANOID); lastrace->baseid = R_OGRE; addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL); @@ -6526,7 +6967,7 @@ void initrace(void) { addflag(lastrace->flags, F_MINIONS, 50, 1, 5, "orc"); addflag(lastrace->flags, F_MINIONS, 50, 1, 3, "orc warrior"); - addrace(R_OGREWARHULK, "ogre warhulk", 160, 'O', C_BROWN, MT_FLESH); + addrace(R_OGREWARHULK, "ogre warhulk", 160, 'O', C_BROWN, MT_FLESH, RC_HUMANOID); lastrace->baseid = R_OGRE; addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL); @@ -6556,7 +6997,7 @@ void initrace(void) { addflag(lastrace->flags, F_MINIONS, 25, 1, 8, "orc"); addflag(lastrace->flags, F_MINIONS, 25, 1, 2, "orc warrior"); - addrace(R_ORC, "orc", 90, 'o', C_BROWN, MT_FLESH); + addrace(R_ORC, "orc", 90, 'o', C_BROWN, MT_FLESH, RC_HUMANOID); 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, 78, NA, NULL); @@ -6584,7 +7025,7 @@ void initrace(void) { addflag(lastrace->flags, F_CANWILL, OT_A_SPRINT, 5, 5, NULL); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addrace(R_ORCWARRIOR, "orc warrior", 90, 'o', C_BROWN, MT_FLESH); + addrace(R_ORCWARRIOR, "orc warrior", 90, 'o', C_BROWN, MT_FLESH, RC_HUMANOID); lastrace->baseid = R_ORC; addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); @@ -6614,7 +7055,7 @@ void initrace(void) { addflag(lastrace->flags, F_CANWILL, OT_A_SPRINT, NA, NA, NULL); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addrace(R_ORK, "ork", 90, 'o', C_BROWN, MT_FLESH); + addrace(R_ORK, "ork", 90, 'o', C_BROWN, MT_FLESH, RC_HUMANOID); addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "orc corpse"); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); @@ -6641,7 +7082,7 @@ void initrace(void) { addflag(lastrace->flags, F_SEEINDARK, 3, NA, NA, NULL); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addrace(R_POLTERGEIST, "poltergeist", 50, 'p', C_GREEN, MT_FLESH); + addrace(R_POLTERGEIST, "poltergeist", 50, 'p', C_GREEN, MT_FLESH, RC_UNDEAD); // sPirit addflag(lastrace->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_AVERAGE, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -6675,7 +7116,7 @@ void initrace(void) { addflag(lastrace->flags, F_DTIMMUNE, DT_NECROTIC, NA, NA, NULL); addflag(lastrace->flags, F_DTVULN, DT_HOLY, NA, NA, NULL); - addrace(R_SHADOWCAT, "shadowcat", 5, 'f', C_BLUE, MT_FLESH); + addrace(R_SHADOWCAT, "shadowcat", 5, 'f', C_BLUE, MT_FLESH, RC_MAGIC); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 65, NA, NULL); @@ -6690,7 +7131,7 @@ void initrace(void) { addflag(lastrace->flags, F_AUTOCREATEOB, 1, NA, NA, "cloud of smoke"); addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); - addrace(R_OOZEGREY, "grey ooze", 10, 'j', C_GREY, MT_SLIME); + addrace(R_OOZEGREY, "grey ooze", 10, 'j', C_GREY, MT_SLIME, RC_SLIME); addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "pool of slime"); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL); @@ -6719,7 +7160,7 @@ void initrace(void) { addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); - addrace(R_SPRITEFIRE, "fire sprite", 5, 'n', C_RED, MT_FIRE); + addrace(R_SPRITEFIRE, "fire sprite", 5, 'n', C_RED, MT_FIRE, RC_MAGIC); addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "small fire"); addflag(lastrace->flags, F_STARTATT, A_STR, ST_VWEAK, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_AVERAGE, NA, NULL); @@ -6745,7 +7186,7 @@ void initrace(void) { addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); - addrace(R_TROLL, "troll", 100, 't', C_GREEN, MT_FLESH); + addrace(R_TROLL, "troll", 100, 't', C_GREEN, MT_FLESH, RC_HUMANOID); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 65, NA, NULL); @@ -6762,7 +7203,7 @@ void initrace(void) { addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); - addrace(R_XAT, "xat", 2, 'x', C_BROWN, MT_FLESH); + addrace(R_XAT, "xat", 2, 'x', C_BROWN, MT_FLESH, RC_ANIMAL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_TINY, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 95, NA, NULL); @@ -6779,7 +7220,7 @@ void initrace(void) { // end monsters // animals - addrace(R_BAT, "giant bat", 3, 'B', C_BROWN, MT_FLESH); + addrace(R_BAT, "giant bat", 3, 'B', C_BROWN, MT_FLESH, RC_ANIMAL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 95, NA, ""); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_ANIMAL, B_TRUE, NA, NA, NULL); @@ -6801,7 +7242,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_TREMORSENSE, 10, NA, NA, NULL); addflag(lastrace->flags, F_NOISETEXT, N_FLY, NA, NA, "^flapping wings"); - addrace(R_ANT, "giant worker ant", 4, 'a', C_BROWN, MT_FLESH); + addrace(R_ANT, "giant worker ant", 4, 'a', C_BROWN, MT_FLESH, RC_ANIMAL); lastrace->baseid = R_ANT; addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 85, NA, NULL); @@ -6823,7 +7264,7 @@ void initrace(void) { addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "0d1+4"); addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL); addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); - addrace(R_ANTS, "giant soldier ant", 5, 'a', C_BROWN, MT_FLESH); + addrace(R_ANTS, "giant soldier ant", 5, 'a', C_BROWN, MT_FLESH, RC_ANIMAL); lastrace->baseid = R_ANT; addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 65, NA, NULL); @@ -6848,7 +7289,7 @@ void initrace(void) { addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_MINIONS, 50, 1, 3, "giant worker ant"); - addrace(R_HAWKYOUNG, "young hawk", 1, 'A', C_GREY, MT_FLESH); // 'A' for Avian + addrace(R_HAWKYOUNG, "young hawk", 1, 'A', C_GREY, MT_FLESH, RC_ANIMAL); // 'A' for Avian lastrace->baseid = R_HAWK; addflag(lastrace->flags, F_RARITY, H_DUNGEON, 75, NA, ""); addflag(lastrace->flags, F_ANIMAL, B_TRUE, NA, NA, NULL); @@ -6870,8 +7311,9 @@ void initrace(void) { addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_CANWILL, OT_A_SWOOP, 3, 3, NULL); addflag(lastrace->flags, F_SWOOPRANGE, 2, NA, NA, NULL); + addflag(lastrace->flags, F_LEVRACE, 4, R_HAWK, NA, NULL); - addrace(R_HAWK, "hawk", 1, 'A', C_GREY, MT_FLESH); // 'A' for Avian + addrace(R_HAWK, "hawk", 1, 'A', C_GREY, MT_FLESH, RC_ANIMAL); // 'A' for Avian lastrace->baseid = R_HAWK; addflag(lastrace->flags, F_RARITY, H_DUNGEON, 68, NA, ""); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -6895,10 +7337,9 @@ void initrace(void) { addflag(lastrace->flags, F_CANWILL, OT_A_SWOOP, 3, 3, NULL); addflag(lastrace->flags, F_SWOOPRANGE, 3, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 5, NA, NA, NULL); - addflag(lastrace->flags, F_LEVRACE, 4, R_HAWK, NA, NULL); addflag(lastrace->flags, F_LEVRACE, 8, R_HAWKBLOOD, NA, NULL); - addrace(R_HAWKBLOOD, "blood hawk", 1, 'A', C_RED, MT_FLESH); // 'A' for Avian + addrace(R_HAWKBLOOD, "blood hawk", 1, 'A', C_RED, MT_FLESH, RC_ANIMAL); // 'A' for Avian lastrace->baseid = R_HAWK; addflag(lastrace->flags, F_RARITY, H_DUNGEON, 65, NA, ""); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -6922,7 +7363,7 @@ void initrace(void) { addflag(lastrace->flags, F_CANWILL, OT_A_SWOOP, 3, 3, NULL); addflag(lastrace->flags, F_SWOOPRANGE, 5, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 7, NA, NA, NULL); - addrace(R_HAWKFROST, "frost hawk", 1, 'A', C_CYAN, MT_FLESH); // 'A' for Avian + addrace(R_HAWKFROST, "frost hawk", 1, 'A', C_CYAN, MT_FLESH, RC_ANIMAL); // 'A' for Avian addflag(lastrace->flags, F_RARITY, H_DUNGEON, 63, NA, ""); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_ANIMAL, B_TRUE, NA, NA, NULL); @@ -6947,7 +7388,7 @@ void initrace(void) { addflag(lastrace->flags, F_CANWILL, OT_S_COLDBURST, 2, 2, "pw:2;"); addflag(lastrace->flags, F_SPELLCASTTEXT, NA, NA, NA, "screeches"); addflag(lastrace->flags, F_MORALE, 10, NA, NA, NULL); - addrace(R_NEWT, "giant newt", 4, ':', C_BROWN, MT_FLESH); + addrace(R_NEWT, "giant newt", 4, ':', C_BROWN, MT_FLESH, RC_ANIMAL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 100, NA, NULL); addflag(lastrace->flags, F_COLDBLOOD, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -6965,7 +7406,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_DTRESIST, DT_FIRE, B_TRUE, NA, NULL); addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); - addrace(R_RAT, "giant rat", 3, 'r', C_BROWN, MT_FLESH); + addrace(R_RAT, "giant rat", 3, 'r', C_BROWN, MT_FLESH, RC_ANIMAL); addflag(lastrace->flags, F_ANIMAL, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, ST_VWEAK, NA, NULL); @@ -6988,7 +7429,7 @@ void initrace(void) { addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, B_COVETS, NA, NULL); addflag(lastrace->flags, F_SEEINDARK, 4, NA, NA, NULL); addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL); - addrace(R_SNAKE, "brown snake", 3, 's', C_BROWN, MT_FLESH); + addrace(R_SNAKE, "brown snake", 3, 's', C_BROWN, MT_FLESH, RC_ANIMAL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 85, NA, ""); addflag(lastrace->flags, F_ANIMAL, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_COLDBLOOD, B_TRUE, NA, NA, NULL); @@ -6999,8 +7440,8 @@ void initrace(void) { addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_HITDICE, 2, NA, NA, ""); addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d4"); - addflag(lastrace->flags, F_HITCONFER, F_POISONED, SC_POISON, 20, "10-15"); - addflag(lastrace->flags, F_HITPOISONTYPE, P_VENOM, 1, NA, NULL); + addflag(lastrace->flags, F_HITCONFER, F_POISONED, SC_POISON, 20, "5-10"); + addflag(lastrace->flags, F_HITCONFERVALS, P_VENOM, 1, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_WEAPON, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_SECWEAPON, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_SHOULDERS, NA, NA, NULL); @@ -7011,13 +7452,128 @@ void initrace(void) { addflag(lastrace->flags, F_DTVULN, DT_COLD, NA, NA, NULL); addflag(lastrace->flags, F_NOISETEXT, N_WALK, NA, NA, "^hissing"); addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); - addrace(R_WOLF, "wolf", 10, 'd', C_BROWN, MT_FLESH); + addrace(R_SNAKECARPET, "carpet snake", 3, 's', C_GREY, MT_FLESH, RC_ANIMAL); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, 88, NA, ""); addflag(lastrace->flags, F_ANIMAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_COLDBLOOD, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); + 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_HITDICE, 2, NA, NA, ""); + addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d3+1"); + addflag(lastrace->flags, F_NOBODYPART, BP_WEAPON, NA, NA, NULL); + addflag(lastrace->flags, F_NOBODYPART, BP_SECWEAPON, NA, NA, NULL); + addflag(lastrace->flags, F_NOBODYPART, BP_SHOULDERS, NA, NA, NULL); + addflag(lastrace->flags, F_NOBODYPART, BP_HANDS, NA, NA, NULL); + addflag(lastrace->flags, F_NOBODYPART, BP_FEET, NA, NA, NULL); + addflag(lastrace->flags, F_NOPACK, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_DTVULN, DT_COLD, NA, NA, NULL); + addflag(lastrace->flags, F_NOISETEXT, N_WALK, NA, NA, "^hissing"); + addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); + addrace(R_SPIDER, "giant spider", 5, 'S', C_GREEN, MT_FLESH, RC_ANIMAL); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, 87, NA, ""); + addflag(lastrace->flags, F_ANIMAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_DEX, DX_DEXTROUS, NA, NULL); + addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); + addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); + addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, ""); + addflag(lastrace->flags, F_HITDICE, 2, 1, NA, NULL); + addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d4"); + addflag(lastrace->flags, F_NOBODYPART, BP_WEAPON, NA, NA, NULL); + addflag(lastrace->flags, F_NOBODYPART, BP_SECWEAPON, NA, NA, NULL); + addflag(lastrace->flags, F_NOBODYPART, BP_SHOULDERS, NA, NA, NULL); + addflag(lastrace->flags, F_NOBODYPART, BP_HANDS, NA, NA, NULL); + addflag(lastrace->flags, F_SPELLCASTTEXT, NA, NA, NA, NULL); // don't announce spellcasting + addflag(lastrace->flags, F_CANWILL, OT_S_WEB, 3, 3, "pw:1;"); + addflag(lastrace->flags, F_NOPACK, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_DTVULN, DT_LIGHT, NA, NA, NULL); + addflag(lastrace->flags, F_SEEINDARK, UNLIMITED, NA, NA, NULL); + addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_POISONOUS, B_TRUE, NA, NA, NULL); + addrace(R_SPIDERFUNNELWEB, "giant funnelweb", 5, 'S', C_MAGENTA, MT_FLESH, RC_ANIMAL); + lastrace->baseid = R_SPIDER; + addflag(lastrace->flags, F_RARITY, H_DUNGEON, 63, NA, ""); + addflag(lastrace->flags, F_ANIMAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_DEX, DX_DEXTROUS, NA, NULL); + addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); + addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); + addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, ""); + addflag(lastrace->flags, F_HITDICE, 3, 1, NA, NULL); + addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d4"); + addflag(lastrace->flags, F_HITCONFER, F_POISONED, SC_POISON, 26, "10-20"); + addflag(lastrace->flags, F_HITCONFERVALS, P_VENOM, 3, NA, NULL); // strong! + addflag(lastrace->flags, F_NOBODYPART, BP_WEAPON, NA, NA, NULL); + addflag(lastrace->flags, F_NOBODYPART, BP_SECWEAPON, NA, NA, NULL); + addflag(lastrace->flags, F_NOBODYPART, BP_SHOULDERS, NA, NA, NULL); + addflag(lastrace->flags, F_NOBODYPART, BP_HANDS, NA, NA, NULL); + addflag(lastrace->flags, F_SPELLCASTTEXT, NA, NA, NA, NULL); // don't announce spellcasting + addflag(lastrace->flags, F_CANWILL, OT_S_WEB, 3, 3, "pw:2;"); + addflag(lastrace->flags, F_NOPACK, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_DTVULN, DT_LIGHT, NA, NA, NULL); + addflag(lastrace->flags, F_SEEINDARK, UNLIMITED, NA, NA, NULL); + addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_POISONOUS, B_TRUE, NA, NA, NULL); + addrace(R_SPIDERREDBACK, "giant redback", 5, 'S', C_RED, MT_FLESH, RC_ANIMAL); + lastrace->baseid = R_SPIDER; + addflag(lastrace->flags, F_RARITY, H_DUNGEON, 78, NA, ""); + addflag(lastrace->flags, F_ANIMAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_DEX, DX_DEXTROUS, NA, NULL); + addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); + addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); + addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, ""); + addflag(lastrace->flags, F_HITDICE, 3, 1, NA, NULL); + addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d4"); + addflag(lastrace->flags, F_HITCONFER, F_PAIN, SC_POISON, 26, "5-15"); + addflag(lastrace->flags, F_HITCONFERVALS, DT_POISON, NA, NA, "1d2"); + addflag(lastrace->flags, F_NOBODYPART, BP_WEAPON, NA, NA, NULL); + addflag(lastrace->flags, F_NOBODYPART, BP_SECWEAPON, NA, NA, NULL); + addflag(lastrace->flags, F_NOBODYPART, BP_SHOULDERS, NA, NA, NULL); + addflag(lastrace->flags, F_NOBODYPART, BP_HANDS, NA, NA, NULL); + addflag(lastrace->flags, F_SPELLCASTTEXT, NA, NA, NA, NULL); // don't announce spellcasting + addflag(lastrace->flags, F_CANWILL, OT_S_WEB, 3, 3, "pw:3;"); + addflag(lastrace->flags, F_NOPACK, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_DTVULN, DT_LIGHT, NA, NA, NULL); + addflag(lastrace->flags, F_SEEINDARK, UNLIMITED, NA, NA, NULL); + addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_POISONOUS, B_TRUE, NA, NA, NULL); + addrace(R_WOLFYOUNG, "young wolf", 5, 'd', C_BROWN, MT_FLESH, RC_ANIMAL); + addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_ANIMAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_CON, CN_HARDY, NA, NULL); + addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL); + addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, ""); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, 87, NA, ""); + addflag(lastrace->flags, F_HITDICE, 2, 0, NA, ""); + addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d3"); + addflag(lastrace->flags, F_MAXATTACKS, 1, NA, NA, NULL); + addflag(lastrace->flags, F_NOBODYPART, BP_WEAPON, NA, NA, NULL); + addflag(lastrace->flags, F_NOBODYPART, BP_SECWEAPON, NA, NA, NULL); + addflag(lastrace->flags, F_NOBODYPART, BP_SHOULDERS, NA, NA, NULL); + addflag(lastrace->flags, F_NOBODYPART, BP_HANDS, NA, NA, NULL); + addflag(lastrace->flags, F_NOPACK, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, B_COVETS, NA, NULL); + addflag(lastrace->flags, F_SEEINDARK, 4, NA, NA, NULL); + addflag(lastrace->flags, F_CANWILL, OT_A_SPRINT, 8, 8, NULL); + addflag(lastrace->flags, F_LEVRACE, 5, R_WOLF, NA, NULL); + addrace(R_WOLF, "wolf", 10, 'd', C_BROWN, MT_FLESH, RC_ANIMAL); + addflag(lastrace->flags, F_ANIMAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_CON, CN_HARDY, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_FAST, NA, NA, ""); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 80, NA, ""); - addflag(lastrace->flags, F_HITDICE, 2, 0, NA, ""); + addflag(lastrace->flags, F_HITDICE, 2, 4, NA, ""); addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d5"); addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d5"); addflag(lastrace->flags, F_MAXATTACKS, 1, NA, NA, NULL); @@ -7033,7 +7589,7 @@ void initrace(void) { addflag(lastrace->flags, F_CANWILL, OT_A_SPRINT, 5, 5, NULL); // insects - addrace(R_BUTTERFLY, "butterfly", 0.01, 'i', C_GREEN, MT_FLESH); + addrace(R_BUTTERFLY, "butterfly", 0.01, 'i', C_GREEN, MT_FLESH, RC_ANIMAL); addflag(lastrace->flags, F_INSECT, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_VERYFAST, NA, NA, ""); @@ -7052,7 +7608,7 @@ void initrace(void) { addflag(lastrace->flags, F_PRODUCESLIGHT, 2, NA, NA, NULL); addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL); addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); - addrace(R_GIANTFLY, "giant fly", 1, 'i', C_GREY, MT_FLESH); + addrace(R_GIANTFLY, "giant fly", 1, 'i', C_GREY, MT_FLESH, RC_INSECT); lastrace->baseid = R_GIANTFLY; addflag(lastrace->flags, F_INSECT, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); @@ -7075,7 +7631,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOISETEXT, N_FLY, NA, NA, "^buzzing"); addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL); addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); - addrace(R_GIANTBLOWFLY, "giant blowfly", 2, 'i', C_WHITE, MT_FLESH); + addrace(R_GIANTBLOWFLY, "giant blowfly", 2, 'i', C_WHITE, MT_FLESH, RC_INSECT); lastrace->baseid = R_GIANTFLY; addflag(lastrace->flags, F_INSECT, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); @@ -7100,7 +7656,7 @@ void initrace(void) { addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL); addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); - addrace(R_CENTIPEDE, "giant centipede", 3, 'c', C_GREEN, MT_FLESH); + addrace(R_CENTIPEDE, "giant centipede", 3, 'c', C_GREEN, MT_FLESH, RC_INSECT); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 80, NA, ""); addflag(lastrace->flags, F_INSECT, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -7111,7 +7667,7 @@ void initrace(void) { addflag(lastrace->flags, F_HITDICE, 3, NA, NA, ""); addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d6"); addflag(lastrace->flags, F_HITCONFER, F_POISONED, SC_POISON, 25, "10-15"); - addflag(lastrace->flags, F_HITPOISONTYPE, P_WEAKNESS, 3, NA, NULL); + addflag(lastrace->flags, F_HITCONFERVALS, P_WEAKNESS, 3, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_WEAPON, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_SECWEAPON, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_SHOULDERS, NA, NA, NULL); @@ -7122,7 +7678,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOISETEXT, N_WALK, NA, NA, "^scuttling"); addflag(lastrace->flags, F_TREMORSENSE, 3, NA, NA, NULL); addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); - addrace(R_GLOWBUG, "glowbug", 1, 'i', C_WHITE, MT_FLESH); + addrace(R_GLOWBUG, "glowbug", 1, 'i', C_WHITE, MT_FLESH, RC_INSECT); addflag(lastrace->flags, F_INSECT, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_VERYFAST, NA, NA, ""); @@ -7145,7 +7701,7 @@ void initrace(void) { addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); // undead - addrace(R_ZOMBIE, "zombie", 50, 'Z', C_BLUE, MT_FLESH); + addrace(R_ZOMBIE, "zombie", 50, 'Z', C_BLUE, MT_FLESH, RC_UNDEAD); addflag(lastrace->flags, F_UNDEAD, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_MINDLESS, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 85, NA, NULL); @@ -7171,7 +7727,7 @@ void initrace(void) { addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); - addrace(R_SKELETON, "skeleton", 20, 'Z', C_GREY, MT_BONE); + addrace(R_SKELETON, "skeleton", 20, 'Z', C_GREY, MT_BONE, RC_UNDEAD); addflag(lastrace->flags, F_UNDEAD, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_MINDLESS, NA, NULL); addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "5-20 bones"); @@ -7197,7 +7753,7 @@ void initrace(void) { addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); - addrace(R_GHAST, "ghast", 50, 'Z', C_MAGENTA, MT_FLESH); + addrace(R_GHAST, "ghast", 50, 'Z', C_MAGENTA, MT_FLESH, RC_UNDEAD); addflag(lastrace->flags, F_UNDEAD, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_SMART, NA, NULL); addflag(lastrace->flags, F_BLOODOB, NA, NA, NA, NULL); @@ -7220,7 +7776,7 @@ void initrace(void) { addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); - addrace(R_GHOST, "ghost", 50, 'I', C_BLUE, MT_MAGIC); + addrace(R_GHOST, "ghost", 50, 'p', C_BLUE, MT_MAGIC, RC_UNDEAD); // p for sPirit addflag(lastrace->flags, F_UNDEAD, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_SMART, NA, NULL); addflag(lastrace->flags, F_BLOODOB, NA, NA, NA, NULL); @@ -7246,7 +7802,7 @@ void initrace(void) { // special: ghosts gain canwill->possession if they are near // their previous corpse. use f_mycorpse->oid for this. - addrace(R_GHOUL, "ghoul", 50, 'Z', C_BLUE, MT_FLESH); + addrace(R_GHOUL, "ghoul", 50, 'Z', C_BLUE, MT_FLESH, RC_UNDEAD); addflag(lastrace->flags, F_UNDEAD, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_MINDLESS, NA, NULL); addflag(lastrace->flags, F_BLOODOB, NA, NA, NA, NULL); @@ -7271,7 +7827,7 @@ void initrace(void) { addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); // special monsters - addrace(R_GASCLOUD, "cloud of gas", 0.1, '}', C_GREY, MT_GAS); + addrace(R_GASCLOUD, "cloud of gas", 0.1, '}', C_GREY, MT_GAS, RC_OTHER); addflag(lastrace->flags, F_MOVESPEED, SP_ULTRAFAST, NA, NA, ""); addflag(lastrace->flags, F_BLOODOB, NA, NA, NA, NULL); addflag(lastrace->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL); @@ -7298,7 +7854,7 @@ void initrace(void) { addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); - addrace(R_DANCINGWEAPON, "dancing weapon", 0, ')', C_GREY, MT_METAL); + addrace(R_DANCINGWEAPON, "dancing weapon", 0, ')', C_GREY, MT_METAL, RC_OTHER); addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL); addflag(lastrace->flags, F_FLYING, B_TRUE, NA, NA, ""); addflag(lastrace->flags, F_HITDICE, 2, NA, NA, ""); @@ -7546,6 +8102,20 @@ int isimmobile(lifeform_t *lf) { return B_FALSE; } +int isloreskill(enum SKILL skid) { + switch (skid) { + case SK_LORE_ARCANA: + case SK_LORE_DEMONS: + case SK_LORE_HUMANOID: + case SK_LORE_NATURE: + case SK_LORE_UNDEAD: + return B_TRUE; + default: + break; + } + return B_FALSE; +} + int ismaxedskill(lifeform_t *lf, enum SKILL skid) { // TODO: implement skill maximums per job if (getskill(lf, skid) == PR_MASTER) { @@ -7913,6 +8483,7 @@ void makefriendly(lifeform_t *who, int howlong) { if (!hasflag(who->flags, F_FRIENDLY)) { addtempflag(who->flags, F_FRIENDLY, B_TRUE, NA, NA, NULL, howlong); } + killflagsofid(who->flags, F_TARGET); // stop targetting anyone } @@ -8019,6 +8590,53 @@ void mayusespellschool(flagpile_t *fp, enum SPELLSCHOOL ss, enum FLAG how) { } +// if you don't meet it, return why not in 'reason' +int meetsattreq(lifeform_t *lf, flag_t *f, object_t *o) { + enum ATTRIB att; + int brackneeded; + int myatt; + int mybrack; + att = f->val[0]; + brackneeded = f->val[1]; + + reason = E_OK; + + // modify for masterwork + if (o) { + if (hasflag(o->flags, F_MASTERWORK)) { + brackneeded--; + if (brackneeded < 0) brackneeded = 0; + } + } + + myatt = getattr(lf, att); + + switch (att) { + case A_DEX: + mybrack = getdexname(myatt, NULL); + reason = E_LOWDEX; + break; + case A_CON: + mybrack = getconname(myatt, NULL); + reason = E_LOWCON; + break; + case A_IQ: + mybrack = getiqname(myatt, NULL); + reason = E_LOWIQ; + break; + case A_STR: + mybrack = getstrname(myatt, NULL); + reason = E_LOWSTR; + break; + case A_NONE: + break; + } + if (mybrack < brackneeded) { + return B_FALSE; + } + return B_TRUE; +} + int modattr(lifeform_t *lf, enum ATTRIB attr, int amt) { if (isplayer(lf)) { @@ -8091,10 +8709,20 @@ int modattr(lifeform_t *lf, enum ATTRIB attr, int amt) { void modhunger(lifeform_t *lf, int amt) { flag_t *f; int prehlev, posthlev; + int multiplier; f = hasflag(lf->flags, F_HUNGER); if (!f) { return; } + + // modify for effects + if (amt > 0) { + sumflags(lf->flags, F_FASTMETAB, &multiplier, NULL, NULL); + if (multiplier > 0) { + amt *= multiplier; + } + } + prehlev = gethungerlevel(f->val[0]); f->val[0] += amt; posthlev = gethungerlevel(f->val[0]); @@ -8141,6 +8769,8 @@ void modhunger(lifeform_t *lf, int amt) { buf, (needexclam) ? '!' : '.'); + statdirty = B_TRUE; + if ((posthlev >= H_PECKISH) && (amt > 0)) { stopresting(lf); } @@ -8577,7 +9207,7 @@ int push(lifeform_t *lf, object_t *o, int dir) { } // move player - moveto(lf, obcell, B_TRUE); + moveto(lf, obcell, B_TRUE, B_FALSE); // announce if (isplayer(lf)) { @@ -9254,13 +9884,18 @@ void initskills(void) { addskill(SK_FIRSTAID, "First Aid", "Increases your healing rate and reduces duration of poison."); addskill(SK_LISTEN, "Listen", "How good you are at hearing and interpreting sounds."); addskill(SK_LOCKPICKING, "Lockpicking", "Enhances your ability to pick locks."); - addskill(SK_MAGITEMUSAGE, "Magic Item Usage", "Lets you make better use of magical items."); - addskill(SK_RESEARCH, "Research", "Allows you a chance of recognising unknown objects."); + addskill(SK_CHANNELING, "Channeling", "Lets you make better use of magical items."); addskill(SK_SHIELDS, "Shields", "Reduces your accuracy penalty when using a shield."); addskill(SK_SPELLCASTING, "Spellcasting", "Determines your ability to cast spells from all schools."); addskill(SK_SPOTHIDDEN, "Searching", "Helps you to spot hidden traps or creatures."); addskill(SK_STEALTH, "Stealth", "Affects your ability to move silently."); addskill(SK_TECHUSAGE, "Technology", "Determines your comprehension of modern technological items."); + // knowledge + addskill(SK_LORE_ARCANA, "Lore:Arcana", "Allows you a chance of recognising unknown objects."); + addskill(SK_LORE_DEMONS, "Lore:Demonology", "Determines your knowledge about demons."); + addskill(SK_LORE_HUMANOID, "Lore:Humanoid", "Determines your knowledge about humanoid (bipedal) creatures."); + addskill(SK_LORE_NATURE, "Lore:Nature", "Determines your knowledge of plants, animals and insects."); + addskill(SK_LORE_UNDEAD, "Lore:Undead", "Determines your knowledge of the undead."); // weaponry addskill(SK_AXES, "Axes", "Helps you use chopping weapons like axes."); addskill(SK_CLUBS, "Clubs", "Helps you use bashing weapons like maces or clubs."); @@ -9274,13 +9909,13 @@ void initskills(void) { addskill(SK_SS_AIR, "Air Magic", "Boosts casting of spells from this school."); addskill(SK_SS_DEATH, "Necromancy", "Boosts casting of spells from this school."); addskill(SK_SS_DIVINATION, "Divination", "Boosts casting of spells from this school."); - addskill(SK_SS_EARTH, "Earth Magic", "Boosts casting of spells from this school."); addskill(SK_SS_FIRE, "Fire Magic", "Boosts casting of spells from this school."); addskill(SK_SS_ICE, "Ice Magic", "Boosts casting of spells from this school."); addskill(SK_SS_GRAVITY, "Gravitation Magic", "Boosts casting of spells from this school."); addskill(SK_SS_LIFE, "Life Magic", "Boosts casting of spells from this school."); addskill(SK_SS_MODIFICATION, "Modification", "Boosts casting of spells from this school."); addskill(SK_SS_MENTAL, "Psionics", "Boosts casting of spells from this school."); + addskill(SK_SS_NATURE, "Nature Magic", "Boosts casting of spells from this school."); addskill(SK_SS_SUMMONING, "Summoning", "Boosts casting of spells from this school."); addskill(SK_SS_TRANSLOCATION, "Translocation", "Boosts casting of spells from this school."); addskill(SK_SS_WILD, "Wild Magic", "Boosts casting of spells from this school."); @@ -9361,7 +9996,9 @@ int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *r flag_t *f; if (lfhasflag(lf, F_DEBUG)) { - db = B_TRUE; + if (ct != SC_STEALTH) { // dont show debug info for stealth checks + db = B_TRUE; + } } switch (ct) { @@ -9508,6 +10145,15 @@ int skillcheckvs(lifeform_t *lf1, enum CHECKTYPE ct1, int mod1, lifeform_t *lf2, db = B_TRUE; } + // bonus for knowledge about the other lf's race + if (getlorelevel(lf1, lf2->race->raceclass->id) >= PR_SKILLED) { + mod1 += 5; + } + if (getlorelevel(lf2, lf1->race->raceclass->id) >= PR_SKILLED) { + mod2 += 5; + } + + real_skillcheck(lf1, ct1, 0, mod1, &roll1); real_skillcheck(lf2, ct2, 0, mod2, &roll2); if (db) { @@ -9549,6 +10195,10 @@ int slipon(lifeform_t *lf, object_t *o) { losehp(lf, 1, DT_FALL, NULL, damstring); } taketime(lf, getactspeed(lf)*2); + // object gets damaged? + if (hasflag(o->flags, F_DAMAGABLE)) { + takedamage(o, 1, DT_DIRECT); + } // object moves? if (hasflag(o->flags, F_SLIPMOVE)) { cell_t *cur, *new; @@ -9809,7 +10459,6 @@ void taketime(lifeform_t *lf, long howlong) { assert(lf->timespent >= 0); // time-based effects on lifeforms (eg hp regeneration) go here... - modhunger(lf, howlong); // TODO: decrement lifeform's (or their object's) temporary flags @@ -9917,6 +10566,7 @@ void turneffectslf(lifeform_t *lf) { enum ERROR error; object_t *o; flag_t *f, *nextf; + flag_t *asp; char buf[BUFLEN]; lifeform_t *l; int i; @@ -9934,7 +10584,8 @@ void turneffectslf(lifeform_t *lf) { if (isplayer(lf)) { updateknowncells(); } else { - lf->ignorecell = NULL; + // ai start of turn code + killflagsofid(lf->flags, F_IGNORECELL); } // stuck inside solid cells? @@ -10076,15 +10727,36 @@ void turneffectslf(lifeform_t *lf) { } } + + asp = hasactivespell(l, OT_S_CALMINGSCENT); + if (asp && (getcelldist(l->cell,lf->cell) == 1)) { + if ((getraceclass(lf) == RC_ANIMAL) && lfhasflag(lf, F_HOSTILE)) { + int maxhitdice; + // calming strong enough? + maxhitdice = asp->val[2] + 1; + if (gethitdice(lf) <= maxhitdice) { + makepeaceful(lf); + } + } + } + // they are hiding, and you haven't spotted them yet f = lfhasflag(l, F_HIDING); if (f && !lfhasflagval(lf, F_SPOTTED, l->id, NA, NA, NULL)) { // can you see their cell? if (haslos(lf, l->cell)) { int bonus = 0; + int dist; if (!lfhasflag(l, F_SILENTMOVE) && !lfhasflag(lf, F_DEAF)) { - bonus = getskill(lf, SK_LISTEN); + bonus += getskill(lf, SK_LISTEN); } + + + dist = getcelldist(lf->cell, l->cell); + if (dist > 1) { + bonus -= (dist*2); + } + // did you spot them? if (skillcheckvs(lf, SC_SEARCH, bonus, l, SC_STEALTH, f->val[0])) { addflag(lf->flags, F_SPOTTED, l->id, NA, NA, NULL); @@ -10191,71 +10863,50 @@ void turneffectslf(lifeform_t *lf) { for (o = lf->cell->obpile->first ; o ; o = o->next) { f = hasflag(o->flags, F_WALKDAM); if (f) { - int dam; - flag_t *fromlfflag; - lifeform_t *fromlf = NULL; - char damstring[BUFLEN]; - - dam = roll(f->text); - getobname(o, buf, o->amt); - - fromlfflag = hasflag(o->flags, F_CREATEDBY); - if (fromlfflag) { - sprintf(damstring, "%s^created by %s",buf, fromlfflag->text); - } else { - strcpy(damstring, buf); - } - - - dam = losehp(lf, dam, f->val[0], fromlf, damstring); - if (dam > 0) { - if (f->val[0] == DT_POISONGAS) { - if (isplayer(lf) || cansee(player, lf)) { - char lfname[BUFLEN]; - getlfname(lf, lfname); - msg("%s choke%s on %s!", lfname, isplayer(lf) ? "" : "s", buf); - } - } else { - if (isplayer(lf)) { - msg("%s %ss you!", buf, getattackverb(NULL, NULL, f->val[0], dam,lf->maxhp)); - } else if (cansee(player, lf)) { - char lfname[BUFLEN]; - getlfname(lf, lfname); - msg("%s %ss %s!", buf, getattackverb(NULL, NULL, f->val[0], dam,lf->maxhp), lfname); - } - } - } - - // some things get your boots too! - if (!isdead(lf)) { - object_t *boots; - boots = getequippedob(lf->pack, BP_FEET); - if (boots) { - switch (f->val[0]) { - case DT_ACID: - case DT_FIRE: - case DT_WATER: - takedamage(boots, dam, f->val[0]); - break; - default: - break; - } - } else { - switch (f->val[0]) { - case DT_WATER: - if (isplayer(lf) && hasbp(lf, BP_FEET)) { - msg("Your feet get wet."); - } - break; - default: - break; - } - } - } + applywalkdam(lf, roll(f->text), f->val[0], o); } + + // for flags which can occur multiple times + for (f = o->flags->first ; f ; f = f->next) { + if (f->id == F_WALKDAMBP) { + object_t *armour; + int dam; + enum BODYPART bp; + enum DAMTYPE damtype; + + + bp = f->val[0]; + damtype = f->val[1]; + dam = roll(f->text); + + getobname(o, buf, o->amt); + + // some things get your armour too! + armour = getouterequippedob(lf, bp); + if (armour) { + takedamage(armour, dam, damtype); + } else { + if (f->val[2] == FALLTHRU) { + // certain combinations might give announcements... + switch (damtype) { + case DT_WATER: + if ((bp == BP_FEET) && isplayer(lf) && hasbp(lf, bp)) { + msg("Your %s get wet.", getbodypartname(bp)); + } + break; + default: + break; + } + // apply damage to lf instead. + applywalkdam(lf, roll(f->text), f->val[1], o); + } + } + } + } // end foreach object flag } if (isdead(lf)) return; + for (f = lf->flags->first ; f ; f = nextf) { nextf = f->next; // remove impossible flags @@ -10559,6 +11210,11 @@ int usestairs(lifeform_t *lf, object_t *o) { getlfname(lf, lfname); getobname(o, obname, 1); + if (initiatemove(lf, NULL, NULL)) { + // failed? + return B_FALSE; + } + curmap = lf->cell->map; f = hasflag(o->flags, F_CLIMBABLE); @@ -10607,13 +11263,15 @@ int usestairs(lifeform_t *lf, object_t *o) { } // find adjacent allies or enemies which will follow you - for (dir = DC_N; dir <= DC_NW; dir++) { - cell_t *c; - c = getcellindir(lf->cell, dir); - if (c && c->lf) { - if (areallies(lf, c->lf) || areenemies(lf, c->lf)) { - adjally[nadjallies] = c->lf; - nadjallies++; + if (isplayer(lf)) { + for (dir = DC_N; dir <= DC_NW; dir++) { + cell_t *c; + c = getcellindir(lf->cell, dir); + if (c && c->lf) { + if (areallies(lf, c->lf) || areenemies(lf, c->lf)) { + adjally[nadjallies] = c->lf; + nadjallies++; + } } } } @@ -10665,16 +11323,18 @@ int usestairs(lifeform_t *lf, object_t *o) { if (f) f->known = B_KNOWN; } // move player to new map - moveto(lf, newcell, B_TRUE); + moveto(lf, newcell, B_TRUE, B_TRUE); taketime(lf, getmovespeed(lf)); - // move adjacent allies too + // move adjacent allies/monsters too for (n = 0; n < nadjallies; n++) { cell_t *c; c = getrandomadjcell(newcell, WE_WALKABLE, B_ALLOWEXPAND); if (c) { - movelf(adjally[n], c); - taketime(adjally[n], getmovespeed(adjally[n])); + if (!initiatemove(adjally[n], NULL, NULL)) { + movelf(adjally[n], c); + taketime(adjally[n], getmovespeed(adjally[n])); + } } } } else { @@ -10815,18 +11475,9 @@ int validateraces(void) { } } } else if (f->id == F_HITCONFER) { - if (f->val[0] == F_POISONED) { - flag_t *ff; - ff = lfhasflag(lf, F_HITPOISONTYPE); - if (ff) { - if ((ff->val[0] == NA) || (ff->val[1] == NA)) { - printf("ERROR in race '%s' - F_HITPOISONTYPE incomplete.\n", r->name); - goterror = B_TRUE; - } - } else { - printf("ERROR in race '%s' - has HITCONFER POISONED, but lacking F_HITPOISONTYPE.\n", r->name); - goterror = B_TRUE; - } + if (!lfhasflag(lf, F_HITCONFERVALS)) { + printf("ERROR in race '%s' - F_HITCONFER, but no HITCONFERVALS defined.\n", r->name); + goterror = B_TRUE; } } else if (f->id == F_NOISETEXT) { if (f->val[0] == N_FLY) { diff --git a/lf.h b/lf.h index 42e1c5d..020a463 100644 --- a/lf.h +++ b/lf.h @@ -3,9 +3,11 @@ lifeform_t *addlf(cell_t *cell, enum RACE rid, int level); lifeform_t *real_addlf(cell_t *cell, enum RACE rid, int level, int controller); job_t *addjob(enum JOB id, char *name); -race_t *addrace(enum RACE id, char *name, float weight, char glyph, int glyphcolour, enum MATERIAL mat); +race_t *addrace(enum RACE id, char *name, float weight, char glyph, int glyphcolour, enum MATERIAL mat, enum RACECLASS raceclass); +raceclass_t *addraceclass(enum RACECLASS id, char *name, char *pluralname, enum SKILL skill); skill_t *addskill(enum SKILL id, char *name, char *desc); void adjustdamlf(lifeform_t *lf, int *amt, enum DAMTYPE damtype); +void applywalkdam(lifeform_t *lf, int dam, enum DAMTYPE damtype, object_t *o); int areallies(lifeform_t *lf1, lifeform_t *lf2); int areenemies(lifeform_t *lf1, lifeform_t *lf2); void autoskill(lifeform_t *lf); @@ -30,10 +32,12 @@ int canweild(lifeform_t *lf, object_t *o); int cantakeoff(lifeform_t *lf, object_t *o); int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *targob, cell_t *targcell); void checkxp(enum RACE rid); +float comparelfs(lifeform_t *lf1, lifeform_t *lf2); int countmoney(lifeform_t *lf); int countnearbyallies(lifeform_t *lf); void debug(lifeform_t *lf); void die(lifeform_t *lf); +void dumplev(void); void dumplf(void); void dumpxp(void); int eat(lifeform_t *lf, object_t *o); @@ -46,6 +50,7 @@ job_t *findjobbyname(char *name); lifeform_t *findlf(map_t *m, int lfid); race_t *findrace(enum RACE id); race_t *findracebyname(char *name); +raceclass_t *findraceclass(enum RACECLASS id); skill_t *findskill(enum SKILL id); skill_t *findskillbyname(char *name); enum SKILLLEVEL findskilllevbyname(char *name); @@ -65,6 +70,7 @@ int getattackspeed(lifeform_t *lf); int getattpoints(lifeform_t *lf); int getattr(lifeform_t *lf, enum ATTRIB attr); int real_getattr(lifeform_t *lf, enum ATTRIB attr, int ignoreattrset); +int getavgdam(lifeform_t *lf, int forxp); int getevasion(lifeform_t *lf); object_t *getbestthrowmissile(lifeform_t *lf); object_t *getbestweapon(lifeform_t *lf); @@ -78,6 +84,8 @@ lifeform_t *getguntarget(lifeform_t *lf); int getguntargetid(lifeform_t *lf); //int gethealtime(lifeform_t *lf); int gethearingrange(lifeform_t *lf); +int gethidemodifier(lifeform_t *lf); +int gethitdice(lifeform_t *lf); int gethppct(lifeform_t *lf); enum HUNGER gethungerlevel(int hunger); char * gethungername(enum HUNGER hunger, char *buf); @@ -87,10 +95,12 @@ int getlfaccuracy(lifeform_t *lf, object_t *wep); enum LFCONDITION getlfcondition(lifeform_t *lf); int getnightvisrange(lifeform_t *lf); char *getlfconditionname(enum LFCONDITION cond); +object_t *getouterequippedob(lifeform_t *lf, enum BODYPART bp); enum LFCONDITION getseenlfconditioncutoff(lifeform_t *lf); char *getseenlfconditionname(lifeform_t *lf, lifeform_t *viewer); glyph_t *getlfglyph(lifeform_t *lf); enum MATERIAL getlfmaterial(lifeform_t *lf); +enum SKILLLEVEL getlorelevel(lifeform_t *lf, enum RACECLASS rcid); float getmaxcarryweight(lifeform_t *lf); float getmaxliftweight(lifeform_t *lf); int getmaxmp(lifeform_t *lf); @@ -113,6 +123,7 @@ char *getplayernamefull(char *buf); int getpoisondamchance(enum POISONTYPE ptype); char *getpoisondamverb(enum POISONTYPE ptype); char *getpoisonname(enum POISONTYPE ptype); +int getraceclass(lifeform_t *lf); int getracerarity(enum RACE rid); object_t *getrandomarmour(lifeform_t *lf); //int getrandommonlevel(int depth); @@ -169,6 +180,7 @@ int isgenius(lifeform_t *lf); int isimmobile(lifeform_t *lf); flag_t *isimmuneto(flagpile_t *fp, enum DAMTYPE dt); int isingunrange(lifeform_t *lf, cell_t *where); +int isloreskill(enum SKILL skid); int ismaxedskill(lifeform_t *lf, enum SKILL skid); int ispeaceful(lifeform_t *lf); int ispetof(lifeform_t *lf, lifeform_t *owner); @@ -188,8 +200,10 @@ void losemp(lifeform_t *lf, int amt); void makefriendly(lifeform_t *lf, int howlong); void makenauseated(lifeform_t *lf, int amt, int howlong); void makenoise(lifeform_t *lf, enum NOISETYPE nid); +void makepeaceful(lifeform_t *lf); lifeform_t *makezombie(object_t *o); void mayusespellschool(flagpile_t *fp, enum SPELLSCHOOL ss, enum FLAG how); +int meetsattreq(lifeform_t *lf, flag_t *f, object_t *o); int modattr(lifeform_t *lf, enum ATTRIB attr, int amt); void modhunger(lifeform_t *lf, int amt); float modifybystat(float num, lifeform_t *lf, enum ATTRIB att); diff --git a/log.txt b/log.txt index c2ccb4e..09efb40 100644 --- a/log.txt +++ b/log.txt @@ -8,6 +8,124 @@ xxx xxx xxx xxx +xxx +xxx +xxx +xxx +xxx +xxx +finding random lf with rarity val 92-100 + +-> possibility: kobold, rarity=95 +-> possibility: xat, rarity=95 +-> possibility: giant bat, rarity=95 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=95 +got 5 possibilities. +finding random lf with rarity val 92-100 + +-> possibility: kobold, rarity=95 +-> possibility: xat, rarity=95 +-> possibility: giant bat, rarity=95 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=95 +got 5 possibilities. +finding random lf with rarity val 92-100 + +-> possibility: kobold, rarity=95 +-> possibility: xat, rarity=95 +-> possibility: giant bat, rarity=95 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=95 +got 5 possibilities. +finding random lf with rarity val 92-100 + +-> possibility: kobold, rarity=95 +-> possibility: xat, rarity=95 +-> possibility: giant bat, rarity=95 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=95 +got 5 possibilities. +finding random lf with rarity val 92-100 + +-> possibility: kobold, rarity=95 +-> possibility: xat, rarity=95 +-> possibility: giant bat, rarity=95 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=95 +got 5 possibilities. +finding random lf with rarity val 92-100 + +-> possibility: kobold, rarity=95 +-> possibility: xat, rarity=95 +-> possibility: giant bat, rarity=95 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=95 +got 5 possibilities. +finding random lf with rarity val 92-100 + +-> possibility: kobold, rarity=95 +-> possibility: xat, rarity=95 +-> possibility: giant bat, rarity=95 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=95 +got 5 possibilities. +finding random lf with rarity val 92-100 + +-> possibility: kobold, rarity=95 +-> possibility: xat, rarity=95 +-> possibility: giant bat, rarity=95 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=95 +got 5 possibilities. +finding random lf with rarity val 92-100 + +-> possibility: kobold, rarity=95 +-> possibility: xat, rarity=95 +-> possibility: giant bat, rarity=95 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=95 +got 5 possibilities. +finding random lf with rarity val 92-100 + +-> possibility: kobold, rarity=95 +-> possibility: xat, rarity=95 +-> possibility: giant bat, rarity=95 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=95 +got 5 possibilities. +finding random lf with rarity val 92-100 + +-> possibility: kobold, rarity=95 +-> possibility: xat, rarity=95 +-> possibility: giant bat, rarity=95 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=95 +got 5 possibilities. +finding random lf with rarity val 92-100 + +-> possibility: kobold, rarity=95 +-> possibility: xat, rarity=95 +-> possibility: giant bat, rarity=95 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=95 +got 5 possibilities. +finding random lf with rarity val 92-100 + +-> possibility: kobold, rarity=95 +-> possibility: xat, rarity=95 +-> possibility: giant bat, rarity=95 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=95 +got 5 possibilities. +finding random lf with rarity val 92-100 + +-> possibility: kobold, rarity=95 +-> possibility: xat, rarity=95 +-> possibility: giant bat, rarity=95 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=95 +got 5 possibilities. finding random lf with rarity val 92-100 -> possibility: kobold, rarity=95 @@ -97,3443 +215,70 @@ finding random lf with rarity val 92-100 -> possibility: giant rat, rarity=95 got 5 possibilities. rollhitdice() - rolling 2d4 + 2 -rollhitdice() - mod is +0% -rollhitdice() ---- die 1/2 == 6 -rollhitdice() ---- die 2/2 == 6 -TOTAL: 12 +rollhitdice() - mod is +54% +rollhitdice() ---- die 1/2 == 5 +rollhitdice() ---- die 2/2 == 3 +TOTAL: 8 -> modified to: 12 test givejob() starting. -processing normal flag: 211 -processing normal flag: 163 -processing normal flag: 163 -processing normal flag: 163 -processing normal flag: 163 -processing normal flag: 163 -processing normal flag: 163 -processing normal flag: 163 -processing normal flag: 163 -processing normal flag: 163 -processing normal flag: 163 -processing normal flag: 163 -processing normal flag: 163 -processing normal flag: 164 -processing normal flag: 164 -processing normal flag: 164 -processing normal flag: 164 -processing normal flag: 164 -processing normal flag: 164 -processing normal flag: 164 -processing normal flag: 162 -processing normal flag: 162 -processing normal flag: 162 -processing normal flag: 162 -processing normal flag: 162 -processing normal flag: 162 -processing normal flag: 162 -processing normal flag: 162 -processing normal flag: 162 -processing normal flag: 162 -processing normal flag: 162 -processing normal flag: 162 -processing normal flag: 162 -processing normal flag: 162 -processing normal flag: 162 -processing normal flag: 162 -processing normal flag: 162 -processing normal flag: 162 -processing normal flag: 162 -processing normal flag: 162 -processing normal flag: 162 -processing normal flag: 162 -processing normal flag: 162 -processing normal flag: 162 -processing normal flag: 162 -processing normal flag: 162 -processing normal flag: 162 -processing normal flag: 162 -processing normal flag: 162 -processing normal flag: 162 -processing normal flag: 162 -processing normal flag: 162 -processing normal flag: 162 -processing normal flag: 162 -processing normal flag: 243 -processing normal flag: 243 -processing normal flag: 243 -processing normal flag: 243 -processing normal flag: 243 -processing normal flag: 243 -processing normal flag: 243 -processing normal flag: 243 -processing normal flag: 243 -processing normal flag: 243 -processing normal flag: 243 -processing normal flag: 243 -processing normal flag: 243 -processing normal flag: 243 -processing normal flag: 243 -processing normal flag: 243 -processing normal flag: 243 -processing normal flag: 243 -processing normal flag: 243 -processing normal flag: 164 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 164 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 164 -processing normal flag: 241 -processing normal flag: 164 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 164 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 164 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 164 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 164 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 164 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 -processing normal flag: 241 +processing normal flag: 171 +processing normal flag: 171 +processing normal flag: 171 +processing normal flag: 220 +processing normal flag: 221 +processing normal flag: 176 +processing normal flag: 176 +processing normal flag: 176 +processing normal flag: 172 +processing normal flag: 172 +processing normal flag: 170 +processing normal flag: 170 +processing normal flag: 337 +processing normal flag: 337 +processing normal flag: 337 +processing normal flag: 172 +processing normal flag: 251 +processing normal flag: 251 +processing normal flag: 251 +processing normal flag: 251 +processing normal flag: 251 +processing normal flag: 251 +processing normal flag: 251 +processing normal flag: 251 +processing normal flag: 251 +processing normal flag: 251 +processing normal flag: 251 +processing normal flag: 251 +processing normal flag: 251 +processing normal flag: 251 +processing normal flag: 251 +processing normal flag: 251 +processing normal flag: 251 +processing normal flag: 251 +processing normal flag: 251 +processing normal flag: 251 +processing normal flag: 251 +processing normal flag: 251 +processing normal flag: 251 +processing normal flag: 251 +processing normal flag: 251 +processing normal flag: 251 +processing normal flag: 251 +processing normal flag: 251 +processing normal flag: 251 +processing normal flag: 251 +processing normal flag: 251 +processing normal flag: 251 +processing normal flag: 251 +processing normal flag: 251 +processing normal flag: 251 +processing normal flag: 326 +processing normal flag: 158 test -xxx -xxx -xxx -xxx -xxx -finding random lf with rarity val 65-100 - --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: hobgoblin, rarity=73 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 39 possibilities. -finding random lf with rarity val 65-100 - --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: hobgoblin, rarity=73 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 39 possibilities. -finding random lf with rarity val 65-100 - --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: hobgoblin, rarity=73 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 39 possibilities. -finding random lf with rarity val 65-100 - --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: hobgoblin, rarity=73 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 39 possibilities. -finding random lf with rarity val 65-100 - --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: hobgoblin, rarity=73 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 39 possibilities. -finding random lf with rarity val 65-100 - --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: hobgoblin, rarity=73 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 39 possibilities. -finding random lf with rarity val 65-100 - --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: hobgoblin, rarity=73 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 39 possibilities. -finding random lf with rarity val 65-100 - --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: hobgoblin, rarity=73 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 39 possibilities. -finding random lf with rarity val 65-100 - --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: hobgoblin, rarity=73 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 39 possibilities. -finding random lf with rarity val 65-100 - --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: hobgoblin, rarity=73 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 39 possibilities. -finding random lf with rarity val 65-100 - --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: hobgoblin, rarity=73 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 39 possibilities. -finding random lf with rarity val 65-100 - --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: hobgoblin, rarity=73 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 39 possibilities. -finding random lf with rarity val 65-100 - --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: hobgoblin, rarity=73 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 39 possibilities. -nwantflags is 0 -initial dam[0] = 0 -adjusted for lf to dam[0] = 0 -reduced by armour to dam[0] = 0 -initial dam[0] = 105 -adjusted for lf to dam[0] = 105 -reduced by armour to dam[0] = 105 -initial dam[0] = 3 -adjusted for lf to dam[0] = 3 -reduced by armour to dam[0] = 2 -initial dam[0] = 102 -adjusted for lf to dam[0] = 102 -reduced by armour to dam[0] = 82 -initial dam[0] = 2 -adjusted for lf to dam[0] = 2 -reduced by armour to dam[0] = 1 -initial dam[0] = 2 -adjusted for lf to dam[0] = 2 -reduced by armour to dam[0] = 1 -initial dam[0] = 206 -adjusted for lf to dam[0] = 206 -reduced by armour to dam[0] = 178 -initial dam[0] = 102 -adjusted for lf to dam[0] = 102 -reduced by armour to dam[0] = 102 -nwantflags is 0 -nwantflags is 0 -nwantflags is 0 -xxx -xxx -xxx -xxx -xxx -xxx -xxx -xxx -xxx -finding random lf with rarity val 62-100 - --> possibility: bugbear, rarity=63 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 42 possibilities. -finding random lf with rarity val 62-100 - --> possibility: bugbear, rarity=63 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 42 possibilities. -finding random lf with rarity val 62-100 - --> possibility: bugbear, rarity=63 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 42 possibilities. -finding random lf with rarity val 62-100 - --> possibility: bugbear, rarity=63 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 42 possibilities. -finding random lf with rarity val 62-100 - --> possibility: bugbear, rarity=63 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 42 possibilities. -finding random lf with rarity val 62-100 - --> possibility: bugbear, rarity=63 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 42 possibilities. -finding random lf with rarity val 62-100 - --> possibility: bugbear, rarity=63 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 42 possibilities. -finding random lf with rarity val 62-100 - --> possibility: bugbear, rarity=63 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 42 possibilities. -finding random lf with rarity val 62-100 - --> possibility: bugbear, rarity=63 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 42 possibilities. -finding random lf with rarity val 62-100 - --> possibility: bugbear, rarity=63 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 42 possibilities. -finding random lf with rarity val 62-100 - --> possibility: bugbear, rarity=63 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 42 possibilities. -finding random lf with rarity val 62-100 - --> possibility: bugbear, rarity=63 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 42 possibilities. -finding random lf with rarity val 62-100 - --> possibility: bugbear, rarity=63 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 42 possibilities. -finding random lf with rarity val 62-100 - --> possibility: bugbear, rarity=63 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 42 possibilities. -finding random lf with rarity val 62-100 - --> possibility: bugbear, rarity=63 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 42 possibilities. -finding random lf with rarity val 62-100 - --> possibility: bugbear, rarity=63 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 42 possibilities. -finding random lf with rarity val 62-100 - --> possibility: bugbear, rarity=63 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 42 possibilities. -finding random lf with rarity val 62-100 - --> possibility: bugbear, rarity=63 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 42 possibilities. -finding random lf with rarity val 62-100 - --> possibility: bugbear, rarity=63 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 42 possibilities. -finding random lf with rarity val 62-100 - --> possibility: bugbear, rarity=63 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 42 possibilities. -finding random lf with rarity val 62-100 - --> possibility: bugbear, rarity=63 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 42 possibilities. -finding random lf with rarity val 62-100 - --> possibility: bugbear, rarity=63 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 42 possibilities. -finding random lf with rarity val 62-100 - --> possibility: bugbear, rarity=63 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 42 possibilities. -finding random lf with rarity val 62-100 - --> possibility: bugbear, rarity=63 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 42 possibilities. -finding random lf with rarity val 62-100 - --> possibility: bugbear, rarity=63 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 42 possibilities. -finding random lf with rarity val 62-100 - --> possibility: bugbear, rarity=63 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 42 possibilities. -initial dam[0] = 5 -adjusted for lf to dam[0] = 5 -reduced by armour to dam[0] = 4 -initial dam[0] = 1 -adjusted for lf to dam[0] = 1 -reduced by armour to dam[0] = 1 -initial dam[0] = 4 -adjusted for lf to dam[0] = 4 -reduced by armour to dam[0] = 3 -.oO { cant cast telekinesis - not valid for given purpose } -.oO { cant cast telekinesis - not valid for given purpose } -.oO { cant cast telekinesis - not valid for given purpose } -xxx -xxx -xxx -xxx -xxx -xxx -finding random lf with rarity val 50-100 - --> possibility: human, rarity=60 --> possibility: beholder, rarity=50 --> possibility: bugbear, rarity=63 --> possibility: cockatrice, rarity=50 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: hill giant, rarity=55 --> possibility: fire giant, rarity=50 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: hobgoblin warrior, rarity=60 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: lurking horror, rarity=50 --> possibility: ogre, rarity=60 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghast, rarity=55 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 51 possibilities. -finding random lf with rarity val 50-100 - --> possibility: human, rarity=60 --> possibility: beholder, rarity=50 --> possibility: bugbear, rarity=63 --> possibility: cockatrice, rarity=50 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: hill giant, rarity=55 --> possibility: fire giant, rarity=50 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: hobgoblin warrior, rarity=60 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: lurking horror, rarity=50 --> possibility: ogre, rarity=60 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghast, rarity=55 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 51 possibilities. -finding random lf with rarity val 50-100 - --> possibility: human, rarity=60 --> possibility: beholder, rarity=50 --> possibility: bugbear, rarity=63 --> possibility: cockatrice, rarity=50 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: hill giant, rarity=55 --> possibility: fire giant, rarity=50 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: hobgoblin warrior, rarity=60 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: lurking horror, rarity=50 --> possibility: ogre, rarity=60 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghast, rarity=55 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 51 possibilities. -finding random lf with rarity val 50-100 - --> possibility: human, rarity=60 --> possibility: beholder, rarity=50 --> possibility: bugbear, rarity=63 --> possibility: cockatrice, rarity=50 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: hill giant, rarity=55 --> possibility: fire giant, rarity=50 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: hobgoblin warrior, rarity=60 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: lurking horror, rarity=50 --> possibility: ogre, rarity=60 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghast, rarity=55 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 51 possibilities. -finding random lf with rarity val 50-100 - --> possibility: human, rarity=60 --> possibility: beholder, rarity=50 --> possibility: bugbear, rarity=63 --> possibility: cockatrice, rarity=50 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: hill giant, rarity=55 --> possibility: fire giant, rarity=50 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: hobgoblin warrior, rarity=60 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: lurking horror, rarity=50 --> possibility: ogre, rarity=60 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghast, rarity=55 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 51 possibilities. -finding random lf with rarity val 50-100 - --> possibility: human, rarity=60 --> possibility: beholder, rarity=50 --> possibility: bugbear, rarity=63 --> possibility: cockatrice, rarity=50 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: hill giant, rarity=55 --> possibility: fire giant, rarity=50 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: hobgoblin warrior, rarity=60 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: lurking horror, rarity=50 --> possibility: ogre, rarity=60 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghast, rarity=55 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 51 possibilities. -finding random lf with rarity val 50-100 - --> possibility: human, rarity=60 --> possibility: beholder, rarity=50 --> possibility: bugbear, rarity=63 --> possibility: cockatrice, rarity=50 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: hill giant, rarity=55 --> possibility: fire giant, rarity=50 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: hobgoblin warrior, rarity=60 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: lurking horror, rarity=50 --> possibility: ogre, rarity=60 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghast, rarity=55 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 51 possibilities. -finding random lf with rarity val 50-100 - --> possibility: human, rarity=60 --> possibility: beholder, rarity=50 --> possibility: bugbear, rarity=63 --> possibility: cockatrice, rarity=50 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: hill giant, rarity=55 --> possibility: fire giant, rarity=50 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: hobgoblin warrior, rarity=60 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: lurking horror, rarity=50 --> possibility: ogre, rarity=60 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghast, rarity=55 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 51 possibilities. -finding random lf with rarity val 50-100 - --> possibility: human, rarity=60 --> possibility: beholder, rarity=50 --> possibility: bugbear, rarity=63 --> possibility: cockatrice, rarity=50 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: hill giant, rarity=55 --> possibility: fire giant, rarity=50 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: hobgoblin warrior, rarity=60 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: lurking horror, rarity=50 --> possibility: ogre, rarity=60 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghast, rarity=55 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 51 possibilities. -finding random lf with rarity val 50-100 - --> possibility: human, rarity=60 --> possibility: beholder, rarity=50 --> possibility: bugbear, rarity=63 --> possibility: cockatrice, rarity=50 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: hill giant, rarity=55 --> possibility: fire giant, rarity=50 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: hobgoblin warrior, rarity=60 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: lurking horror, rarity=50 --> possibility: ogre, rarity=60 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghast, rarity=55 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 51 possibilities. -finding random lf with rarity val 50-100 - --> possibility: human, rarity=60 --> possibility: beholder, rarity=50 --> possibility: bugbear, rarity=63 --> possibility: cockatrice, rarity=50 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: hill giant, rarity=55 --> possibility: fire giant, rarity=50 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: hobgoblin warrior, rarity=60 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: lurking horror, rarity=50 --> possibility: ogre, rarity=60 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghast, rarity=55 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 51 possibilities. -finding random lf with rarity val 50-100 - --> possibility: human, rarity=60 --> possibility: beholder, rarity=50 --> possibility: bugbear, rarity=63 --> possibility: cockatrice, rarity=50 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: hill giant, rarity=55 --> possibility: fire giant, rarity=50 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: hobgoblin warrior, rarity=60 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: lurking horror, rarity=50 --> possibility: ogre, rarity=60 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghast, rarity=55 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 51 possibilities. -finding random lf with rarity val 50-100 - --> possibility: human, rarity=60 --> possibility: beholder, rarity=50 --> possibility: bugbear, rarity=63 --> possibility: cockatrice, rarity=50 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: hill giant, rarity=55 --> possibility: fire giant, rarity=50 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: hobgoblin warrior, rarity=60 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: lurking horror, rarity=50 --> possibility: ogre, rarity=60 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghast, rarity=55 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 51 possibilities. -finding random lf with rarity val 50-100 - --> possibility: human, rarity=60 --> possibility: beholder, rarity=50 --> possibility: bugbear, rarity=63 --> possibility: cockatrice, rarity=50 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: hill giant, rarity=55 --> possibility: fire giant, rarity=50 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: hobgoblin warrior, rarity=60 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: lurking horror, rarity=50 --> possibility: ogre, rarity=60 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghast, rarity=55 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 51 possibilities. -finding random lf with rarity val 50-100 - --> possibility: human, rarity=60 --> possibility: beholder, rarity=50 --> possibility: bugbear, rarity=63 --> possibility: cockatrice, rarity=50 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: hill giant, rarity=55 --> possibility: fire giant, rarity=50 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: hobgoblin warrior, rarity=60 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: lurking horror, rarity=50 --> possibility: ogre, rarity=60 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghast, rarity=55 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 51 possibilities. -finding random lf with rarity val 50-100 - --> possibility: human, rarity=60 --> possibility: beholder, rarity=50 --> possibility: bugbear, rarity=63 --> possibility: cockatrice, rarity=50 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: hill giant, rarity=55 --> possibility: fire giant, rarity=50 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: hobgoblin warrior, rarity=60 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: lurking horror, rarity=50 --> possibility: ogre, rarity=60 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghast, rarity=55 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 51 possibilities. -finding random lf with rarity val 50-100 - --> possibility: human, rarity=60 --> possibility: beholder, rarity=50 --> possibility: bugbear, rarity=63 --> possibility: cockatrice, rarity=50 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: hill giant, rarity=55 --> possibility: fire giant, rarity=50 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: hobgoblin warrior, rarity=60 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: lurking horror, rarity=50 --> possibility: ogre, rarity=60 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghast, rarity=55 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 51 possibilities. -finding random lf with rarity val 50-100 - --> possibility: human, rarity=60 --> possibility: beholder, rarity=50 --> possibility: bugbear, rarity=63 --> possibility: cockatrice, rarity=50 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: hill giant, rarity=55 --> possibility: fire giant, rarity=50 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: hobgoblin warrior, rarity=60 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: lurking horror, rarity=50 --> possibility: ogre, rarity=60 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghast, rarity=55 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 51 possibilities. -finding random lf with rarity val 50-100 - --> possibility: human, rarity=60 --> possibility: beholder, rarity=50 --> possibility: bugbear, rarity=63 --> possibility: cockatrice, rarity=50 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: hill giant, rarity=55 --> possibility: fire giant, rarity=50 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: hobgoblin warrior, rarity=60 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: lurking horror, rarity=50 --> possibility: ogre, rarity=60 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghast, rarity=55 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 51 possibilities. -finding random lf with rarity val 50-100 - --> possibility: human, rarity=60 --> possibility: beholder, rarity=50 --> possibility: bugbear, rarity=63 --> possibility: cockatrice, rarity=50 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: hill giant, rarity=55 --> possibility: fire giant, rarity=50 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: hobgoblin warrior, rarity=60 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: lurking horror, rarity=50 --> possibility: ogre, rarity=60 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghast, rarity=55 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 51 possibilities. -finding random lf with rarity val 50-100 - --> possibility: human, rarity=60 --> possibility: beholder, rarity=50 --> possibility: bugbear, rarity=63 --> possibility: cockatrice, rarity=50 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: hill giant, rarity=55 --> possibility: fire giant, rarity=50 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: hobgoblin warrior, rarity=60 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: lurking horror, rarity=50 --> possibility: ogre, rarity=60 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghast, rarity=55 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 51 possibilities. -finding random lf with rarity val 50-100 - --> possibility: human, rarity=60 --> possibility: beholder, rarity=50 --> possibility: bugbear, rarity=63 --> possibility: cockatrice, rarity=50 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: hill giant, rarity=55 --> possibility: fire giant, rarity=50 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: hobgoblin warrior, rarity=60 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: lurking horror, rarity=50 --> possibility: ogre, rarity=60 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghast, rarity=55 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 51 possibilities. -finding random lf with rarity val 50-100 - --> possibility: human, rarity=60 --> possibility: beholder, rarity=50 --> possibility: bugbear, rarity=63 --> possibility: cockatrice, rarity=50 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: hill giant, rarity=55 --> possibility: fire giant, rarity=50 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: hobgoblin warrior, rarity=60 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: lurking horror, rarity=50 --> possibility: ogre, rarity=60 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghast, rarity=55 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 51 possibilities. -finding random lf with rarity val 50-100 - --> possibility: human, rarity=60 --> possibility: beholder, rarity=50 --> possibility: bugbear, rarity=63 --> possibility: cockatrice, rarity=50 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: hill giant, rarity=55 --> possibility: fire giant, rarity=50 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: hobgoblin warrior, rarity=60 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: lurking horror, rarity=50 --> possibility: ogre, rarity=60 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghast, rarity=55 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 51 possibilities. -finding random lf with rarity val 50-100 - --> possibility: human, rarity=60 --> possibility: beholder, rarity=50 --> possibility: bugbear, rarity=63 --> possibility: cockatrice, rarity=50 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: hill giant, rarity=55 --> possibility: fire giant, rarity=50 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: hobgoblin warrior, rarity=60 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: lurking horror, rarity=50 --> possibility: ogre, rarity=60 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghast, rarity=55 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 51 possibilities. -finding random lf with rarity val 50-100 - --> possibility: human, rarity=60 --> possibility: beholder, rarity=50 --> possibility: bugbear, rarity=63 --> possibility: cockatrice, rarity=50 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: hill giant, rarity=55 --> possibility: fire giant, rarity=50 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: hobgoblin warrior, rarity=60 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: lurking horror, rarity=50 --> possibility: ogre, rarity=60 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghast, rarity=55 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 51 possibilities. -finding random lf with rarity val 50-100 - --> possibility: human, rarity=60 --> possibility: beholder, rarity=50 --> possibility: bugbear, rarity=63 --> possibility: cockatrice, rarity=50 --> possibility: darkmantle, rarity=65 --> possibility: eyebat, rarity=80 --> possibility: hill giant, rarity=55 --> possibility: fire giant, rarity=50 --> possibility: gnoll, rarity=72 --> possibility: gnoll huntmaster, rarity=68 --> possibility: gnoll marauder, rarity=65 --> possibility: goblin, rarity=87 --> possibility: goblin warrior, rarity=75 --> possibility: goblin sharpshooter, rarity=70 --> possibility: goblin hexer, rarity=63 --> possibility: hobgoblin, rarity=73 --> possibility: hobgoblin warrior, rarity=60 --> possibility: kobold, rarity=95 --> possibility: troglodyte, rarity=78 --> possibility: lizardman, rarity=72 --> possibility: lurking horror, rarity=50 --> possibility: ogre, rarity=60 --> possibility: orc, rarity=78 --> possibility: orc warrior, rarity=70 --> possibility: ork, rarity=81 --> possibility: poltergeist, rarity=75 --> possibility: shadowcat, rarity=65 --> possibility: grey ooze, rarity=80 --> possibility: fire sprite, rarity=70 --> possibility: troll, rarity=65 --> possibility: xat, rarity=95 --> possibility: giant bat, rarity=95 --> possibility: giant worker ant, rarity=85 --> possibility: giant soldier ant, rarity=65 --> possibility: young hawk, rarity=75 --> possibility: hawk, rarity=68 --> possibility: blood hawk, rarity=65 --> possibility: frost hawk, rarity=63 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=95 --> possibility: brown snake, rarity=85 --> possibility: wolf, rarity=80 --> possibility: giant fly, rarity=85 --> possibility: giant blowfly, rarity=80 --> possibility: giant centipede, rarity=80 --> possibility: glowbug, rarity=87 --> possibility: zombie, rarity=85 --> possibility: skeleton, rarity=90 --> possibility: ghast, rarity=55 --> possibility: ghost, rarity=72 --> possibility: ghoul, rarity=65 -got 51 possibilities. -.oO { cant cast telekinesis - not valid for given purpose } -.oO { cant cast telekinesis - not valid for given purpose } -initial dam[0] = 6 -adjusted for lf to dam[0] = 6 -reduced by armour to dam[0] = 5 -nwantflags is 0 -initial dam[0] = 7 -adjusted for lf to dam[0] = 7 -reduced by armour to dam[0] = 6 -nwantflags is 0 -.oO { cant cast cold burst - targetting conditions cannot be met } -initial dam[0] = 7 -adjusted for lf to dam[0] = 7 -reduced by armour to dam[0] = 6 -initial dam[1] = 6 -adjusted for lf to dam[1] = 6 -reduced by armour to dam[1] = 5 -.oO { cant cast cold burst - targetting conditions cannot be met } -.oO { cant cast cold burst - targetting conditions cannot be met } -.oO { cant cast cold burst - targetting conditions cannot be met } -.oO { cant cast cold burst - targetting conditions cannot be met } -initial dam[0] = 10 -adjusted for lf to dam[0] = 10 -reduced by armour to dam[0] = 8 -initial dam[1] = 6 -adjusted for lf to dam[1] = 6 -reduced by armour to dam[1] = 5 -.oO { cant cast cold burst - targetting conditions cannot be met } -.oO { cant cast cold burst - targetting conditions cannot be met } -.oO { cant cast cold burst - targetting conditions cannot be met } -.oO { cant cast sleep - specific spell check failed } -.oO { cant cast sleep - specific spell check failed } -.oO { cant cast sleep - specific spell check failed } -.oO { cant cast paralyze - specific spell check failed } -.oO { cant cast sleep - specific spell check failed } -.oO { cant cast paralyze - specific spell check failed } -.oO { cant cast sleep - specific spell check failed } -.oO { cant cast paralyze - specific spell check failed } -initial dam[0] = 6 -adjusted for lf to dam[0] = 6 -reduced by armour to dam[0] = 5 -nwantflags is 0 +rollhitdice() - rolling 1d4 + 1 +rollhitdice() - mod is +54% +rollhitdice() ---- die 1/1 == 4 +TOTAL: 4 + -> modified to: 6 diff --git a/map.c b/map.c index d671cc6..3a64742 100644 --- a/map.c +++ b/map.c @@ -22,6 +22,8 @@ extern glyph_t tempglyph; extern enum OBCLASS sortorder[]; +extern enum ERROR reason; + cell_t *addcell(map_t *m, int x, int y) { cell_t *cell; m->cell[(y*m->w)+x] = malloc(sizeof(cell_t)); @@ -80,7 +82,8 @@ map_t *addmap(void) { } -lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt) { +// when monsters are made during level generation, autogen will be true. otherwise false; +lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int autogen) { lifeform_t *lf = NULL; race_t *r; int db = B_FALSE; @@ -116,7 +119,8 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt) { } } - if (lf->cell->map->beingcreated) { + //if (lf->cell->map->beingcreated) { + if (autogen) { // sometimes start off asleep in new maps if (!lfhasflag(lf, F_DEAF)) { // TODO: base this on the time, and whether monster is nocturnal @@ -124,64 +128,77 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt) { addflag(lf->flags, F_ASLEEP, B_TRUE, NA, NA, NULL); } } + f = lfhasflag(lf, F_STARTHIDDENPCT); + if (f) { + if (rnd(1,100) <= f->val[0]) { + // note: if we start off hidden, we have no hide penalty. + // this is so we can have monsters which start hidden, but + // don't have the 'hide' skill. + addflag(lf->flags, F_HIDING, 0, NA, NA, NULL); + } + } } // appears in groups? - f = hasflag(lf->flags, F_NUMAPPEAR); - if (f) { - // override amount - amt = rnd(f->val[0], f->val[1]); - } - if (amt > 1) { - cell_t *adjcell; - amt--; // we've already added one + if (autogen) { + f = hasflag(lf->flags, F_NUMAPPEAR); + if (f) { + // override amount + amt = rnd(f->val[0], f->val[1]); + } + if (amt > 1) { + cell_t *adjcell; + amt--; // we've already added one - //adjcell = c; - for ( ; amt > 0; amt--) { - lifeform_t *newlf; - // find an adjacent cell to one of the newly added monsters, - // starting with the first one - adjcell = getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND); - // did we find one? - if (!adjcell) break; + //adjcell = c; + for ( ; amt > 0; amt--) { + lifeform_t *newlf; + // find an adjacent cell to one of the newly added monsters, + // starting with the first one + adjcell = getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND); + // did we find one? + if (!adjcell) break; + + newlf = addlf(adjcell, r->id, 1); + if (!newlf) { + break; + } + newlf->born = B_FALSE; + if (lfhasflag(lf, F_ASLEEP)) addflag(newlf->flags, F_ASLEEP, B_TRUE, NA, NA, NULL); + newlf->born = B_TRUE; - newlf = addlf(adjcell, r->id, 1); - if (!newlf) { - break; } - newlf->born = B_FALSE; - if (lfhasflag(lf, F_ASLEEP)) addflag(newlf->flags, F_ASLEEP, B_TRUE, NA, NA, NULL); - newlf->born = B_TRUE; - } } // minons? - f = hasflag(lf->flags, F_MINIONS); - if (f) { - if (rnd(1,100) <= f->val[0]) { - int n; - cell_t *adjcell; - int nminions; - // override amount - nminions = rnd(f->val[1], f->val[2]); + if (autogen) { + f = hasflag(lf->flags, F_MINIONS); + if (f) { + if (rnd(1,100) <= f->val[0]) { + int n; + cell_t *adjcell; + int nminions; + // override amount + nminions = rnd(f->val[1], f->val[2]); - for (n = 0; n < nminions; n++) { - lifeform_t *newlf; - race_t *newr; + for (n = 0; n < nminions; n++) { + lifeform_t *newlf; + race_t *newr; - adjcell = getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND); - if (!adjcell) break; + adjcell = getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND); + if (!adjcell) break; - newr = findracebyname(f->text); - if (!newr) break; + newr = findracebyname(f->text); + if (!newr) break; - newlf = addlf(adjcell, newr->id, 1); - if (!newlf) break; + newlf = addlf(adjcell, newr->id, 1); + if (!newlf) break; - newlf->born = B_FALSE; - if (lfhasflag(lf, F_ASLEEP)) addflag(newlf->flags, F_ASLEEP, B_TRUE, NA, NA, NULL); - newlf->born = B_TRUE; + newlf->born = B_FALSE; + if (lfhasflag(lf, F_ASLEEP)) addflag(newlf->flags, F_ASLEEP, B_TRUE, NA, NA, NULL); + newlf->born = B_TRUE; + } } } } @@ -228,7 +245,7 @@ void addrandomthing(cell_t *c, int obchance) { addrandomob(c); } else { // monster - addmonster(c, R_RANDOM, B_TRUE, 1); + addmonster(c, R_RANDOM, B_TRUE, 1, B_TRUE); } } @@ -454,9 +471,12 @@ void getcellglyph(glyph_t *g, cell_t *c, lifeform_t *viewer) { *g = *(getglyph(o)); } // show dungeon features - o = hasobofclass(c->obpile, OC_DFEATURE); - if (o) { - *g = *(getglyph(o)); + for (o = c->obpile->first ; o ; o = o->next) { + if (o->type->obclass->id == OC_DFEATURE) { + if (!issecretdoor(o)) { + *g = *(getglyph(o)); + } + } } } break; @@ -1938,6 +1958,10 @@ int getobchance(int habitat) { } cell_t *getrandomadjcell(cell_t *c, int wantempty, int allowexpand) { + return real_getrandomadjcell(c, wantempty, allowexpand, NULL); +} + +cell_t *real_getrandomadjcell(cell_t *c, int wantempty, int allowexpand, enum OBTYPE *dontwantob) { int radius = 1; int x,y; cell_t *poss[MAXCANDIDATES]; @@ -1951,24 +1975,44 @@ cell_t *getrandomadjcell(cell_t *c, int wantempty, int allowexpand) { for (x = c->x - radius ; x <= c->x + radius ; x++) { new = getcellat(c->map, x, y); if (new && (getcelldist(c,new) == radius) && haslof(c, new, LOF_WALLSTOP, NULL)) { + enum OBTYPE *badoid; + int ok = B_FALSE; numwithlof++; if (wantempty == WE_EMPTY) { // make sure it's empty if (isempty(new)) { - poss[nposs++] = new; + ok = B_TRUE; } } else if (wantempty == WE_WALKABLE) { if (cellwalkable(NULL, new, NULL)) { - poss[nposs++] = new; + ok = B_TRUE; } } else if (wantempty == WE_PORTAL) { if (cellwalkable(NULL, new, NULL) && !hasenterableobject(new) ) { if (!hasobwithflag(new->obpile, F_DOOR)) { - poss[nposs++] = new; + ok = B_TRUE; } } + } else if (wantempty == WE_NOTWALL) { + if (!new->type->solid){ + ok = B_TRUE; + } } else { // always ok + ok = B_TRUE; + } + + // obs we dont want? + if (dontwantob) { + for (badoid = dontwantob; (*badoid != OT_NONE) ; badoid++) { + if (hasob(new->obpile, *badoid)) { + ok = B_FALSE; + break; + } + } + } + + if (ok) { poss[nposs++] = new; } } @@ -2079,16 +2123,19 @@ void getroomcells(map_t *m, int roomid, cell_t **retcell, int *ncells) { } // returns how slippery this cell is +// if slipob is set, return the most slippery object in it. int getslipperyness(cell_t *c, object_t **slipob) { - object_t *o; + object_t *o,*bestob = NULL; + int bestslip = 0; int totalslip = 0; if (slipob) *slipob = NULL; for (o = c->obpile->first ; o ; o = o->next) { int thisslip; sumflags(o->flags, F_SLIPPERY, &thisslip, NULL, NULL); if (thisslip > 0) { - if (slipob && (*slipob == NULL)) { - *slipob = o; + if (thisslip > bestslip) { + bestob = o; + bestslip = thisslip; } } thisslip *= o->amt; @@ -2097,6 +2144,10 @@ int getslipperyness(cell_t *c, object_t **slipob) { totalslip *= 2; + if (slipob) { + *slipob = bestob; + } + return totalslip; } diff --git a/map.h b/map.h index d49fe35..9b4f072 100644 --- a/map.h +++ b/map.h @@ -2,7 +2,7 @@ cell_t *addcell(map_t *map, int x, int y); map_t *addmap(void); -lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt); +lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int autogen); void addrandomob(cell_t *c); void addrandomthing(cell_t *c, int obchance); int cellhaslos(cell_t *c1, cell_t *dest); @@ -35,6 +35,7 @@ cell_t *getcellindir(cell_t *cell, int dir); int getnewdigdir(cell_t *cell, int lastdir, int turnpct, int *moved); int getobchance(int habitat); cell_t *getrandomadjcell(cell_t *c, int wantempty, int allowexpand); +cell_t *real_getrandomadjcell(cell_t *c, int wantempty, int allowexpand, enum OBTYPE *dontwantob); cell_t *getrandomcell(map_t *map); cell_t *getrandomcelloftype(map_t *map, int id); int getrandomdir(int dirtype); diff --git a/move.c b/move.c index 6ad3693..39621e5 100644 --- a/move.c +++ b/move.c @@ -550,8 +550,11 @@ int moveawayfrom(lifeform_t *lf, cell_t *dst, int dirtype ) { // IMPORTANT: don't modify lf's flagpile during this code! // particularly don't remove flags... -void moveeffects(lifeform_t *lf) { + +// returns TRUE if we displayed a message +int moveeffects(lifeform_t *lf) { flag_t *f; + int didmsg = B_FALSE; if (isbleeding(lf)) { if (rnd(1,2) == 1) { @@ -562,18 +565,29 @@ void moveeffects(lifeform_t *lf) { f = lfhasflag(lf, F_PAIN); if (f) { if (!isdrunk(lf)) { + int dam; if (isplayer(lf)) { msg("Your body is wracked with pain!"); + didmsg = B_TRUE; } else if (cansee(player, lf)) { char lfname[BUFLEN]; getlfname(lf, lfname); msg("%s convulses in pain!",lfname); + didmsg = B_TRUE; } - losehp(lf, roll(f->text), f->val[0], NULL, "extreme pain"); + + if (strlen(f->text)) { + dam = roll(f->text); + } else { + dam = roll("1d2"); + } + losehp(lf, dam, f->val[0], NULL, "extreme pain"); + if (isdead(lf)) return didmsg; } } - if (isdead(lf)) return; + + return didmsg; } @@ -586,6 +600,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) { flag_t *f; int changedlev = B_FALSE; int preroom = -1, postroom = -1; + int prespeed = B_FALSE, postspeed = B_FALSE; getlfname(lf, lfname); @@ -594,8 +609,10 @@ int movelf(lifeform_t *lf, cell_t *newcell) { } // update current cell + room id - lf->cell->lf = NULL; + prespeed = getmovespeed(lf); preroom = lf->cell->roomid; + lf->cell->lf = NULL; + // if required, relink lifeform to new map if (newcell->map != lf->cell->map) { @@ -613,6 +630,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) { // remember new room... postroom = lf->cell->roomid; + postspeed = getmovespeed(lf); // update new cell newcell->lf = lf; @@ -622,7 +640,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) { calclight(lf->cell->map); } - moveeffects(lf); + didmsg = moveeffects(lf); killflagsofid(lf->flags, F_HIDING); @@ -770,16 +788,20 @@ int movelf(lifeform_t *lf, cell_t *newcell) { } } + // status bar + if ((prespeed != postspeed) && isplayer(lf)) { + statdirty = B_TRUE; + } + return didmsg; } // basically this is a warpper for 'movelf' which // does other game things like telling the player // what is here. -int moveto(lifeform_t *lf, cell_t *newcell, int onpurpose) { +int moveto(lifeform_t *lf, cell_t *newcell, int onpurpose, int dontclearmsg) { char lfname[BUFLEN]; int didmsg; - int dontclearmsg = B_FALSE; int predark = B_FALSE,postdark = B_FALSE; if (!onpurpose || !isplayer(lf)) { @@ -1176,6 +1198,145 @@ int pullnextto(lifeform_t *lf, cell_t *c) { return B_FALSE; } + +// do pre-move checks like slipping on stuff in your current cell, +// webs, etc. +// cell can be null if you're using stairs. +int initiatemove(lifeform_t *lf, cell_t *cell, int *didmsg) { + object_t *o, *nexto; + char buf[BUFLEN]; + flag_t *f; + + // check for cursed objects in new cell + animals + // do this AFTER checking if we will move, so that + // they will actually try the move and fail (this lets + // the player find out about the cursed object). + // + // note however that if a monster is chasing a player (ie + // has F_TARGET,player) then they will simply avoid the cursed + // object rather than failing the movement. + if (cell) { + for (o = cell->obpile->first ; o ; o = nexto) { + nexto = o->next; + if (!isplayer(lf)) { + if ((o->blessed == B_CURSED) && lfhasflag(lf, F_ANIMAL) && !isairborne(lf)) { + if (cansee(player, lf)) { + char lfname[BUFLEN]; + getlfname(lf,lfname); + getobname(o, buf, o->amt); + msg("%s %s away from %s!", lfname, isplayer(lf) ? "shy" : "shies", buf); + o->blessknown = B_TRUE; + if (didmsg) *didmsg = B_TRUE; + } + taketime(lf, getmovespeed(lf)); + reason = E_OK; + // avoid this object in future + sprintf(buf, "%ld",o->id); + addflag(lf->flags, F_AVOIDCURSEDOB, NA, NA, NA, buf); + return B_TRUE; + } + } + } + } + + // gravboosted + if (lfhasflag(lf, F_GRAVBOOSTED)) { + // make a saving throw to move + if (!skillcheck(lf, SC_STR, 25, 0)) { + if (isplayer(lf)) { + msg("You try to move but are unable to lift your feet!"); + if (didmsg) *didmsg = B_TRUE; + } else if (cansee(player, lf)) { + char lfname[BUFLEN]; + getlfname(lf, lfname); + msg("%s tries to move but is unable to lift its feet!",lfname); + if (didmsg) *didmsg = B_TRUE; + } + reason = E_OK; + taketime(lf, getmovespeed(lf)); + return B_TRUE; + } + } + + + // sticky objects in current cell? + for (o = lf->cell->obpile->first ; o ; o = nexto) { + nexto = o->next; + + if ((o->type->id == OT_WEB) && (lf->race->baseid == R_SPIDER)) { + continue; + } + + f = hasflag(o->flags, F_RESTRICTMOVEMENT); + if (f) { + char lfname[BUFLEN]; + int diff; + int getsweaker; + getlfname(lf,lfname); + getobname(o, buf, o->amt); + + // for stacks of sticky objects, each one after the first adds + // quarter its difficuly. ie: + // 1 x object with f_sticky:20, difficult is 20 + // 2 x object with f_sticky:20, difficult is 25 + // 3 x object with f_sticky:20, difficult is 30 + // etc + // can you break free? + diff = f->val[0]; + if (o->amt > 1) { + diff = (o->amt - 1) * ((float)f->val[0] / 4.0); + } + getsweaker = f->val[1]; + if (skillcheck(lf, SC_STR, diff, 0)) { + if (isplayer(lf)) { + msg("You tear free from %s!", buf); + if (didmsg) *didmsg = B_TRUE; + } else if (cansee(player, lf)) { + msg("%s tears free from %s!", lfname, buf); + if (didmsg) *didmsg = B_TRUE; + } + killob(o); + continue; + } else { + // failed - object gets a little less sticky + if (isplayer(lf)) { + msg("You struggle in %s!", buf); + if (didmsg) *didmsg = B_TRUE; + } else if (cansee(player, lf)) { + msg("%s struggles in %s!", lfname, buf); + if (didmsg) *didmsg = B_TRUE; + } + + if (getsweaker) { + takedamage(o, 1, DT_DIRECT); + } + + taketime(lf, getmovespeed(lf)); + + reason = E_OK; + return B_TRUE; + } + } + } + + // slipping on something before moving? + if (!isairborne(lf)) { + int slip; + object_t *slipob; + 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; + } + } + return B_FALSE; +} + + + // teleport somewhere, along with puffs of smoke etc int teleportto(lifeform_t *lf, cell_t *c, int wantsmoke) { char buf[BUFLEN]; @@ -1226,6 +1387,7 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) { cell_t *cell; enum ERROR errcode; char buf[BUFLEN]; + int dontclearmsg = B_FALSE; flag_t *f; f = isdrunk(lf); @@ -1240,73 +1402,13 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) { cell = getcellindir(lf->cell, dir); if (canandwillmove(lf, dir, &errcode)) { - object_t *o,*slipob; - int slip; - - // check for cursed objects + animals - // do this AFTER checking if we will move, so that - // they will actually try the move and fail (this lets - // the player find out about the cursed object). - // - // note however that if a monster is chasing a player (ie - // has F_TARGET,player) then they will simply avoid the cursed - // object rather than failing the movement. - for (o = cell->obpile->first ; o ; o = o->next) { - if (!isplayer(lf)) { - if (o->blessed == B_CURSED) { - if (lfhasflag(lf, F_ANIMAL)) { - if (!isairborne(lf)) { - if (cansee(player, lf)) { - char lfname[BUFLEN]; - getlfname(lf,lfname); - getobname(o, buf, o->amt); - msg("%s %s away from %s!", lfname, isplayer(lf) ? "shy" : "shies", buf); - o->blessknown = B_TRUE; - } - taketime(lf, getmovespeed(lf)); - reason = E_OK; - // avoid this object in future - sprintf(buf, "%ld",o->id); - addflag(lf->flags, F_AVOIDCURSEDOB, NA, NA, NA, buf); - return B_FALSE; - } - } - } - } + if (initiatemove(lf, cell, &dontclearmsg)) { + // failed? + return B_FALSE; } - - // slipping on blood before moving? - if (!isairborne(lf)) { - slip = getslipperyness(lf->cell, &slipob); - if (slip && !skillcheck(lf, SC_SLIP, slip, 0)) { - slipon(lf, slipob); - // don't move - reason = E_OK; - return B_FALSE; - } - } - - - // gravboosted - if (lfhasflag(lf, F_GRAVBOOSTED)) { - // make a saving throw to move - if (!skillcheck(lf, SC_STR, 25, 0)) { - if (isplayer(lf)) { - msg("You try to move but are unable to lift your feet!"); - } else if (cansee(player, lf)) { - char lfname[BUFLEN]; - getlfname(lf, lfname); - msg("%s tries to move but is unable to lift its feet!",lfname); - } - reason = E_OK; - taketime(lf, getmovespeed(lf)); - return B_FALSE; - } - } - // move to new cell reason = E_OK; - moveto(lf, cell, onpurpose); + moveto(lf, cell, onpurpose, dontclearmsg); taketime(lf, getmovespeed(lf)); } else { object_t *inway = NULL; @@ -1428,7 +1530,7 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) { oldcell = lf->cell; // move you.. - moveto(lf, cell, onpurpose); + moveto(lf, cell, onpurpose, B_FALSE); taketime(lf, getmovespeed(lf)); // move them... @@ -1463,7 +1565,7 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) { killflagsofid(lf->flags, F_GRABBEDBY); killflagsofid(grabbedby->flags, F_GRABBING); // move - don't clear the 'you break free from' msg - moveto(lf, cell, B_TRUE); + moveto(lf, cell, B_TRUE, B_TRUE); } else { if (isplayer(lf)) { msg("You cannot get away from %s!",gbname); @@ -1523,6 +1625,13 @@ int willmove(lifeform_t *lf, int dir, enum ERROR *error) { // don't attack other monsters if (cell->lf) { // if someone is in the way + if (lf->race->raceclass->id == RC_INSECT) { + if (hasactivespell(cell->lf, OT_S_REPELINSECTS)) { + if (error) *error = E_WONT; + return B_FALSE; + } + } + if (!isplayer(lf)) { // if we are a monster // if the person in the way isn't our enemy... if (!areenemies(lf, cell->lf)) { diff --git a/move.h b/move.h index 8888f1d..7acbba3 100644 --- a/move.h +++ b/move.h @@ -13,13 +13,14 @@ int getdiraway(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, int d int getdirtowards(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, int dirtype); int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher); int moveawayfrom(lifeform_t *lf, cell_t *dst, int dirtype); -void moveeffects(lifeform_t *lf); +int moveeffects(lifeform_t *lf); int movelf(lifeform_t *lf, cell_t *newcell); -int moveto(lifeform_t *lf, cell_t *newcell, int onpurpose); +int moveto(lifeform_t *lf, cell_t *newcell, int onpurpose, int dontclearmsg); int movetowards(lifeform_t *lf, cell_t *dst, int dirtype); int opendoorat(lifeform_t *lf, cell_t *c); int opendoor(lifeform_t *lf, object_t *o); int pullnextto(lifeform_t *lf, cell_t *c); +int initiatemove(lifeform_t *lf, cell_t *cell, int *didmsg); int teleportto(lifeform_t *lf, cell_t *c, int wantsmoke); int trymove(lifeform_t *lf, int dir, int onpurpose); int tryrun(lifeform_t *lf, int dir); diff --git a/nexus.c b/nexus.c index c4cdf2b..9572495 100644 --- a/nexus.c +++ b/nexus.c @@ -25,6 +25,7 @@ obmod_t *firstobmod = NULL,*lastobmod = NULL; celltype_t *firstcelltype = NULL,*lastcelltype = NULL; command_t *firstcommand = NULL,*lastcommand = NULL; race_t *firstrace = NULL,*lastrace = NULL; +raceclass_t *firstraceclass = NULL,*lastraceclass = NULL; job_t *firstjob = NULL,*lastjob = NULL; skill_t *firstskill = NULL,*lastskill = NULL; map_t *firstmap = NULL,*lastmap = NULL; @@ -160,6 +161,7 @@ int main(int argc, char **argv) { } } + // find staircase where = findobinmap(firstmap, OT_STAIRSUP); assert(where); @@ -177,14 +179,26 @@ int main(int argc, char **argv) { addflag(player->flags, F_NAME, NA, NA, NA, "Anonymous"); } givejob(player, j->id); - // special case: + // special cases for jobs: if (j->id == J_PIRATE) { flag_t *f; f = lfhasflagval(player, F_HASATTACK, OT_FISTS, NA, NA, NULL); assert(f); f->val[0] = OT_HOOKHAND; sprintf(f->text, "1d4"); + } else if (j->id == J_WIZARD) { + skill_t *sk; + initprompt(&prompt, "Select your spell specialty:"); + addchoice(&prompt, 'a', getskillname(SK_SS_AIR), NULL, findskill(SK_SS_AIR)); + addchoice(&prompt, 'i', getskillname(SK_SS_ICE), NULL, findskill(SK_SS_ICE)); + addchoice(&prompt, 'f', getskillname(SK_SS_FIRE), NULL, findskill(SK_SS_FIRE)); + getchoice(&prompt); + sk = (skill_t *) prompt.result; + giveskill(player, sk->id); + } + + // read cheat info from player file if (playerfile) { if (parseplayerfile(playerfile, player)) { diff --git a/objects.c b/objects.c index ce7b640..db30c19 100644 --- a/objects.c +++ b/objects.c @@ -54,7 +54,6 @@ objecttype_t *lastot = NULL; enum OBCLASS sortorder[] = { OC_EFFECT, - OC_DFEATURE, OC_MONEY, OC_WEAPON, OC_MISSILE, @@ -70,6 +69,7 @@ enum OBCLASS sortorder[] = { OC_BOOK, OC_ROCK, OC_MISC, + OC_DFEATURE, // omitting OC_SPELL and OC_JUMP because it shouldn't ever be displayed OC_NULL }; @@ -393,7 +393,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack) { int howmany = 1; int i; int db = B_FALSE; - //flag_t *f; + flag_t *f; char *localname; int wantblessed = B_UNCURSED; race_t *corpserace = NULL; @@ -493,8 +493,6 @@ object_t *addobject(obpile_t *where, char *name, int canstack) { } // } - - if (strstr(p, "corpse")) { int len; char racename[BUFLEN]; @@ -542,6 +540,12 @@ object_t *addobject(obpile_t *where, char *name, int canstack) { dblog("xxx"); } + // override blessed status from flags... + f = hasflag(ot->flags, F_STARTBLESSED); + if (f) { + wantblessed = f->val[0]; + } + // don't give nopickup objects to lifeforms if (hasflag(ot->flags, F_NOPICKUP) && where->owner) { return NULL; @@ -963,6 +967,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack) { if (bonus) f->val[2] = bonus; else f->val[2] = rnd(1,3); } + if (o->blessed == B_CURSED) f->val[2] *= -1; } else if (o->type->id == OT_RING_DEX) { flag_t *f; f = hasflagval(o->flags, F_EQUIPCONFER, F_ATTRMOD, A_DEX, NA, NULL); @@ -970,6 +975,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack) { if (bonus) f->val[2] = bonus; else f->val[2] = rnd(1,3); } + if (o->blessed == B_CURSED) f->val[2] *= -1; } else if (o->type->id == OT_RING_IQ) { flag_t *f; f = hasflagval(o->flags, F_EQUIPCONFER, F_ATTRMOD, A_IQ, NA, NULL); @@ -977,6 +983,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack) { if (bonus) f->val[2] = bonus; else f->val[2] = rnd(1,3); } + if (o->blessed == B_CURSED) f->val[2] *= -1; } else if (o->type->id == OT_RING_STR) { flag_t *f; f = hasflagval(o->flags, F_EQUIPCONFER, F_ATTRMOD, A_STR, NA, NULL); @@ -984,6 +991,8 @@ object_t *addobject(obpile_t *where, char *name, int canstack) { if (bonus) f->val[2] = bonus; else f->val[2] = rnd(1,3); } + + if (o->blessed == B_CURSED) f->val[2] *= -1; } // check for postmods. eg. "xxx of pyromania" @@ -1328,12 +1337,19 @@ void adjustdamob(object_t *o, unsigned int *dam, enum DAMTYPE damtype) { if (isvulnto(o->flags, damtype)) { *dam *= 2; } - // poison gas never hurts objects + // some damage types never hurts objects if (damtype == DT_POISONGAS) { *dam = 0; return; } + if (damtype == DT_WATER) { + if (!isvulnto(o->flags, damtype)) { + *dam = 0; + return; + } + } + // adjust damage if (o->blessed == B_BLESSED) { // chance of no hp loss @@ -1878,20 +1894,6 @@ void damageallobs(object_t *exception, obpile_t *op, int howmuch, int damtype) { } } -void dumprandomobs(int amt) { - int i; - char buf[BUFLEN]; - int min,max; - int depth; - depth = player->cell->map->depth; - getrarity(depth, &min, &max, RARITYVARIANCE); - dblog("Random object dump for depth %d (rarity %d-%d)",depth,min,max); - for (i = 0; i < amt; i++) { - getrandomob(player->cell->map, buf); - dblog(" %s",buf); - } - dblog("END RANDOM OBJECT"); -} void explodeob(object_t *o, flag_t *f, int bigness) { cell_t *c; @@ -2092,9 +2094,11 @@ objecttype_t *findotn(char *name) { // check for exact matches on real name (and plural versions) first for (ot = objecttype ; ot ; ot = ot->next) { - if (checkobnames(ot->name, modname)) { - free(modname); - return ot; + if ((ot->obclass->id != OC_SPELL) && (ot->obclass->id != OC_ABILITY)) { + if (checkobnames(ot->name, modname)) { + free(modname); + return ot; + } } } @@ -2109,10 +2113,12 @@ objecttype_t *findotn(char *name) { // then partial matches on real name for (ot = objecttype ; ot ; ot = ot->next) { - if (strstr(ot->name, modname)) { - free(modname); - // found it! - return ot; + if ((ot->obclass->id != OC_SPELL) && (ot->obclass->id != OC_ABILITY)) { + if (strstr(ot->name, modname)) { + free(modname); + // found it! + return ot; + } } } @@ -2743,6 +2749,7 @@ int getmaterialvalue(enum MATERIAL mat) { case MT_BLOOD: case MT_SLIME: case MT_WAX: + case MT_OIL: return 2; case MT_CLOTH: case MT_LEATHER: @@ -2755,6 +2762,7 @@ int getmaterialvalue(enum MATERIAL mat) { case MT_PLASTIC: case MT_RUBBER: case MT_GLASS: + case MT_SILK: return 5; case MT_METAL: return 6; @@ -3010,6 +3018,7 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan char *pluralname; char prefix[BUFLEN]; char basename[BUFLEN]; + char localbuf[BUFLEN]; char buf2[BUFLEN]; char triedbuf[BUFLEN]; int shopitem = B_FALSE; @@ -3103,28 +3112,11 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan if (count == ALL) { count = o->amt; } + strcpy(localbuf, ""); - // figure out prefix + // figure out pluralname if ((count == 1) && !hasflag(o->flags, F_NO_A)) { pluralname = strdup(basename); - - if (hasflag(o->flags, F_UNIQUE)) { // TODO: && o->identified - strcpy(prefix, "The"); - } else { - if (!hasflag(o->flags, F_NOBLESS) && isblessknown(o)) { - if (o->blessed == B_UNCURSED) { - strcpy(prefix, "an"); - } else { - strcpy(prefix, "a"); - } - } else { - if (isvowel(basename[0])) { - strcpy(prefix, "an"); - } else { - strcpy(prefix, "a"); - } - } - } } else { // multiple objects? if (hasflag(o->flags, F_NO_PLURAL)) { @@ -3132,11 +3124,8 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan } else { pluralname = makeplural(basename); } - sprintf(prefix, "%d",count); } - sprintf(buf, "%s ", prefix); - // blessed status if (!hasflag(o->flags, F_NOBLESS) && wantblesscurse) { @@ -3146,16 +3135,16 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan // blessed water is known as "holy water" if ((o->type->id == OT_POT_WATER) && isknown(o)) { } else { - strcat(buf, "blessed "); + strcat(localbuf, "blessed "); } break; case B_UNCURSED: - strcat(buf, "uncursed "); + strcat(localbuf, "uncursed "); break; case B_CURSED: if ((o->type->id == OT_POT_COMPETENCE) && isknown(o)) { } else { - strcat(buf, "cursed "); + strcat(localbuf, "cursed "); } break; } @@ -3166,14 +3155,14 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan if (o->material != o->type->material) { switch (o->material->id) { case MT_GOLD: - strcat(buf, "golden "); + strcat(localbuf, "golden "); break; case MT_WOOD: - strcat(buf, "wooden "); + strcat(localbuf, "wooden "); break; default: - // strcat(buf, o->material->name); - // strcat(buf, " "); + // strcat(localbuf, o->material->name); + // strcat(localbuf, " "); break; } } @@ -3189,7 +3178,7 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan } } if (found) { - strcat(buf, om->prefix); + strcat(localbuf, om->prefix); } } } @@ -3199,8 +3188,8 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan if (!hasflag(o->flags, F_NOOBDAMTEXT)) { getobconditionname(o, buf2); if (strlen(buf2) > 0) { - strcat(buf, buf2); - strcat(buf, " "); + strcat(localbuf, buf2); + strcat(localbuf, " "); } } } @@ -3213,7 +3202,7 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan bonus = f->val[0]; if (bonus != 0) { sprintf(buf2, "%s%d ", (bonus < 0) ? "" : "+", bonus); - strcat(buf, buf2); + strcat(localbuf, buf2); } } @@ -3228,7 +3217,7 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan f = hasflag(o->flags, F_EQUIPCONFER); if (f) { sprintf(buf2, "+%d ",f->val[2]); - strcat(buf, buf2); + strcat(localbuf, buf2); } break; default: @@ -3237,11 +3226,11 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan } if (issecretdoor(o)) { - strcat(buf, "secret "); + strcat(localbuf, "secret "); } // object name - strcat(buf, pluralname); + strcat(localbuf, pluralname); free(pluralname); // include mods if identified - ie. xxx of pyromania @@ -3264,14 +3253,14 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan } if (ok) { - strcat(buf, br->suffix); + strcat(localbuf, br->suffix); } } } // make sure obname doesn't start with a space - while (buf && (buf[0] == ' ')) { - strcpy(buf, buf + 1); + while (localbuf[0] == ' ') { + strcpy(localbuf, localbuf + 1); } // show portal/stair destination @@ -3282,15 +3271,15 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan if (newmap) { char buf2[BUFLEN]; sprintf(buf2, " to level %d", newmap->depth); - strcat(buf, buf2); + strcat(localbuf, buf2); } } // append inscription if (o->inscription) { - strcat(buf, " {"); - strcat(buf, o->inscription); - strcat(buf, "}"); + strcat(localbuf, " {"); + strcat(localbuf, o->inscription); + strcat(localbuf, "}"); } // show if we've tried this @@ -3308,17 +3297,35 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan } if (strlen(triedbuf)) { strcat(triedbuf, "]"); - strcat(buf, triedbuf); + strcat(localbuf, triedbuf); } // detect magic - append [magic] if (lfhasflag(player, F_DETECTMAGIC)) { if (ismagical(o)) { - strcat(buf, " [magic]"); + strcat(localbuf, " [magic]"); } } } + // apply prefix now! + if ((count == 1) && !hasflag(o->flags, F_NO_A)) { + if (hasflag(o->flags, F_UNIQUE)) { // TODO: && o->identified + strcpy(prefix, "The"); + } else { + if (needan(localbuf)) { + strcpy(prefix, "an"); + } else { + strcpy(prefix, "a"); + } + } + } else { + // multiple objects? + sprintf(prefix, "%d",count); + } + + // prepend prefix on to buf + sprintf(buf, "%s %s", prefix, localbuf); return buf; } @@ -3342,8 +3349,8 @@ char *getobconditionname(object_t *o, char *buf) { } if (iscorpse(o)) { - // you only know it's rotting if you have average or higher iq - if (isrotting(o) && (iqb >= IQ_AVERAGE)) { + // you only know it's rotting if you are smart + if (isrotting(o) && (iqb >= IQ_SMART)) { sprintf(buf, "rotting"); } else { strcpy(buf, ""); @@ -3485,7 +3492,7 @@ char *real_getrandomob(map_t *map, char *buf, int cond, int cval, int forcedepth depth = rnd(1,MAXDEPTH); } - getrarity(depth, &raritymin, &raritymax, RARITYVARIANCE); + getrarity(depth, &raritymin, &raritymax, RARITYVARIANCEOB); while (!done) { if (db) dblog("adding random object with rarity value between %d - %d",raritymin,raritymax); @@ -3586,40 +3593,37 @@ char *real_getrandomob(map_t *map, char *buf, int cond, int cval, int forcedepth pluralname = strdup(ot->name); } - // blessed? + // blessed or cursed? strcpy(cursestr, ""); if (!hasflag(ot->flags, F_NOBLESS)) { int num; - int bonus = 0; num = rnd(1,100); if (num <= 15) { strcpy(cursestr, "blessed "); - // chance of bonus - while (rnd(1,100) <= 25) { - bonus++; - } } else if (num <= 30) { strcpy(cursestr, "cursed "); - // chance of penalty - while (rnd(1,100) <= 25) { - bonus--; - } } } - if ((ot->obclass->id == OC_WEAPON) || - (ot->obclass->id == OC_ARMOUR)) { + if (hasflag(ot->flags, F_ENCHANTABLE)) { char buf2[BUFLENSMALL]; int bonus = 0; - if (strlen(cursestr) > 0) { - // chance of bonus/penalty - while (rnd(1,100) <= 25) { - bonus++; - } - if (strstr(cursestr, "cursed")){ - bonus = -bonus; - } + int dir,chance; + + if (strstr(cursestr, "cursed")){ // cursed WILL have a negative bonus + bonus = -1; // always at least -1 + chance = 25; + dir = -1; + } else if (strstr(cursestr, "blessed")) { // blessed/uncursed MAY have a bonus + chance = 30; + dir = 1; + } else { + chance = 25; + dir = 1; + } + while (rnd(1,100) <= chance) { + bonus += dir; } sprintf(buf2, "%s%d ", (bonus >= 0) ? "+" : "", bonus); strcat(cursestr, buf2); @@ -3684,203 +3688,6 @@ char *real_getrandomob(map_t *map, char *buf, int cond, int cval, int forcedepth return buf; } -/* -OLD CODE -char *real_getrandomob(map_t *map, char *buf, int cond, int cval, int forcedepth) { - enum RARITY rarity; - objecttype_t *ot; - int roll; - objecttype_t *poss[MAXRANDOMOBCANDIDATES]; - int nposs = 0; - int selidx; - int amt; - flag_t *f; - int db = B_TRUE; - char *pluralname; - char cursestr[BUFLEN]; - int depth; - int getrarer; - int firstgo; - int moddir = 0; - - // determine rarity of object to generate - if (rnd(1,2) == 1) { - rarity = RR_FREQUENT; - } else { - rarity = RR_COMMON; - } - - if (forcedepth != NA) { - depth = forcedepth; - } else if (map) { - depth = map->depth; - } else { - depth = rnd(1,20); - } - - getrarer = 40 + (depth * 2); - - if (getrarer > 75) getrarer = 75; - - // start with 'frequent'ly appearing items - // roll a die. if less than 'getrarer', get rarer. - // stop when we fail the die roll. - roll = rnd(1,100); - while (roll < getrarer) { - rarity++; - if (rarity == RR_VERYRARE) break; - roll = rnd(1,100); - } - if (db) dblog("adding random object of rarity %d",rarity); - if (db) { - objectclass_t *oc; - switch (cond) { - case RO_DAMTYPE: - dblog(" (must have damtype = %s)",getdamname(cval)); - break; - case RO_OBCLASS: - oc = findoc(cval); - dblog(" (must have obclass = %s)",oc->name); - break; - } - } - - - // try to find an object of this type which will - // fit in the map's habitat - - moddir = -1; - firstgo = B_TRUE; - nposs = 0; - while (nposs == 0) { - for (ot = objecttype ; ot ; ot = ot->next) { - int rarok = B_FALSE, condok = B_FALSE; - // correct rarity? - if ( map && hasflagval(ot->flags, F_RARITY, map->habitat, rarity, NA, NULL)) { - rarok = B_TRUE; - } else if (hasflagval(ot->flags, F_RARITY, NA, rarity, NA, NULL)) { - rarok = B_TRUE; - } else { - rarok = B_FALSE; - } - - if (rarok) { - // matches condition? - if (cond == RO_NONE) { - condok = B_TRUE; - } else if (cond == RO_DAMTYPE) { - if (hasflagval(ot->flags, F_DAMTYPE, cval, NA, NA, NULL)) { - condok = B_TRUE; - } - } else if (cond == RO_OBCLASS) { - if (ot->obclass->id == cval) { - condok = B_TRUE; - } - } - } - - if (rarok && condok) { - poss[nposs] = ot; - nposs++; - if (nposs >= MAXRANDOMOBCANDIDATES) break; - } - } - - - // nothing found? - if (nposs == 0) { - // already at lowest rarity? - if (rarity == RR_FREQUENT) { - if (firstgo) { - moddir = 1; - } else { - // give up - strcpy(buf, ""); - if (db) dblog("no possible objects at all! giving up."); - return NULL; - } - } - - firstgo = B_FALSE; - - // lower/raise rarity and try again - rarity += moddir; - if (rarity >= RR_NEVER) { - // give up - strcpy(buf, ""); - if (db) dblog("no possible objects at all! giving up."); - return NULL; - } - if (db) dblog("no possible objects like this. trying again with rarity %d\n",rarity); - } - } - - if (db) dblog("got %d possibilities.",nposs); - // pick a random object from our possiblities - selidx = rnd(0,nposs-1); - ot = poss[selidx]; - // handle objects which appear in multiples (ie. rocks) - f = hasflag(ot->flags, F_NUMAPPEAR); - if (f) { - amt = rnd(f->val[0], f->val[1]); - } else { - amt = 1; - } - - if (amt > 1) { - pluralname = makeplural(ot->name); - } else { - pluralname = strdup(ot->name); - } - - // blessed? - strcpy(cursestr, ""); - if (!hasflag(ot->flags, F_NOBLESS)) { - int num; - int bonus = 0; - num = rnd(1,100); - if (num <= 15) { - strcpy(cursestr, "blessed "); - // chance of bonus - while (rnd(1,100) <= 25) { - bonus++; - } - } else if (num <= 30) { - strcpy(cursestr, "cursed "); - // chance of penalty - while (rnd(1,100) <= 25) { - bonus--; - } - } - } - - - if ((ot->obclass->id == OC_WEAPON) || - (ot->obclass->id == OC_ARMOUR)) { - char buf2[BUFLENSMALL]; - int bonus = 0; - if (strlen(cursestr) > 0) { - // chance of bonus/penalty - while (rnd(1,100) <= 25) { - bonus++; - } - if (strstr(cursestr, "cursed")){ - bonus = -bonus; - } - } - sprintf(buf2, "%s%d ", (bonus >= 0) ? "+" : "", bonus); - strcat(cursestr, buf2); - } - - sprintf(buf, "%d %s%s", amt, cursestr, pluralname); - - - if (db) dblog("random ob: %d x %s ('%s')", amt, ot->name,pluralname); - free(pluralname); - return buf; -} -*/ - char *getrandomob(map_t *map, char *buf) { return real_getrandomob(map, buf, RO_NONE, NA, NA); } @@ -3938,11 +3745,11 @@ char *getschoolname(enum SPELLSCHOOL sch) { case SS_WILD: return "Wild Magic"; case SS_MENTAL: return "Psionic Powers"; case SS_AIR: return "Elemental/Air Magic"; - case SS_EARTH: return "Elemental/Earth Magic"; case SS_FIRE: return "Elemental/Fire Magic"; case SS_ICE: return "Elemental/Ice Magic"; case SS_MODIFICATION: return "Modification Magic"; case SS_DEATH: return "Necromancy"; + case SS_NATURE: return "Nature"; case SS_LIFE: return "Life Magic"; case SS_DIVINATION: return "Divination Magic"; case SS_TRANSLOCATION: return "Translocation Magic"; @@ -3961,14 +3768,14 @@ char *getschoolnameshort(enum SPELLSCHOOL sch) { case SS_ALLOMANCY: return "Allomancy"; case SS_DIVINE: return "Divine Powers"; case SS_WILD: return "Wild Magic"; - case SS_MENTAL: return "Psionic Powers"; case SS_AIR: return "Air Magic"; - case SS_EARTH: return "Earth Magic"; case SS_FIRE: return "Fire Magic"; case SS_ICE: return "Ice Magic"; - case SS_MODIFICATION: return "Modification"; case SS_DEATH: return "Necromancy"; case SS_LIFE: return "Life Magic"; + case SS_MENTAL: return "Psionic Powers"; + case SS_MODIFICATION: return "Modification"; + case SS_NATURE: return "Nature"; case SS_DIVINATION: return "Divination"; case SS_TRANSLOCATION: return "Translocation"; case SS_SUMMONING: return "Summoning"; @@ -4180,15 +3987,49 @@ void identify(object_t *o) { } void ignite(object_t *o) { - flag_t *f; - if (!hasflag(o->flags, F_DAMAGABLE)) { - addflag(o->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); + flag_t *f,*ff; + char convertto[BUFLEN]; + int howlong = 3; // default + + strcpy(convertto, ""); // default + ff = hasflag(o->flags, F_FLAMMABLE); + if (ff) { + howlong = ff->val[0]; + strcpy(convertto, ff->text); } + f = hasflag(o->flags, F_ONFIRE); if (!f) { - // on fire for 2 turns - addtempflag(o->flags, F_ONFIRE, B_TRUE, NA, NA, NULL, 2); + if (strlen(convertto)) { + cell_t *where; + object_t *newob; + + where = getoblocation(o); + // change + newob = addob(where->obpile, convertto); + + if (newob) { + // announce + if (haslos(player, where)) { + char obname[BUFLEN]; + char newobname[BUFLEN]; + getobname(o, obname, o->amt); + getobname(newob, newobname, newob->amt); + msg("%s ignites into %s!",obname,newobname); + } + // kill old ob + addflag(o->flags, F_DEAD, B_TRUE, NA, NA, NULL); + addflag(o->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL); + } + } else { + // make it damagable, if it isn't already. + if (!hasflag(o->flags, F_DAMAGABLE)) { + addflag(o->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); + } + // on fire for 3 turns + addtempflag(o->flags, F_ONFIRE, B_TRUE, NA, NA, NULL, howlong); + } } } @@ -4218,6 +4059,7 @@ void initobjects(void) { addhiddenname(OC_SCROLL, "scroll titled ETEE NOM"); addhiddenname(OC_SCROLL, "scroll titled FIE JOOHM"); addhiddenname(OC_SCROLL, "scroll titled GREE VII"); + addhiddenname(OC_SCROLL, "scroll titled HERE HERE"); addhiddenname(OC_SCROLL, "scroll titled HTEB IH"); addhiddenname(OC_SCROLL, "scroll titled HOCUS POCUS"); addhiddenname(OC_SCROLL, "scroll titled ILU-MA ZEE"); @@ -4227,10 +4069,18 @@ void initobjects(void) { addhiddenname(OC_SCROLL, "scroll titled MARIGON"); addhiddenname(OC_SCROLL, "scroll titled MAXIMOR BLATHUS"); addhiddenname(OC_SCROLL, "scroll titled NORTH"); + addhiddenname(OC_SCROLL, "scroll titled ORI GREEBLE"); + addhiddenname(OC_SCROLL, "scroll titled POCUS HOCUS"); + addhiddenname(OC_SCROLL, "scroll titled QUANDRILAR"); addhiddenname(OC_SCROLL, "scroll titled REZZ KINETO"); addhiddenname(OC_SCROLL, "scroll titled SHAZZARIO"); addhiddenname(OC_SCROLL, "scroll titled THERIUM LARGOS"); + addhiddenname(OC_SCROLL, "scroll titled TAKA TAKA TAKA"); + addhiddenname(OC_SCROLL, "scroll titled UNDWEL"); addhiddenname(OC_SCROLL, "scroll titled VOLTR YI MEN"); + addhiddenname(OC_SCROLL, "scroll titled WII"); + addhiddenname(OC_SCROLL, "scroll titled XAND"); + addhiddenname(OC_SCROLL, "scroll titled YES"); addhiddenname(OC_SCROLL, "scroll titled ZAREL NOR"); addhiddenname(OC_POTION, "clear potion"); @@ -4290,6 +4140,7 @@ void initobjects(void) { addflag_real(lastobmod->flags, F_SHODDY, B_TRUE, NA, NA, NULL, PERMENANT, B_KNOWN, -1); addobmod(OM_POISONED,"poisoned"); addflag_real(lastobmod->flags, F_HITCONFER, F_POISONED, SC_POISON, 25, "15-30", PERMENANT, B_KNOWN, -1); + addflag_real(lastobmod->flags, F_HITCONFERVALS, P_VENOM, 1, NA, NULL, PERMENANT, B_KNOWN, -1); addobmod(OM_WET1,"damp"); addflag_real(lastobmod->flags, F_WET, W_DAMP, NA, NA, NULL, PERMENANT, B_KNOWN, -1); addobmod(OM_WET2,"wet"); @@ -4366,11 +4217,14 @@ void initobjects(void) { addflag(lastmaterial->flags, F_MATCONVERT, MT_WATER, NA, NA, "lump of soggy paper"); addflag(lastmaterial->flags, F_MATCONVERTTEXT, MT_WATER, NA, NA, "goes soggy"); addflag(lastmaterial->flags, F_MATCONVERTTEXTPL, MT_WATER, NA, NA, "go soggy"); - addflag(lastmaterial->flags, F_FLAMMABLE, B_TRUE, NA, NA, NULL); + addflag(lastmaterial->flags, F_FLAMMABLE, PERMENANT, NA, NA, NULL); + addmaterial(MT_SILK, "silk", 1); + 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); addmaterial(MT_WETPAPER, "wet paper", 3); addmaterial(MT_CLOTH, "cloth", 3); - addflag(lastmaterial->flags, F_FLAMMABLE, B_TRUE, NA, NA, NULL); + addflag(lastmaterial->flags, F_FLAMMABLE, 3, NA, NA, NULL); addflag(lastmaterial->flags, F_CANGETWET, B_TRUE, NA, NA, NULL); addmaterial(MT_FOOD, "food", 3); addmaterial(MT_PLASTIC, "plastic", 3); @@ -4384,11 +4238,12 @@ void initobjects(void) { addflag(lastmaterial->flags, F_CANGETWET, B_TRUE, NA, NA, NULL); addmaterial(MT_BONE, "bone", 5); addflag(lastmaterial->flags, F_HARD, B_TRUE, NA, NA, NULL); + addmaterial(MT_OIL, "oil", 5); addmaterial(MT_ICE, "ice",6); addflag(lastmaterial->flags, F_HARD, B_TRUE, NA, NA, NULL); addmaterial(MT_WOOD, "wood", 6); addflag(lastmaterial->flags, F_HARD, B_TRUE, NA, NA, NULL); - addflag(lastmaterial->flags, F_FLAMMABLE, B_TRUE, NA, NA, NULL); + addflag(lastmaterial->flags, F_FLAMMABLE, 5, NA, NA, NULL); addflag(lastmaterial->flags, F_CANGETWET, B_TRUE, NA, NA, NULL); addmaterial(MT_ACID, "acid", 7); addmaterial(MT_WATER, "water", 7); @@ -4467,6 +4322,7 @@ void initobjects(void) { addoc(OC_MISC, "Miscellaneous", "This could be anything.", '\\', C_GREY); addoc(OC_EFFECT, "Environmental Effects", "Smoke, fire, etc.", '}', C_GREY); addflag(lastobjectclass->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); + addflag(lastobjectclass->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); addoc(OC_BOOK, "Books", "Spellbooks, tomes or manuals.", '+', C_GREY); addflag(lastobjectclass->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL); addflag(lastobjectclass->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); @@ -4503,7 +4359,7 @@ void initobjects(void) { addflag(lastot->flags, F_DTVULN, DT_BASH, NA, NA, NULL); addflag(lastot->flags, F_DTVULN, DT_CHOP, NA, NA, NULL); - addot(OT_BOULDER, "boulder", "A massive stone boulder.", MT_STONE, 80, OC_DFEATURE); + addot(OT_BOULDER, "boulder", "A massive stone boulder.", MT_STONE, 80, OC_ROCK); addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, ""); addflag(lastot->flags, F_GLYPH, NA, NA, NA, "'"); addflag(lastot->flags, F_IMPASSABLE, SZ_LARGE, NA, NA, NULL); @@ -4517,7 +4373,7 @@ void initobjects(void) { addflag(lastot->flags, F_OBHP, 80, 80, NA, NULL); addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "50-100 stones"); - addot(OT_STATUE, "statue", "A stone statue of a monster.", MT_STONE, 80, OC_DFEATURE); + addot(OT_STATUE, "statue", "A stone statue of a monster.", MT_STONE, 80, OC_ROCK); addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, ""); addflag(lastot->flags, F_GLYPH, NA, NA, NA, "'"); addflag(lastot->flags, F_IMPASSABLE, SZ_LARGE, NA, NA, NULL); @@ -4542,13 +4398,13 @@ void initobjects(void) { addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); - addot(OT_VENDINGMACHINE, "vending machine", "A gold-operated vending machine.", MT_METAL, 500, OC_DFEATURE); + addot(OT_VENDINGMACHINE, "vending machine", "A gold-operated vending machine.", MT_METAL, 500, OC_MISC); addflag(lastot->flags, F_RARITY, H_ALL, 70, NA, ""); addflag(lastot->flags, F_GLYPH, C_WHITE, NA, NA, "_"); addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); - addot(OT_PORTAL, "magic portal", "A magical portal to a different place...", MT_MAGIC, 0, OC_DFEATURE); + addot(OT_PORTAL, "magic portal", "A magical portal to a different place...", MT_MAGIC, 0, OC_MISC); 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); @@ -4635,7 +4491,7 @@ void initobjects(void) { addflag(lastot->flags, F_GLYPH, C_YELLOW, NA, NA, "%"); addflag(lastot->flags, F_EDIBLE, B_TRUE, 85, NA, ""); addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); - addot(OT_ROASTMEAT, "chunk of roast meat", "A chunk of flame-roasted flesh.", MT_FOOD, 1, OC_FOOD); // weight normally comes from corpse type + addot(OT_ROASTMEAT, "chunk of roast meat", "A chunk of flame-roasted flesh.", MT_FLESH, 1, OC_FOOD); // weight normally comes from corpse type addflag(lastot->flags, F_GLYPH, C_BROWN, NA, NA, "%"); addflag(lastot->flags, F_EDIBLE, B_TRUE, 100, NA, ""); addflag(lastot->flags, F_RARITY, H_DUNGEON, 65, NA, NULL); @@ -4675,9 +4531,11 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL); addflag(lastot->flags, F_AIHEALITEM, B_TRUE, NA, NA, NULL); addot(OT_POT_OIL, "potion of oil", "A bottle of cooking oil.", MT_GLASS, 1, OC_POTION); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 83, NA, NULL); + addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "puddle of oil"); + addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL); addot(OT_POT_RUM, "potion of rum", "String liqour which is sure to make you tipsy.", MT_GLASS, 1, OC_POTION); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 83, NA, NULL); addot(OT_POT_RESTORATION, "potion of restoration", "Restores lost abilities to the drinker.", MT_GLASS, 1, OC_POTION); addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); addot(OT_POT_SPEED, "potion of haste", "Temporarily increasees the drinker's speed.", MT_GLASS, 1, OC_POTION); @@ -4699,6 +4557,7 @@ void initobjects(void) { addot(OT_POT_ACID, "flask of battery acid", "Causes massive internal burning if ingested.", MT_GLASS, 1, OC_POTION); addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "puddle of acid"); + addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL); addot(OT_POT_ELEMENTIMMUNE, "potion of elemental immunity", "Grants the imbiber temporary immunity to both fire and cold.", MT_GLASS, 1, OC_POTION); addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL); addot(OT_POT_BLOOD, "potion of blood", "A small quantity of blood.", MT_GLASS, 1, OC_POTION); @@ -4746,8 +4605,13 @@ void initobjects(void) { addflag(lastot->flags, F_LINKSPELL, OT_S_IDENTIFY, NA, NA, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, 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_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, 60, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 84, NA, 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); @@ -4871,16 +4735,12 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); + // l3 addot(OT_S_POISONBOLT, "poison bolt", "Fires a glob of venom at the target.", MT_NOTHING, 0, OC_SPELL); addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); - addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); - addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); - // l3 - addot(OT_S_ANIMATEDEAD, "animate dead", "Imbues nearby corpses with life, creating an undead zombie.", MT_NOTHING, 0, OC_SPELL); - addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); - // TODO: should be "castnearob ot_corpse" - addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); addot(OT_S_DRAINLIFE, "drain life", "Draws life force from the victim in order to heal the caster.", MT_NOTHING, 0, OC_SPELL); addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); @@ -4898,6 +4758,11 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); + addot(OT_S_ANIMATEDEAD, "animate dead", "Imbues nearby corpses with life, creating an undead zombie.", MT_NOTHING, 0, OC_SPELL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); + // TODO: should be "castnearob ot_corpse" + addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL); // l5 addot(OT_S_FEEBLEMIND, "feeblemind", "Temporarily lowers the target's intelligence to that of an animal.", MT_NOTHING, 0, OC_SPELL); addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); @@ -4931,12 +4796,13 @@ void initobjects(void) { addot(OT_S_DETECTAURA, "detect aura", "Senses holiness or evil near the caster.", MT_NOTHING, 0, OC_SPELL); addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINATION, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); - addot(OT_S_DETECTMAGIC, "detect magic", "Allows the caster to detect magical enchantments.", MT_NOTHING, 0, OC_SPELL); + addot(OT_S_REVEALHIDDEN, "reveal hidden", "Reveals hidden doors or invisible creatures in the caster's line of sight.", MT_NOTHING, 0, OC_SPELL); addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINATION, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); // l4 - addot(OT_S_REVEALHIDDEN, "reveal hidden", "Reveals hidden doors or invisible creatures in the caster's line of sight.", MT_NOTHING, 0, OC_SPELL); + addot(OT_S_DETECTMAGIC, "detect magic", "Allows the caster to detect magical enchantments.", MT_NOTHING, 0, OC_SPELL); addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINATION, NA, NA, NULL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); // l8 addot(OT_S_IDENTIFY, "identification", "Completely identifies any one item.", MT_NOTHING, 0, OC_SPELL); @@ -4948,6 +4814,7 @@ void initobjects(void) { // l2 addot(OT_S_AIRBLAST, "airblast", "Knocks enemies back with a powerful blast of air.", MT_NOTHING, 0, OC_SPELL); addflag(lastot->flags, F_SPELLSCHOOL, SS_AIR, NA, NA, NULL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOFLEE, ST_VICTIM, NA, NA, NULL); // l3 @@ -4956,6 +4823,7 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); addot(OT_S_WINDSHIELD, "cyclonic shield", "Surrounds the caster with a whirling cyclone to repel missiles.", MT_NOTHING, 0, OC_SPELL); addflag(lastot->flags, F_SPELLSCHOOL, SS_AIR, NA, NA, NULL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); addflag(lastot->flags, F_VARPOWER, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL); @@ -4966,6 +4834,7 @@ void initobjects(void) { // l1 addot(OT_S_SPARK, "spark", "Creates a tiny spark of flame, sufficient to ignite flammable objects but not enough to deal direct damage.", MT_NOTHING, 0, OC_SPELL); addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); // l2 addot(OT_S_FIREDART, "flame dart", "Fires a medium-sized dart of fire, dealing 2-6 fire damage.", MT_NOTHING, 0, OC_SPELL); @@ -4973,19 +4842,21 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); // l3 - addot(OT_S_FLAMEPILLAR, "flame pillar", "Creates a tall pillar of flame.", MT_NOTHING, 0, OC_SPELL); - addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL); - addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); - addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); - // l4 addot(OT_S_FLAMEBURST, "flame burst", "Creates a radial blast of fire out from the caster.", MT_NOTHING, 0, OC_SPELL); addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL); - addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJSELF, NA, NA, NULL); + // l4 + addot(OT_S_FLAMEPILLAR, "flame pillar", "Creates a tall pillar of flame.", MT_NOTHING, 0, OC_SPELL); + 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, 4, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); // l5 addot(OT_S_BURNINGWAVE, "burning wave", "Fire bursts from the ground in a line towards the target.", MT_NOTHING, 0, OC_SPELL); addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL); - addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 5, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); addflag(lastot->flags, F_RANGE, 3, NA, NA, NULL); addot(OT_S_FIREBALL, "fireball", "Creates a huge ball of fire.", MT_NOTHING, 0, OC_SPELL); @@ -5009,12 +4880,106 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJSELF, NA, NA, NULL); /////////////////// - // elemental - earth + // nature /////////////////// + // l1 + addot(OT_S_CALMANIMALS, "calm animals", "Makes animals within the casters line of sight become peaceful.", MT_NOTHING, 0, OC_SPELL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); + addot(OT_S_DETECTPOISON, "detect poison", "Detects any poisoned object in sight of the caster.", MT_NOTHING, 0, OC_SPELL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); + addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL); + addot(OT_S_PURIFYFOOD, "purify food", "Removes rot or poison from food or drink.", MT_NOTHING, 0, OC_SPELL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); + addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL); + addot(OT_S_STICKTOSNAKE, "sticks to snakes", "Transforms all seen wooden weapons into snakes.", MT_NOTHING, 0, OC_SPELL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); + addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL); + // l2 + addot(OT_S_BARKSKIN, "barkskin", "Covers the caster with a skin of bark, reducing damage but making them vulnerable to fire.", MT_NOTHING, 0, OC_SPELL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); + addflag(lastot->flags, F_MAXPOWER, 5, NA, NA, NULL); + addflag(lastot->flags, F_VARPOWER, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL); + addot(OT_S_CHARMANIMAL, "befriend animal", "Temporarily makes a single animal friendly to you.", MT_NOTHING, 0, OC_SPELL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); + addflag(lastot->flags, F_MAXPOWER, 5, NA, NA, NULL); + addot(OT_S_LESSENPOISON, "lessen poison", "Reduces the effects of poison within the caster's bloodstream.", MT_NOTHING, 0, OC_SPELL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); + addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL); + addot(OT_S_REPELINSECTS, "repel insects", "Surrounds the caster with an insect-repelling smell.", MT_NOTHING, 0, OC_SPELL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); + addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); + addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL); + addot(OT_S_SOFTENEARTH, "soften earth", "Converts earth into mud, slowing down.", MT_NOTHING, 0, OC_SPELL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOFLEE, ST_VICTIM, NA, NA, NULL); + addot(OT_S_WARPWOOD, "warp wood", "Causes damage to all wooden object in the target area.", MT_NOTHING, 0, OC_SPELL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); + addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); + // l3 + addot(OT_S_CALLLIGHTNING, "call lightning", "Blasts a single enemy with a bolt of lightning from the sky.", MT_NOTHING, 0, OC_SPELL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_AIR, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); + addot(OT_S_ENDUREELEMENTS, "endure elements", "Provides resistance to fire and cold.", MT_NOTHING, 0, OC_SPELL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); + addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL); + addot(OT_S_QUENCH, "quench", "Extinguishes all fires within the given area.", MT_NOTHING, 0, OC_SPELL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 3, NA, 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); + addflag(lastot->flags, F_AICASTTOFLEE, ST_VICTIM, NA, NA, NULL); + addflag(lastot->flags, F_MAXPOWER, 4, NA, NA, NULL); + addot(OT_S_WEB, "web", "Slows down pursuers with a burst of sticky spider web.", 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_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOFLEE, ST_VICTIM, NA, NA, NULL); // l4 addot(OT_S_DIG, "dig", "Blasts away earth to create passages.", MT_NOTHING, 0, OC_SPELL); - addflag(lastot->flags, F_SPELLSCHOOL, SS_EARTH, NA, NA, NULL); - addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); + addot(OT_S_ENTANGLE, "entangle", "Causes magical vines to hold enemies.", MT_NOTHING, 0, OC_SPELL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOFLEE, ST_VICTIM, NA, NA, NULL); + // l4 + addot(OT_S_CALMINGSCENT, "calming scent", "Automatically calms any nearby animals.", MT_NOTHING, 0, OC_SPELL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); + addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); + addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL); + addot(OT_S_CUREPOISON, "cure poison", "Cures the target of all poisons.", MT_NOTHING, 0, OC_SPELL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); + addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL); + addot(OT_S_HAILSTORM, "hail storm", "Creates an intense storm of hail, causing damage to all within.", MT_NOTHING, 0, OC_SPELL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOFLEE, ST_VICTIM, NA, NA, NULL); + addflag(lastot->flags, F_MAXPOWER, 5, NA, NA, NULL); /////////////////// // gravity /////////////////// @@ -5033,11 +4998,12 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOFLEE, ST_VICTIM, NA, NA, NULL); - // l5 addot(OT_S_LEVITATION, "levitation", "Causes the caster hover a metre above the ground.", MT_NOTHING, 0, OC_SPELL); addflag(lastot->flags, F_SPELLSCHOOL, SS_GRAVITY, NA, NA, NULL); - addflag(lastot->flags, F_SPELLLEVEL, 5, NA, NA, NULL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL); + // l5 // l6 addot(OT_S_FLIGHT, "fly", "Allows the caster to fly.", MT_NOTHING, 0, OC_SPELL); addflag(lastot->flags, F_SPELLSCHOOL, SS_GRAVITY, NA, NA, NULL); @@ -5053,6 +5019,7 @@ void initobjects(void) { // l1 addot(OT_S_HEALINGMIN, "minor healing", "Restores 1-8 health to the caster.", MT_NOTHING, 0, OC_SPELL); addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, 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_AICASTTOFLEE, ST_SELF, NA, NA, NULL); addot(OT_S_TURNUNDEAD, "turn undead", "Instills fear in undead creatures. Power depends on caster's skill.", MT_NOTHING, 0, OC_SPELL); @@ -5061,6 +5028,7 @@ void initobjects(void) { // l3 addot(OT_S_HEALING, "healing", "Restores 10-20 health to the caster.", MT_NOTHING, 0, OC_SPELL); addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, NA, NA, NULL); /////////////////// @@ -5107,12 +5075,17 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); addot(OT_S_LIGHT, "light", "Creates a temporary light source centred on the caster.\nAt Power III, you can control where the light appears.\nAt Power VIII, the light becomes permenant.", MT_NOTHING, 0, OC_SPELL); addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, 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_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL); addot(OT_S_DARKNESS, "darkness", "Permenantly darkens the area around the caster.", MT_NOTHING, 0, OC_SPELL); addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL); + addot(OT_S_MENDING, "mending", "Repairs minor damage to objects.", MT_NOTHING, 0, OC_SPELL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); // l3 addot(OT_S_INVISIBILITY, "invisibility", "Temporarily renders the target invisible.", MT_NOTHING, 0, OC_SPELL); addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL); @@ -5122,12 +5095,8 @@ void initobjects(void) { addflag(lastot->flags, F_XPVAL, 50, NA, NA, NULL); addot(OT_S_PASSWALL, "passwall", "Allows the caster to temporarily walk through walls.", MT_NOTHING, 0, OC_SPELL); addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); - // l4 - addot(OT_S_GASEOUSFORM, "gaseous form", "Changes the caster into a cloud of gas.", MT_NOTHING, 0, OC_SPELL); - addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL); - addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); - addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL); // l6 addot(OT_S_PETRIFY, "petrify", "Causes the target mosnter to turn into stone.", MT_NOTHING, 0, OC_SPELL); addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL); @@ -5137,6 +5106,11 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 6, NA, NA, NULL); // l7 + addot(OT_S_GASEOUSFORM, "gaseous form", "Changes the caster into a cloud of gas.", MT_NOTHING, 0, OC_SPELL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 7, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL); addot(OT_S_ENCHANT, "enchantment", "Magically enhances a weapon or piece of armour.", MT_NOTHING, 0, OC_SPELL); addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL); @@ -5201,6 +5175,7 @@ void initobjects(void) { addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJSELF, NA, NA, NULL); addot(OT_S_FLASH, "flash", "Causes a very bright flash, stunning anyone who sees it.", MT_NOTHING, 0, OC_SPELL); addflag(lastot->flags, F_SPELLSCHOOL, SS_WILD, NA, NA, NULL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL); // l6 @@ -5281,10 +5256,8 @@ void initobjects(void) { 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_RESEARCH, "manual of research", "Teaches you the skill 'research'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_RESEARCH, NA, NA, NULL); - addot(OT_MAN_MAGITEMUSAGE, "manual of magic item usage", "Teaches you the skill 'magic item usage'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_MAGITEMUSAGE, 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_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 spellcasting", "Teaches you the skill 'spellcasting'.", MT_PAPER, 3, OC_BOOK); @@ -5295,6 +5268,17 @@ void initobjects(void) { 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); + // 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); @@ -5319,8 +5303,8 @@ void initobjects(void) { 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_EARTH, "manual of earth magic", "Teaches you the skill 'earth magic'.", MT_PAPER, 3, OC_BOOK); - addflag(lastot->flags, F_MANUALOF, SK_SS_EARTH, 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_ICE, "manual of ice magic", "Teaches you the skill 'ice magic'.", MT_PAPER, 3, OC_BOOK); @@ -5375,6 +5359,8 @@ void initobjects(void) { // 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); // elemental - fire @@ -5443,6 +5429,8 @@ void initobjects(void) { 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_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); @@ -5450,6 +5438,8 @@ void initobjects(void) { 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); @@ -5478,8 +5468,7 @@ void initobjects(void) { f2 = hasflag(spelltype->flags, F_SPELLLEVEL); if (f2) { int rarity; - // ie. 80 - spelllevel*12 - rarity = 80 - (f2->val[0]*12); + 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); @@ -5503,7 +5492,7 @@ void initobjects(void) { 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, 80, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 83, NA, 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); @@ -5519,12 +5508,12 @@ void initobjects(void) { 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, 70, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 73, NA, NULL); addflag(lastot->flags, F_LINKSPELL, OT_S_CONECOLD, 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, 70, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 73, NA, 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); @@ -5603,7 +5592,7 @@ void initobjects(void) { addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_EXPLODEONDAM, NA, NA, NA, "8d2"); addflag(lastot->flags, F_DTVULN, DT_FIRE, NA, NA, "2d6"); - addflag(lastot->flags, F_FLAMMABLE, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_FLAMMABLE, 3, NA, NA, NULL); addflag(lastot->flags, F_POWDER, B_TRUE, NA, NA, NULL); addot(OT_LAMPOIL, "oil lamp", "An oil-powered lamp which produces light.", MT_METAL, 1, OC_TOOLS); @@ -5613,7 +5602,7 @@ void initobjects(void) { addflag(lastot->flags, F_OPERONOFF, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_ACTIVATECONFER, F_PRODUCESLIGHT, 2, NA, NULL); addflag(lastot->flags, F_PRODUCESLIGHT, 2, NA, IFACTIVE, NULL); - addflag(lastot->flags, F_RNDCHARGES, 50, 100, NA, NULL); + addflag(lastot->flags, F_RNDCHARGES, 100, 200, NA, NULL); addflag(lastot->flags, F_REFILLWITH, OT_POT_OIL, NA, NA, NULL); addflag(lastot->flags, F_LIGHTSOURCE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_CHARGELOWMSG, B_TRUE, NA, NA, "flickers"); @@ -5626,7 +5615,7 @@ void initobjects(void) { addflag(lastot->flags, F_OPERONOFF, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_ACTIVATECONFER, F_PRODUCESLIGHT, 3, NA, NULL); addflag(lastot->flags, F_PRODUCESLIGHT, 3, NA, IFACTIVE, NULL); - addflag(lastot->flags, F_RNDCHARGES, 100, 200, NA, NULL); + addflag(lastot->flags, F_RNDCHARGES, 200, 300, NA, NULL); addflag(lastot->flags, F_REFILLWITH, OT_POT_OIL, NA, NA, NULL); addflag(lastot->flags, F_LIGHTSOURCE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_CHARGELOWMSG, B_TRUE, NA, NA, "flickers"); @@ -5652,6 +5641,7 @@ void initobjects(void) { addflag(lastot->flags, F_PRODUCESLIGHT, 2, NA, IFACTIVE, NULL); addflag(lastot->flags, F_RNDCHARGES, 50, 100, NA, NULL); addflag(lastot->flags, F_REFILLWITH, OT_POT_OIL, NA, NA, NULL); + addflag(lastot->flags, F_RODSHAPED, B_TRUE, NA, NA, NULL); // tech - l0 addot(OT_CREDITCARD, "credit card", "A rectangular plastic card.", MT_PLASTIC, 0.01, OC_TECH); @@ -5810,7 +5800,7 @@ void initobjects(void) { addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_GLYPH, NA, NA, NA, "!"); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 82, NA, NULL); addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL); addot(OT_BROKENGLASS, "piece of broken glass", "Sharp shards of broken glass.", MT_GLASS, 0.1, OC_MISC); addflag(lastot->flags, F_STACKABLE, NA, NA, NA, NULL); @@ -5885,7 +5875,7 @@ void initobjects(void) { addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, 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_WALKDAM, DT_ACID, NA, NA, "2d4"); + addflag(lastot->flags, F_WALKDAMBP, BP_FEET, DT_ACID, FALLTHRU, "2d4"); addflag(lastot->flags, F_DRINKABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_LINKOB, OT_POT_ACID, NA, NA, NULL); @@ -5894,12 +5884,12 @@ void initobjects(void) { addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_GLYPH, NA, NA, NA, "{"); addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); - addflag(lastot->flags, F_DIETEXT, NA, NA, NA, "evaporates"); + addflag(lastot->flags, F_OBDIETEXT, NA, NA, NA, "evaporates"); addflag(lastot->flags, F_OBHP, 4, 4, NA, NULL); addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL); addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); - addflag(lastot->flags, F_WALKDAM, DT_ACID, NA, NA, "1d4"); + addflag(lastot->flags, F_WALKDAMBP, BP_FEET, DT_ACID, FALLTHRU, "1d4"); addflag(lastot->flags, F_DRINKABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_LINKOB, OT_POT_ACID, NA, NA, NULL); @@ -5910,6 +5900,20 @@ void initobjects(void) { 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); + 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, "{"); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); + addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_FLAMMABLE, 5, NA, NA, "medium fire"); + addflag(lastot->flags, F_DRINKABLE, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_LINKOB, OT_POT_OIL, NA, NA, NULL); + addflag(lastot->flags, F_SLIPPERY, 13, NA, NA, NULL); + addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_OBHP, 4, 4, NA, NULL); + addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL); + // this isn't made out of water, so that it won't put out fire etc addot(OT_SPLASHWATER, "splash of water", "A small splash of water.", MT_NOTHING, 0, OC_MISC); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL); @@ -5917,13 +5921,24 @@ void initobjects(void) { addflag(lastot->flags, F_GLYPH, C_BLUE, NA, NA, ","); addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); - addflag(lastot->flags, F_DIETEXT, NA, NA, NA, "evaporates"); + addflag(lastot->flags, F_OBDIETEXT, NA, NA, NA, "evaporates"); addflag(lastot->flags, F_OBHP, 5, 5, NA, NULL); addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL); addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DTVULN, DT_FIRE, NA, NA, "0d1+100"); addflag(lastot->flags, F_LINKOB, OT_POT_WATER, NA, NA, NULL); + addot(OT_MUDPOOL, "pool of mud", "A large puddle of wet mud.", MT_WATER, 0, OC_MISC); + addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_GLYPH, C_BROWN, NA, NA, ","); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); + addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_DTIMMUNE, DT_WATER, NA, NA, NULL); + addflag(lastot->flags, F_REDUCEMOVEMENT, 2, NA, NA, NULL); + //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); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); @@ -5934,7 +5949,8 @@ void initobjects(void) { addflag(lastot->flags, F_DTCONVERT, DT_FIRE, NA, NA, "puff of steam"); addflag(lastot->flags, F_DRINKABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_LINKOB, OT_POT_WATER, NA, NA, NULL); - addflag(lastot->flags, F_WALKDAM, DT_WATER, NA, NA, "0d1+1"); + //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); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL); @@ -5946,7 +5962,7 @@ void initobjects(void) { addflag(lastot->flags, F_DTCONVERT, DT_FIRE, NA, NA, "cloud of steam"); addflag(lastot->flags, F_DRINKABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_LINKOB, OT_POT_WATER, NA, NA, NULL); - addflag(lastot->flags, F_WALKDAM, DT_WATER, NA, NA, "0d1+2"); + 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); @@ -5962,7 +5978,7 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_SLIPPERY, 1, NA, NA, NULL); - addflag(lastot->flags, F_DIETEXT, NA, NA, NA, "evaporates"); + addflag(lastot->flags, F_OBDIETEXT, NA, NA, NA, "evaporates"); addflag(lastot->flags, F_OBHP, 3, 3, NA, NULL); addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL); addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL); @@ -6014,7 +6030,7 @@ void initobjects(void) { addflag(lastot->flags, F_OBHP, 6, 6, NA, NULL); addot(OT_WOODENSTOOL, "wooden footstool", "A small, wooden footstool.", MT_WOOD, 5, OC_MISC); - addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, NULL); + addflag(lastot->flags, F_RARITY, H_ALL, 83, NA, NULL); addflag(lastot->flags, F_GLYPH, NA, NA, NA, "\\"); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); @@ -6030,7 +6046,6 @@ void initobjects(void) { // 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_NOPICKUP, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DIECONVERTTEXT, NA, NA, NA, "dies down a little"); addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "medium fire"); addflag(lastot->flags, F_OBHP, 3, 3, NA, NULL); @@ -6039,9 +6054,9 @@ void initobjects(void) { addflag(lastot->flags, F_WALKDAM,DT_FIRE, NA, NA, "2d4+4"); addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); 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_NOPICKUP, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "small fire"); addflag(lastot->flags, F_DIECONVERTTEXT, NA, NA, NA, "dies down a little"); addflag(lastot->flags, F_OBHP, 3, 3, NA, NULL); @@ -6050,20 +6065,20 @@ void initobjects(void) { addflag(lastot->flags, F_WALKDAM, DT_FIRE, NA, NA, "2d4"); addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); 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_NOPICKUP, B_TRUE, NA, NA, NULL); - addflag(lastot->flags, F_DIETEXT, B_TRUE, NA, NA, "goes out"); + 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); addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_WALKDAM, DT_FIRE, NA, NA, "1d4"); addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_PRODUCESLIGHT, 1, NA, NA, NULL); + addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "!"); addot(OT_STEAMCLOUD, "cloud of steam", "A thick cloud of scalding steam.", MT_GAS, 0, OC_EFFECT); addflag(lastot->flags, F_GLYPH, NA, NA, NA, "{"); - addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NODIECONVERTTEXT, NA, NA, NA, NULL); addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "puff of steam"); addflag(lastot->flags, F_OBHP, 3, 3, NA, NULL); @@ -6071,20 +6086,39 @@ void initobjects(void) { addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_WALKDAM, DT_FIRE, NA, NA, "1d2"); + addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "!"); addot(OT_STEAMPUFF, "puff of steam", "A small puff of scalding steam.", MT_GAS, 0, OC_EFFECT); - addflag(lastot->flags, F_GLYPH, NA, NA, NA, "{"); - addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); - addflag(lastot->flags, F_DIETEXT, B_TRUE, NA, NA, "disperses"); + addflag(lastot->flags, F_GLYPH, C_GREY, NA, NA, "{"); + addflag(lastot->flags, F_OBDIETEXT, B_TRUE, NA, NA, "disperses"); addflag(lastot->flags, F_OBHP, 2, 2, NA, NULL); addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL); addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_WALKDAM, DT_FIRE, NA, NA, "1d1+1"); + addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "!"); + + + addot(OT_SLEETSTORM, "storm of sleet", "An intense storm of sleet. Hampers movement", MT_GAS, 0, OC_EFFECT); + addflag(lastot->flags, F_GLYPH, C_CYAN, NA, NA, "{"); + addflag(lastot->flags, F_NODIECONVERTTEXT, NA, NA, NA, NULL); + addflag(lastot->flags, F_OBHP, 10, 10, NA, NULL); + addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL); + addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_BLOCKSVIEW, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_REDUCEMOVEMENT, 2, NA, NA, NULL); + addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "!"); + addflag(lastot->flags, F_WALKDAMBP, BP_HEAD, DT_WATER, NA, "1d2"); + addflag(lastot->flags, F_WALKDAMBP, BP_SHOULDERS, DT_WATER, NA, "1d2"); + addflag(lastot->flags, F_WALKDAMBP, BP_BODY, DT_WATER, NA, "1d2"); + addflag(lastot->flags, F_WALKDAMBP, BP_HANDS, DT_WATER, NA, "1d2"); + addflag(lastot->flags, F_WALKDAMBP, BP_LEGS, DT_WATER, NA, "1d2"); + addflag(lastot->flags, F_WALKDAMBP, BP_FEET, DT_WATER, NA, "1d2"); addot(OT_SMOKECLOUD, "cloud of smoke", "A thick cloud of black smoke.", MT_GAS, 0, OC_EFFECT); addflag(lastot->flags, F_GLYPH, NA, NA, NA, "{"); - addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NODIECONVERTTEXT, NA, NA, NA, NULL); addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "puff of smoke"); addflag(lastot->flags, F_OBHP, 3, 3, NA, NULL); @@ -6092,19 +6126,19 @@ void initobjects(void) { addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_BLOCKSVIEW, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "!"); addot(OT_SMOKEPUFF, "puff of smoke", "A small puff of black smoke.", MT_GAS, 0, OC_EFFECT); addflag(lastot->flags, F_GLYPH, NA, NA, NA, "{"); - addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); - addflag(lastot->flags, F_DIETEXT, B_TRUE, NA, NA, "disperses"); + addflag(lastot->flags, F_OBDIETEXT, B_TRUE, NA, NA, "disperses"); addflag(lastot->flags, F_OBHP, 2, 2, NA, NULL); addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL); addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "."); - addot(OT_POISONCLOUD, "cloud of gas", "A thick cloud of poisonous gas.", MT_GAS, 0, OC_EFFECT); + addot(OT_POISONCLOUD, "cloud of poison gas", "A thick cloud of poisonous gas.", MT_GAS, 0, OC_EFFECT); addflag(lastot->flags, F_GLYPH, C_GREEN, NA, NA, "{"); - addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DIECONVERTTEXT, NA, NA, NA, "thins out a little"); addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "puff of gas"); addflag(lastot->flags, F_OBHP, 3, 3, NA, NULL); @@ -6112,27 +6146,68 @@ void initobjects(void) { addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_WALKDAM, DT_POISONGAS, NA, NA, "1d4"); + addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "!"); - addot(OT_POISONPUFF, "puff of gas", "A small puff of poisonous gas.", MT_GAS, 0, OC_EFFECT); + addot(OT_POISONPUFF, "puff of poison gas", "A small puff of poisonous gas.", MT_GAS, 0, OC_EFFECT); addflag(lastot->flags, F_GLYPH, C_GREEN, NA, NA, "{"); - addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); - addflag(lastot->flags, F_DIETEXT, B_TRUE, NA, NA, "disperses"); + addflag(lastot->flags, F_OBDIETEXT, B_TRUE, NA, NA, "disperses"); addflag(lastot->flags, F_OBHP, 2, 2, NA, NULL); addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL); addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_WALKDAM, DT_POISONGAS, NA, NA, "1d2"); + addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "!"); + + addot(OT_HAILSTORM, "hail storm", "An intense storm of damaging hail.", MT_GAS, 0, OC_EFFECT); + addflag(lastot->flags, F_GLYPH, C_WHITE, NA, NA, "{"); + addflag(lastot->flags, F_NODIECONVERTTEXT, NA, NA, NA, NULL); + addflag(lastot->flags, F_OBHP, 10, 10, NA, NULL); + addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL); + addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "!"); + addflag(lastot->flags, F_WALKDAM, DT_COLD, NA, NA, "1d4"); + addflag(lastot->flags, F_WALKDAMBP, BP_HEAD, DT_WATER, NA, "1d2"); + addflag(lastot->flags, F_WALKDAMBP, BP_SHOULDERS, DT_WATER, NA, "1d2"); + addflag(lastot->flags, F_WALKDAMBP, BP_BODY, DT_WATER, NA, "1d2"); + addflag(lastot->flags, F_WALKDAMBP, BP_HANDS, DT_WATER, NA, "1d2"); + addflag(lastot->flags, F_WALKDAMBP, BP_LEGS, DT_WATER, NA, "1d2"); + addflag(lastot->flags, F_WALKDAMBP, BP_FEET, DT_WATER, NA, "1d2"); addot(OT_MAGICBARRIER, "magical barrier", "A glowing, impassable barrier of magical energy.", MT_MAGIC, 0, OC_EFFECT); addflag(lastot->flags, F_GLYPH, NA, NA, NA, "#"); - addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_IMPASSABLE, SZ_MAX, NA, NA, NULL); addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL); addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL); - addflag(lastot->flags, F_DIETEXT, B_TRUE, NA, NA, "vanishes"); + addflag(lastot->flags, F_OBDIETEXT, B_TRUE, NA, NA, "vanishes"); addflag(lastot->flags, F_PRODUCESLIGHT, 1, NA, NA, NULL); + addot(OT_VINE, "entangling vine", "A living vine which grasps nearby creature", MT_SILK, 0.1, OC_EFFECT); + 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, "^"); + addflag(lastot->flags, F_RESTRICTMOVEMENT, 25, B_FALSE, NA, 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); + addflag(lastot->flags, F_DTVULN, DT_ACID, NA, NA, NULL); + addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "!"); + + addot(OT_WEB, "web", "A huge, sticky spider web.", MT_SILK, 0.1, OC_EFFECT); + 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, "^"); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); + addflag(lastot->flags, F_RESTRICTMOVEMENT, 25, B_TRUE, NA, 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); + addflag(lastot->flags, F_DTVULN, DT_FIRE, NA, NA, NULL); + addflag(lastot->flags, F_DTVULN, DT_ACID, NA, NA, NULL); + addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "!"); + // armour - body addot(OT_COTTONSHIRT, "cotton shirt", "A comfortable white cotton shirt.", MT_CLOTH, 0.7, OC_ARMOUR); addflag(lastot->flags, F_RARITY, H_ALL, 80, NA, NULL); @@ -6189,7 +6264,7 @@ void initobjects(void) { addflag(lastot->flags, F_ARMOURRATING, 2, NA, NA, NULL); addflag(lastot->flags, F_EVASION, 0, NA, NA, NULL); addflag(lastot->flags, F_OBHP, 10, 10, NA, NULL); - addot(OT_SILKSHIRT, "silk shirt", "A lightweight, comfortable white silk shirt.", MT_CLOTH, 0.5, OC_ARMOUR); + addot(OT_SILKSHIRT, "silk shirt", "A lightweight, comfortable white silk shirt.", MT_SILK, 0.5, OC_ARMOUR); addflag(lastot->flags, F_RARITY, H_ALL, 60, NA, NULL); addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL); addflag(lastot->flags, F_ARMOURRATING, 0, NA, NA, NULL); @@ -6211,6 +6286,7 @@ void initobjects(void) { addflag(lastot->flags, F_GOESON, BP_SHOULDERS, NA, NA, NULL); addflag(lastot->flags, F_ARMOURRATING, 1, NA, NA, NULL); addflag(lastot->flags, F_OBHP, 6, 6, NA, NULL); + addflag(lastot->flags, F_WATERPROOF, B_TRUE, NA, NA, NULL); // armour - waist addot(OT_BELTLEATHER, "leather belt", "A plain leather belt.", MT_LEATHER, 0.2, OC_ARMOUR); addflag(lastot->flags, F_RARITY, H_ALL, 85, NA, NULL); @@ -6267,7 +6343,7 @@ void initobjects(void) { addflag(lastot->flags, F_OBHP, 5, 5, NA, NULL); // armour - gloves addot(OT_GLOVESCLOTH, "pair of cloth gloves", "A pair of soft cloth gloves.", MT_CLOTH, 0.15, OC_ARMOUR); - addflag(lastot->flags, F_RARITY, H_ALL, 80, NA, NULL); + addflag(lastot->flags, F_RARITY, H_ALL, 83, NA, NULL); addflag(lastot->flags, F_GOESON, BP_HANDS, NA, NA, NULL); addflag(lastot->flags, F_ARMOURRATING, 0, NA, NA, NULL); addflag(lastot->flags, F_EVASION, 0, NA, NA, NULL); @@ -6365,14 +6441,14 @@ void initobjects(void) { // armour - shields addot(OT_BUCKLER, "buckler", "A small, unobtrusive wooden shield.", MT_WOOD, 3.00, OC_ARMOUR); - addflag(lastot->flags, F_RARITY, H_ALL, 80, NA, NULL); + addflag(lastot->flags, F_RARITY, H_ALL, 83, NA, NULL); addflag(lastot->flags, F_SHIELD, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_GOESON, BP_SECWEAPON, NA, NA, NULL); addflag(lastot->flags, F_ARMOURRATING, 4, NA, NA, NULL); addflag(lastot->flags, F_EQUIPCONFER, F_SHIELDPENALTY, 5, NA, NULL); addflag(lastot->flags, F_OBHP, 10, 10, NA, NULL); addot(OT_SHIELD, "shield", "A medium-sized metal shield.", MT_METAL, 4.00, OC_ARMOUR); - addflag(lastot->flags, F_RARITY, H_ALL, 80, NA, NULL); + addflag(lastot->flags, F_RARITY, H_ALL, 76, NA, NULL); addflag(lastot->flags, F_SHIELD, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_GOESON, BP_SECWEAPON, NA, NA, NULL); addflag(lastot->flags, F_ARMOURRATING, 6, NA, NA, NULL); @@ -6429,8 +6505,12 @@ void initobjects(void) { addflag(lastot->flags, F_EQUIPCONFER, F_ATTRMOD, A_DEX, 1, NULL); // '1' is randomized during generation addflag(lastot->flags, F_IDWHENUSED, B_TRUE, NA, NA, NULL); + 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_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, 65, NA, ""); + addflag(lastot->flags, F_RARITY, H_ALL, 73, NA, ""); addflag(lastot->flags, F_EQUIPCONFER, F_EXTRADAM, NA, NA, "0d0+4"); addflag(lastot->flags, F_ENCHANTABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_IDWHENUSED, B_TRUE, NA, NA, NULL); @@ -6535,6 +6615,7 @@ void initobjects(void) { addflag(lastot->flags, F_DAM, DT_TOUCH, NA, NA, "0d1"); addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL); addflag(lastot->flags, F_HITCONFER, F_PARALYZED, SC_CON, 22, "2-4"); + addflag(lastot->flags, F_HITCONFERVALS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOSTRDAMMOD, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_NONE, NA, NA, NULL); addflag(lastot->flags, F_UNARMEDWEP, B_TRUE, NA, NA, NULL); @@ -6542,6 +6623,7 @@ void initobjects(void) { addflag(lastot->flags, F_DAM, DT_TOUCH, NA, NA, "0d1"); addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL); addflag(lastot->flags, F_HITCONFER, F_PARALYZED, SC_CON, 30, "5-10"); + addflag(lastot->flags, F_HITCONFERVALS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOSTRDAMMOD, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_NONE, NA, NA, NULL); addflag(lastot->flags, F_UNARMEDWEP, B_TRUE, NA, NA, NULL); @@ -6554,6 +6636,7 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, ""); addflag(lastot->flags, F_NUMAPPEAR, 1, 10, NA, ""); addflag(lastot->flags, F_CANHAVEOBMOD, OM_POISONED, 17, NA, NULL); + addflag(lastot->flags, F_RODSHAPED, B_TRUE, NA, NA, NULL); addot(OT_NANODART, "nanodart", "A metal dart with a laser-sharpened point.", MT_METAL, 0.5, OC_MISSILE); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, ""); @@ -6569,7 +6652,7 @@ void initobjects(void) { addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, ""); addflag(lastot->flags, F_MISSILEDAM, 3, NA, NA, ""); addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, ""); - addflag(lastot->flags, F_NUMAPPEAR, 1, 3, NA, ""); + addflag(lastot->flags, F_NUMAPPEAR, 1, 2, NA, ""); addflag(lastot->flags, F_OBHP, 3, 3, NA, ""); addflag(lastot->flags, F_CANHAVEOBMOD, OM_POISONED, 17, NA, NULL); @@ -6581,6 +6664,7 @@ void initobjects(void) { addflag(lastot->flags, F_OBHP, 2, 2, NA, NULL); addflag(lastot->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_CANHAVEOBMOD, OM_POISONED, 17, NA, NULL); + addflag(lastot->flags, F_RODSHAPED, B_TRUE, NA, NA, NULL); addot(OT_BOLT, "bolt", "A sharp metal spike, meant for firing from a crossbow.", MT_METAL, 1, OC_MISSILE); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, ""); @@ -6679,7 +6763,7 @@ void initobjects(void) { addflag(lastot->flags, F_PICKLOCKS, 7, B_BLUNTONFAIL, NA, NULL); 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, 35, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 73, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 90, NA, NA, NULL); addflag(lastot->flags, F_DAM, DT_PIERCE, NA, NA, "1d4"); addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL); @@ -6719,14 +6803,14 @@ 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, 70, NA, NULL); + 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, ST_STRONG, NA, NULL); addot(OT_GREATSWORD, "greatsword", "A massive two-handed sword.", MT_METAL, 10, OC_WEAPON); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 55, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 180, NA, NA, NULL); addflag(lastot->flags, F_DAM, DT_SLASH, NA, NA, "1d12+6"); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); @@ -6771,7 +6855,7 @@ void initobjects(void) { addflag(lastot->flags, F_USESSKILL, SK_POLEARMS, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, ST_STRONG, NA, NULL); addot(OT_GUISARME, "guisarme", "A hooked polearm, made by attaching a hook to a spear shaft.", MT_METAL, 4, OC_WEAPON); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 67, NA, NULL); addflag(lastot->flags, F_TRIPATTACK, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 130, NA, NA, NULL); @@ -6791,7 +6875,7 @@ void initobjects(void) { addflag(lastot->flags, F_ATTREQ, A_STR, ST_STRONG, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_DEX, DX_AVERAGE, NA, NULL); addot(OT_LANCE, "lance", "A pole weapon designed for use while mounted.", MT_METAL, 4, OC_WEAPON); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 67, NA, NULL); addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 140, NA, NA, NULL); addflag(lastot->flags, F_DAM, DT_PIERCE, NA, NA, "1d8+2"); @@ -6799,7 +6883,7 @@ void initobjects(void) { addflag(lastot->flags, F_USESSKILL, SK_POLEARMS, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, ST_STRONG, NA, NULL); addot(OT_RANSEUR, "ranseur", "A long spear and cross hilt, resembling a pole-mounted sai. Good for disarming.", MT_METAL, 1, OC_WEAPON); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 67, NA, NULL); addflag(lastot->flags, F_DISARMATTACK, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 120, NA, NA, NULL); @@ -6843,9 +6927,10 @@ void initobjects(void) { addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_STAVES, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, ST_VWEAK, NA, NULL); + addflag(lastot->flags, F_RODSHAPED, B_TRUE, NA, NA, NULL); // clubs (bashing) - addot(OT_CLUB, "club", "A heavy, blunt wooden instrument to hit things with.", MT_STONE, 1.5, OC_WEAPON); + addot(OT_CLUB, "club", "A heavy, blunt wooden instrument to hit things with.", MT_WOOD, 1.5, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 140, NA, NA, NULL); addflag(lastot->flags, F_DAM, DT_BASH, NA, NA, "1d6"); @@ -6912,6 +6997,7 @@ void initobjects(void) { addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_CLUBS, NA, NA, NULL); addflag(lastot->flags, F_NOQUALITY, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_RODSHAPED, B_TRUE, NA, NA, NULL); // projectile weapons addot(OT_BOW, "bow", "A weapon which projects arrows via its elasticity.", MT_WOOD, 3, OC_WEAPON); @@ -6923,6 +7009,7 @@ void initobjects(void) { addflag(lastot->flags, F_RANGE, 5, NA, NA, NULL); addflag(lastot->flags, F_AMMOOB, OT_ARROW, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, ST_AVERAGE, NA, NULL); + addflag(lastot->flags, F_RODSHAPED, B_TRUE, NA, NA, NULL); addot(OT_CROSSBOW, "crossbow", "A standard crossbow. Very powerful, but needs high strength to use.", MT_WOOD, 5, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); @@ -7154,6 +7241,13 @@ int isdangerousob(object_t *o, lifeform_t *lf, int onlyifknown) { return B_FALSE; } +int isdeadob(object_t *o) { + if (hasflag(o->flags, F_DEAD)) { + return B_TRUE; + } + return B_FALSE; +} + int isdrinkable(object_t *o) { switch (o->type->obclass->id) { case OC_POTION: @@ -7804,6 +7898,10 @@ void makewet(object_t *o, int amt) { char obnamefull[BUFLEN]; flag_t *f; + if (hasflag(o->flags, F_WATERPROOF)) { + return; + } + loc = getoblocation(o); owner = o->pile->owner; if (owner) { @@ -8087,7 +8185,7 @@ void obdie(object_t *o) { real_getobname(o, obname, o->amt, B_TRUE, B_FALSE, B_TRUE, B_TRUE); if (!hasflag(o->flags, F_NOOBDIETEXT)) { // announce the death - f = hasflag(o->flags, F_DIETEXT); + f = hasflag(o->flags, F_OBDIETEXT); if (f) { sprintf(desc, "%s", f->text); } else if (oblastdamtype(o) == DT_DECAY) { @@ -8190,40 +8288,46 @@ int brandappliesto(brand_t *om, objecttype_t *ot) { int obmatchescondition(object_t *o, long opts) { - int ok = B_TRUE; - if ((opts & AO_ONLYEQUIPPED) && !hasflag(o->flags, F_EQUIPPED)) { + int ok; + + if (opts) { + // default to not ok ok = B_FALSE; + } else { + // default to ok + ok = B_TRUE; } - if ((opts & AO_EQUIPPEDARMOUR)) { + if ((opts & AO_ONLYEQUIPPED) && hasflag(o->flags, F_EQUIPPED)) { + ok = B_TRUE; + } + if ((opts & AO_EQUIPPEDNONWEAPON)) { flag_t *ff; ff = hasflag(o->flags, F_EQUIPPED); - if (!ff) { - ok = B_FALSE; - } else if (ff->val[0] == BP_WEAPON) { - ok = B_FALSE; + if (ff) { + if ((ff->val[0] != BP_WEAPON) && + (ff->val[0] != BP_SECWEAPON)) { + ok = B_TRUE; + } + } + } + if ((opts & AO_EDIBLE) && isedible(o)) ok = B_TRUE; + if ((opts & AO_DRINKABLE) && isdrinkable(o)) ok = B_TRUE; + 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])) { + ok = B_TRUE; } } - if ((opts & AO_EDIBLE) && !isedible(o)) ok = B_FALSE; - if ((opts & AO_READABLE) && !isreadable(o)) ok = B_FALSE; - if ((opts & AO_ARMOUR) && (o->type->obclass->id != OC_ARMOUR)) ok = B_FALSE; - if ((opts & AO_WEARABLE) && !iswearable(o)) { - ok = B_FALSE; - } - if ((opts & AO_WEILDABLE) && !isweapon(o)) { - ok = B_FALSE; - } - if ((opts & AO_OPERABLE) && !isoperable(o)) { - ok = B_FALSE; - } - if ((opts & AO_POURABLE) && !ispourable(o)) { - ok = B_FALSE; - } - if ((opts & AO_NOTIDENTIFIED) && isidentified(o)) { - ok = B_FALSE; - } - if ((opts & AO_NOTKNOWN) && isknown(o)) { - ok = B_FALSE; - } + if ((opts & AO_WEARABLE) && iswearable(o)) ok = B_TRUE; + if ((opts & AO_WEILDABLE) && isweapon(o)) ok = B_TRUE; + if ((opts & AO_OPERABLE) && isoperable(o)) ok = B_TRUE; + if ((opts & AO_POURABLE) && ispourable(o)) ok = B_TRUE; + if ((opts & AO_NOTIDENTIFIED) && !isidentified(o)) ok = B_TRUE; + if ((opts & AO_NOTKNOWN) && !isknown(o)) ok = B_TRUE; + return ok; } @@ -8393,7 +8497,9 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { } } - touch(lf, o); + if (touch(lf, o)) { + return B_TRUE; + } if (hasflag(o->flags, F_DEAD)) return B_TRUE; // TODO: change to be based on item type @@ -8462,7 +8568,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { if (power == NA) power = 1; if (isblessed(o)) power += 4; - power += (getskill(lf, SK_MAGITEMUSAGE)*2); + power += (getskill(lf, SK_CHANNELING)*2); // certain wands always used the blessed version of spells // certain wands have different effects when cursed @@ -8491,7 +8597,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { case 0: // butterflies around user willid = B_TRUE; where = getrandomadjcell(lf->cell, WE_WALKABLE, B_ALLOWEXPAND); - addmonster(where, R_BUTTERFLY, B_FALSE, rnd(10,20)); + addmonster(where, R_BUTTERFLY, B_FALSE, rnd(10,20), B_FALSE); if (haslos(player, where)) { msg("A swarm of butterflies appears!"); } @@ -8571,7 +8677,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { o->blessknown = B_TRUE; } if (isplayer(lf)) { - real_getobname(o, obname, 1, B_FALSE, B_TRUE, B_FALSE, B_FALSE); // don't adjust for blindness + real_getobname(o, obname, 1, B_FALSE, B_TRUE, B_FALSE, B_TRUE); // don't adjust for blindness msg("This is %s!",obname); } } @@ -8592,7 +8698,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { } } // big spray - addob(where->obpile, "cloud of gas"); + addob(where->obpile, "cloud of poison gas"); if (isplayer(lf)) { msg("Psssssssst!"); seen = B_TRUE; @@ -9196,7 +9302,9 @@ void quaff(lifeform_t *lf, object_t *o) { maketried(o->type->id); - touch(lf, o); + if (touch(lf, o)) { + return; + } if (hasflag(o->flags, F_DEAD)) return; if (o->material->id == MT_ICE) { @@ -9699,7 +9807,9 @@ int readsomething(lifeform_t *lf, object_t *o) { maketried(o->type->id); // some checks first... - touch(lf, o); + if (touch(lf, o)) { + return B_TRUE; + } if (hasflag(o->flags, F_DEAD)) { return B_TRUE; } @@ -9736,6 +9846,7 @@ 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_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 @@ -9751,6 +9862,7 @@ int readsomething(lifeform_t *lf, object_t *o) { // ask for a target object of any type if scroll is unknown? switch (o->type->id) { case OT_SCR_IDENTIFY: + case OT_SCR_MENDING: case OT_SCR_ENCHANT: needsob = B_TRUE; break; @@ -9782,7 +9894,7 @@ int readsomething(lifeform_t *lf, object_t *o) { if (power == NA) power = 1; // increase based on your magic item usage skill - power += (getskill(lf, SK_MAGITEMUSAGE)*2); + power += (getskill(lf, SK_CHANNELING)*2); // blessed scrolls are more powerful if (isblessed(o)) power += 4; @@ -10039,6 +10151,211 @@ void setobcreatedby(object_t *o, lifeform_t *lf) { addflag(o->flags, F_CREATEDBY, lf->id, NA, NA, lfname); } + +void shatter(object_t *o, int hitlf, char *damstring, lifeform_t *fromlf) { + int shatterdam; + cell_t *where = NULL; + lifeform_t *target = NULL; + char buf[BUFLEN]; + char obname[BUFLEN]; + char targetname[BUFLEN]; + int seen = B_FALSE; + + getobname(o,obname,o->amt); + where = getoblocation(o); + + if (hitlf) { + target = where->lf; + } else { + target = NULL; + } + + if (target) { + getlfname(target, targetname); + } + + // announce + if (haslos(player, where)) { + char *obcaps; + obcaps = strdup(obname); + capitalise(obcaps); + obcaps = strrep(obcaps, "An ", "The ", NULL); + obcaps = strrep(obcaps, "A ", "The ", NULL); + msg("%s shatters!",obcaps); + free(obcaps); + + seen = B_TRUE; + } else { + noise(where, NULL, "shattering glass.", NULL); + } + + if (target) { + shatterdam = getshatterdam(o); + if (shatterdam && !isdead(target)) { + // extra glass damage + if (seen) { + msg("%s %s showered in %s shards!", targetname, isplayer(target) ? "are" : "is", + o->material->name); + } + losehp(target, shatterdam, DT_SLASH, fromlf, damstring); + } + } + + + // place shards + if (o->material->id == MT_GLASS) { + int numshards; + numshards = getnumshards(o); + // place glass shards + sprintf(buf, "%d pieces of broken glass",numshards); + addob(where->obpile, buf); + } else if (o->material->id == MT_ICE) { + int numshards; + numshards = getnumshards(o) / 15; + if (numshards < 1) numshards = 1; + + // ice + sprintf(buf, "%d chunks of ice",numshards); + addob(where->obpile, buf); + } + + // potion effects (only if you hit)? + if (o->type->obclass->id == OC_POTION) { + // effects on lifeforms + if (hitlf && target) { + int observed; + // some potions have special effects... + switch (o->type->id) { + case OT_POT_ACID: // take acid damage + if (seen) { + makeknown(o->type->id); + } + if (target) { + if (seen) { + msg("%s %s splashed with acid!", targetname, + isplayer(target) ? "are" : "is"); + } + losehp(target, rnd(1,5)*o->amt, DT_ACID, fromlf, "a splash of acid"); + } else { + // announce + if (seen) { + msg("Acid splashes all over the floor!"); + } + } + break; + case OT_POT_BLOOD: + if (seen) { + makeknown(o->type->id); + } + if (target) { + if (seen) { + msg("%s %s splashed with blood.", targetname, + isplayer(target) ? "are" : "is"); + } + } else { + // announce + if (seen) { + msg("Blood splashes onto the floor."); + } + } + break; + case OT_POT_ELEMENTIMMUNE: + case OT_POT_ETHEREALNESS: + case OT_POT_GASEOUSFORM: + case OT_POT_POISON: + case OT_POT_POLYMORPH: + case OT_POT_INVIS: + case OT_POT_SANCTUARY: // apply regular potion effects, and make them known + if (target) { + if (seen) { + makeknown(o->type->id); + } + potioneffects(target, o->type->id, 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); + if (observed) { + makeknown(o->type->id); + } + } + break; + case OT_POT_OIL: + if (seen) { + makeknown(o->type->id); + msg("%s %s covered with oil!", targetname, isplayer(target) ? "are" : "is"); + } + // target is temporarily vulnerable to fire. + addtempflag(target->flags, F_DTVULN, DT_FIRE, NA, NA, "1d6", rnd(5,10)); + break; + case OT_POT_WATER: + if (seen) makeknown(o->type->id); + if (target) { + if (seen) { + msg("%s %s splashed with water.", targetname, + isplayer(target) ? "are" : "is"); + } + + if (hasflag(target->flags, F_UNDEAD) && isblessed(o)) { + if (isplayer(target)) { + msg("The water burns like acid!"); + } else if (cansee(player, target)) { + msg("%s writhes in agony!", targetname); + } + losehp(target, o->amt*rnd(5,10), DT_HOLY, NULL, "holy water"); + if (seen) { + // we now know that it is blessed + o->blessknown = B_TRUE; + } + } else { + losehp(target, 0, DT_WATER, fromlf, "a splash of water"); + } + } else { + // all objects take damage + object_t *oo,*nextoo; + // announce + if (seen) { + msg("Water splashes onto the floor."); + } + //TODO: holy water blesses everything? + // everything here takes water damage + for (oo = where->obpile->first ; oo ; oo = nextoo) { + nextoo = oo->next; + takedamage(oo, 0, DT_WATER); + } + } + + break; + default: + break; + } + } else { // ie. you didn't hit anyone + switch (o->type->id) { + case OT_POT_OIL: + if (seen) { + makeknown(o->type->id); + msg("The floor is covered with oil!"); + } + break; + case OT_POT_WATER: + if (seen) { + makeknown(o->type->id); + msg("The floor is covered with water!"); + } + break; + default: + break; + } + } + } + + // object is dead. + addflag(o->flags, F_DEAD, B_TRUE, NA, NA, NULL); + addflag(o->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL); +} + // randomizes hidden names void shufflehiddennames(void) { int i,n; @@ -10130,6 +10447,9 @@ int takedamage(object_t *o, unsigned int howmuch, int damtype) { if (damtype == DT_FIRE) { if (isflammable(o)) { ignite(o); + if (isdeadob(o)) { + return howmuch; + } } } @@ -10279,6 +10599,8 @@ int takedamage(object_t *o, unsigned int howmuch, int damtype) { if (damtype != DT_DECAY) { msg("%s %s!", obname, getobhurtname(o, damtype)); } + // if you see a secret door get damaged, it's not secret anymore. + killflagsofid(o->flags, F_SECRETDOOR); } } @@ -10296,7 +10618,6 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed, char realthrowernamea[BUFLEN]; char obname[BUFLEN]; char targetname[BUFLEN]; - char buf[BUFLEN]; lifeform_t *target; cell_t *srcloc; int seen; @@ -10411,7 +10732,9 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed, // touch effects if (thrower && !firearm) { if (o->pile == thrower->pack) { - touch(thrower, o); + if (touch(thrower, o)) { + return B_TRUE; + } } } @@ -10576,15 +10899,18 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed, // saving throws if (youhit && !willcatch) { - // first check to see if you can catch it - if (!lfhasflag(target, F_NOPACK) && hasbp(target, BP_HANDS) && - lfhasflag(target, F_HUMANOID) && - !isimmobile(target) && - skillcheck(target, SC_DEX, 15*speed, isblind(target) ? -15 : 0)) { - willcatch = B_TRUE; - } else if (skillcheck(target, SC_DODGE, 10*speed, isblind(target) ? -15 : 0)) { - // then check if we dodge it... - youhit = B_FALSE; + // can the victim see the thrower? + if (thrower && cansee(target, thrower)) { + // first check to see if you can catch it + if (!lfhasflag(target, F_NOPACK) && hasbp(target, BP_HANDS) && + lfhasflag(target, F_HUMANOID) && + !isimmobile(target) && + skillcheck(target, SC_DEX, 15*speed, 0)) { + willcatch = B_TRUE; + } else if (skillcheck(target, SC_DODGE, 10*speed, 0)) { + // then check if we dodge it... + youhit = B_FALSE; + } } } @@ -10618,7 +10944,7 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed, moveob(o, target->pack, amt); return B_FALSE; } else { - int dam = 0,shatterdam = 0; + int dam = 0; char damstring[BUFLEN]; int reduceamt = 0; int throwdam; @@ -10633,27 +10959,20 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed, } // deal extra cutting damage afterwards? - shatterdam = getshatterdam(o); - if (shatterdam > 0) { + if (willshatter(o->material->id)) { shattered = B_TRUE; } // announce if (seen) { char buf2[BUFLEN]; - sprintf(buf2, "%s hit%s %s%s",obname,(amt == 1) ? "s" : "", targetname, - (willshatter(o->material->id)) ? " and shatters!" : "." - ); + sprintf(buf2, "%s hit%s %s.",obname,(amt == 1) ? "s" : "", targetname); if (lfhasflag(player, F_EXTRAINFO)) { char damstring[BUFLEN]; sprintf(damstring, " [%d dmg]",dam); strcat(buf2, damstring); } msg("%s", buf2); - } else { - if (willshatter(o->material->id)) { - noise(where, NULL, "shattering glass.", NULL); - } } sprintf(damstring, "%s (%s by %s)",obname,throwverbpast, realthrowernamea); @@ -10674,19 +10993,10 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed, if (reduceamt && (speed >= 3)) { applyarmourdamage(target, o, reduceamt, DT_PROJECTILE); } - - if (shatterdam && !isdead(target)) { - // extra glass damage - if (seen) { - msg("%s %s showered in glass shards!", targetname, isplayer(target) ? "are" : "is"); - } - sprintf(damstring, "%s (%s by %s)",obname,throwverbpast, realthrowernamea); - losehp(target, shatterdam, DT_SLASH, thrower, damstring); - } wepeffects(o->flags, target->cell, hasflag(o->flags, F_DAM), dam); } - } else { + } else { // ie. if !youhit if (!announcedmiss) { if (isplayer(thrower)) { msg("Your %s misses %s.", noprefix(obname), targetname); @@ -10696,153 +11006,7 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed, announcedmiss = B_TRUE; } } - } - - if (!target || !youhit) { - // will it shatter on the ground? - if (willshatter(o->material->id)) { - if (haslos(player, where)) { - char *obcaps; - obcaps = strdup(obname); - capitalise(obcaps); - obcaps = strrep(obcaps, "An ", "The ", NULL); - obcaps = strrep(obcaps, "A ", "The ", NULL); - msg("%s shatters!",obcaps); - free(obcaps); - } else { - noise(where, NULL, "shattering glass.", NULL); - } - shattered = B_TRUE; - } - } - - // either remove or move the object - if (shattered) { - if (o->material->id == MT_GLASS) { - int numshards; - numshards = getnumshards(o); - // place glass shards - sprintf(buf, "%d pieces of broken glass",numshards); - addob(where->obpile, buf); - } else if (o->material->id == MT_ICE) { - int numshards; - numshards = getnumshards(o) / 15; - if (numshards < 1) numshards = 1; - - // ice - sprintf(buf, "%d chunks of ice",numshards); - addob(where->obpile, buf); - } - - // potion effects (only if you hit)? - if (shattered && youhit) { - if (o->type->obclass->id == OC_POTION) { - int observed; - // some potions have special effects... - switch (o->type->id) { - case OT_POT_ACID: // take acid damage - if (seen) { - makeknown(o->type->id); - } - if (target) { - if (seen) { - msg("%s %s splashed with acid!", targetname, - isplayer(target) ? "are" : "is"); - } - losehp(target, rnd(1,5)*amt, DT_ACID, thrower, "a splash of acid"); - } else { - // announce - if (seen) { - msg("Acid splashes all over the floor!"); - } - } - break; - case OT_POT_ELEMENTIMMUNE: - case OT_POT_ETHEREALNESS: - case OT_POT_GASEOUSFORM: - case OT_POT_POISON: - case OT_POT_POLYMORPH: - case OT_POT_INVIS: - case OT_POT_SANCTUARY: // always make them known - if (target) { - if (seen) { - makeknown(o->type->id); - } - potioneffects(target, o->type->id, 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); - if (observed) { - makeknown(o->type->id); - } - } - break; - case OT_POT_BLOOD: - if (seen) { - makeknown(o->type->id); - } - if (target) { - if (seen) { - msg("%s %s splashed with blood.", targetname, - isplayer(target) ? "are" : "is"); - } - } else { - // announce - if (seen) { - msg("Blood splashes onto the floor."); - } - } - break; - case OT_POT_WATER: - if (seen) { - makeknown(o->type->id); - } - if (target) { - if (seen) { - msg("%s %s splashed with water.", targetname, - isplayer(target) ? "are" : "is"); - } - - if (hasflag(target->flags, F_UNDEAD) && isblessed(o)) { - if (isplayer(target)) { - msg("The water burns like acid!"); - } else if (cansee(player, target)) { - msg("%s writhes in agony!", targetname); - } - losehp(target, amt*rnd(5,10), DT_HOLY, NULL, "holy water"); - if (seen) { - // we now know that it is blessed - o->blessknown = B_TRUE; - } - } else { - losehp(target, 0, DT_WATER, thrower, "a splash of water"); - } - } else { - // all objects take damage - object_t *oo,*nextoo; - // announce - if (seen) { - msg("Water splashes onto the floor."); - } - //TODO: holy water blesses everything? - // everything here takes water damage - for (oo = where->obpile->first ; oo ; oo = nextoo) { - nextoo = oo->next; - takedamage(oo, 0, DT_WATER); - } - } - - break; - default: - break; - } - } - } - } - + } // end if target // heavy ob? if (youhit && target) { @@ -10859,9 +11023,10 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed, newob = moveob(o, where->obpile, amt); // fake its birth time so that it can be damaged newob->birthtime = -1; - if (shattered) { - addflag(newob->flags, F_DEAD, B_TRUE, NA, NA, NULL); - addflag(newob->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL); + if (willshatter(newob->material->id)) { + char dambuf[BUFLEN]; + sprintf(dambuf, "%s (%s by %s)",obname,throwverbpast, realthrowernamea); + shatter(newob, youhit, dambuf, thrower); } else { takedamage(newob, speed, DT_BASH); } @@ -10982,8 +11147,39 @@ void timeeffectsob(object_t *o) { addob(location->obpile, "pile of ash"); } } + + + // checks based on object + if (o->type->id == OT_VINE) { + lifeform_t *creator; + int willvanish = B_FALSE; + + // noone there? + if (!location->lf) { + willvanish = B_TRUE; + } + + // creator no longer has los? + f = hasflag(o->flags, F_CREATEDBY); + if (f) { + creator = findlf(NULL, f->val[0]); + if (!creator || !haslos(creator, location)) { + willvanish = B_TRUE; + } + } + + if (willvanish) { + // vanish. + if (haslos(player, location)) { + msg("%s vanish%s.", obname, (o->amt == 1) ? "es" : ""); + } + killob(o); + return; + } + } } + // check each flag for this object... for (f = o->flags->first ; f ; f = nextf) { object_t *oo,*nextoo; @@ -11434,6 +11630,19 @@ int validateobs(void) { printf("ERROR in object '%s' - F_EXPLODEONDEATH does not have damage string.\n", ot->name); goterror = B_TRUE; } + if (hasflag(ot->flags, F_HITCONFER) && !hasflag(ot->flags, F_HITCONFERVALS)) { + printf("ERROR in object '%s' - has F_HITCONFER, but no HITCONFERVALS defined.\n", ot->name); + goterror = B_TRUE; + } + if (hasflag(ot->flags, F_OBDIETEXT) && hasflag(ot->flags, F_NOOBDIETEXT)) { + printf("ERROR in object '%s' - has both dietext & noobdietext.\n", ot->name); + goterror = B_TRUE; + } + f = hasflag(ot->flags, F_THEREISHERE); + if (f && !strlen(f->text)) { + printf("ERROR in object '%s' - has f_thereishere but no ->text.\n", ot->name); + goterror = B_TRUE; + } } for (sk = firstskill ; sk ; sk = sk->next) { @@ -11534,13 +11743,14 @@ enum COLOUR getmaterialcolour(enum MATERIAL mat) { // is the given material solid or liquid? enum MATSTATE getmaterialstate(enum MATERIAL mat) { switch (mat) { - case MT_NOTHING: case MT_FIRE: case MT_MAGIC: + case MT_NOTHING: return MS_OTHER; - case MT_WATER: - case MT_BLOOD: case MT_ACID: + case MT_BLOOD: + case MT_OIL: + case MT_WATER: return MS_LIQUID; case MT_GAS: return MS_GAS; @@ -11601,3 +11811,9 @@ int getmissileaccuracy(lifeform_t *thrower, cell_t *where, object_t *missile, ob } return acc; } + + + + + + diff --git a/objects.h b/objects.h index ae50800..b5596b3 100644 --- a/objects.h +++ b/objects.h @@ -125,6 +125,7 @@ int isblessknown(object_t *o); int iscorpse(object_t *o); int iscursed(object_t *o); int isdangerousob(object_t *o, lifeform_t *lf, int onlyifknown); +int isdeadob(object_t *o); int isdrinkable(object_t *o); int isedible(object_t *o); flag_t *isequipped(object_t *o); @@ -188,6 +189,7 @@ object_t *relinkob(object_t *src, obpile_t *dst); void setblessed(object_t *o, enum BLESSTYPE wantbless); void setinscription(object_t *o, char *text); void setobcreatedby(object_t *o, lifeform_t *lf); +void shatter(object_t *o, int hitlf, char *damstring, lifeform_t *fromlf); void shufflehiddennames(void); object_t *splitob(object_t *o); int takedamage(object_t *o, unsigned int howmuch, int damtype); diff --git a/save.c b/save.c index 30e1787..48ca2c4 100644 --- a/save.c +++ b/save.c @@ -199,7 +199,11 @@ lifeform_t *loadlf(FILE *f, cell_t *where) { if (db) dblog("--> Got hp=%d/%d. timespend=%d. sorted=%d. Now loading flags.",l->hp,l->maxhp,l->timespent,l->sorted); - // lf flags + // clear existing flags from addlf + while (l->flags->first) { + killflag(l->flags->first); + } + // load lf flags loadflagpile(f, l->flags); if (db) dblog("--> now loading objects"); diff --git a/spell.c b/spell.c index 81c4fe1..80e0cf0 100644 --- a/spell.c +++ b/spell.c @@ -75,34 +75,32 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef } - if (abilid == OT_A_SWOOP) { + if (abilid == OT_A_CHARGE) { cell_t *adjcell = NULL,*origcell; char targetname[BUFLEN]; int i; cell_t *retcell[MAXRETCELLS]; int nretcell; - int srange = 5; - flag_t *srflag; - - // get max range - srflag = lfhasflag(user, F_SWOOPRANGE); - if (srflag) { - srange = srflag->val[0]; - } + int crange = 3; // default if (isimmobile(user)) { if (isplayer(user)) msg("You can't move!"); return B_TRUE; - } else if (!lfhasflag(user, F_FLYING)) { - if (isplayer(user)) msg("You are not flying, therefore cannot swoop."); + } + + // get max range - based on speed. + crange = (int) (((float)SP_NORMAL / (float)getmovespeed(user)) * 2.5); + if (crange <= 1) { + if (isplayer(user)) msg("You are too slow to charge!"); return B_TRUE; } + if (!targcell) { if (isplayer(user)) { - sprintf(buf, "Flyby who (max range %d)?",srange); + sprintf(buf, "Charge who (max range %d)?",crange); // TODO: ask for direction - targcell = askcoords("Flyby who?", TT_MONSTER); + targcell = askcoords(buf, TT_MONSTER); if (!targcell) { msg("Cancelled."); return TRUE; @@ -112,8 +110,8 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef } } - if (getcelldist(user->cell, targcell) > srange) { - if (isplayer(user)) msg("You can't swoop that far!"); + if (getcelldist(user->cell, targcell) > crange) { + if (isplayer(user)) msg("You can't charge that far!"); return B_TRUE; } @@ -153,7 +151,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef // teleport next to them movelf(user, adjcell); if (haslos(player, adjcell)) { - msg("%s swoop%s towards %s!",username,isplayer(user) ? "" : "s",targetname); + msg("%s charge%s towards %s!",username,isplayer(user) ? "" : "s",targetname); needredraw = B_TRUE; drawlevelfor(player); redraw(); @@ -165,13 +163,6 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef // attack attackcell(user, targcell); - - - // teleport back to initial pos - movelf(user, origcell); - if (haslos(player, origcell)) { - redraw(); - } } else if (abilid == OT_A_GRAB) { char dirch; flag_t *f; @@ -444,6 +435,102 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef // cause ongoing pain for 2 turns addtempflag(target->flags, F_PAIN, DT_ACID, NA, NA, damstr, 2); taketime(user, getactspeed(user)); + } else if (abilid == OT_A_SWOOP) { + cell_t *adjcell = NULL,*origcell; + char targetname[BUFLEN]; + int i; + cell_t *retcell[MAXRETCELLS]; + int nretcell; + int srange = 5; + flag_t *srflag; + + // get max range + srflag = lfhasflag(user, F_SWOOPRANGE); + if (srflag) { + srange = srflag->val[0]; + } + + if (isimmobile(user)) { + if (isplayer(user)) msg("You can't move!"); + return B_TRUE; + } else if (!lfhasflag(user, F_FLYING)) { + if (isplayer(user)) msg("You are not flying, therefore cannot swoop."); + return B_TRUE; + } + + if (!targcell) { + if (isplayer(user)) { + sprintf(buf, "Swoop who (max range %d)?",srange); + // TODO: ask for direction + targcell = askcoords(buf, TT_MONSTER); + if (!targcell) { + msg("Cancelled."); + return TRUE; + } + } else { + return B_FALSE; + } + + } + if (getcelldist(user->cell, targcell) > srange) { + if (isplayer(user)) msg("You can't swoop that far!"); + return B_TRUE; + } + + // make sure we have LOF to there + target = targcell->lf; + if (!target) { + if (isplayer(user)) msg("There is nobody there!"); + return TRUE; + } else if (!haslof(user->cell, targcell, LOF_NEED, NULL)) { + if (isplayer(user)) msg("Your path there is blocked!"); + return TRUE; + } + + getlfname(target, targetname); + + // find cell on the way... + calcbresnham(user->cell->map, user->cell->x, user->cell->y, targcell->x, targcell->y, retcell, &nretcell); + for (i = 1; i < nretcell; i++) { + if (retcell[i] == targcell) { + adjcell = retcell[i-1]; + break; + } + } + if (!adjcell) { + if (isplayer(user)) { + msg("There is no space nearby for you to attack!"); + } + return B_TRUE; + } + + // take some time + taketime(user, getactspeed(user)); + + // remember orig cell + origcell = user->cell; + + // teleport next to them + movelf(user, adjcell); + if (haslos(player, adjcell)) { + msg("%s swoop%s towards %s!",username,isplayer(user) ? "" : "s",targetname); + needredraw = B_TRUE; + drawlevelfor(player); + redraw(); + + //if (!isplayer(user)) { + more(); + //} + } + + // attack + attackcell(user, targcell); + + // teleport back to initial pos + movelf(user, origcell); + if (haslos(player, origcell)) { + redraw(); + } } else if (abilid == OT_A_POLYREVERT) { flag_t *f; if (!target) target = user; @@ -657,24 +744,11 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef return B_TRUE; } - if (!safetorest(user)) { - if (getskill(user, SK_STEALTH) == PR_EXPERT) { - // can still hide, but with a penalty - penalty = -4; - } else if (getskill(user, SK_STEALTH) == PR_MASTER) { - // can still hide, but with a penalty - penalty = -2; - } else { - if (isplayer(user)) msg("You can't hide - there are monsters around!"); - return B_TRUE; - } - } - - // no stealth skill? - if (!getskill(user, SK_STEALTH)) { - penalty = -5; + penalty = gethidemodifier(user); + if (reason == E_IMPOSSIBLE) { + if (isplayer(user)) msg("You can't hide - there are monsters around!"); + return B_TRUE; } - // start hiding addflag(user->flags, F_HIDING, penalty, NA, NA, NULL); @@ -748,7 +822,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef } - slev = getskill(user, SK_RESEARCH); + slev = getskill(user, SK_LORE_ARCANA); switch (slev) { case PR_INEPT: mod = -5; @@ -805,7 +879,15 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ stopspell(caster, spellid); return B_FALSE; } else { - addflag(caster->flags, F_BOOSTSPELL, spellid, NA, NA, NULL); + objecttype_t *sp; + int cost; + cost = getmpcost(caster, spellid); + sp = findot(spellid); + + if (sp && hasflag(sp->flags, F_VARPOWER)) { + cost *= power; + } + addflag(caster->flags, F_BOOSTSPELL, spellid, cost, power, NULL); } } @@ -983,6 +1065,16 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } else { fizzle(caster); } + } else if (spellid == OT_S_BARKSKIN) { + flag_t *f; + // always targetted at caster + targcell = caster->cell; + target = caster; + + f = addtempflag(caster->flags, F_MAGICARMOUR, power*2, NA, NA, "skin of bark", FROMSPELL); + f->obfrom = spellid; + f = addtempflag(caster->flags, F_DTVULN, DT_FIRE, NA, NA, "2d4", FROMSPELL); + f->obfrom = spellid; } else if (spellid == OT_S_BLINDNESS) { int failed = B_FALSE; // ask for target @@ -1079,6 +1171,60 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ needredraw = B_TRUE; } + } else if (spellid == OT_S_CALLLIGHTNING) { + int failed = B_FALSE; + // ask for a target cell + if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE, LOF_DONTNEED, spellid, power)) return B_TRUE; + + target = targcell->lf; + if (target) { + char targname[BUFLEN]; + + getlfname(target, targname); + + if (haslos(player, targcell)) { + msg("%s is struck by a bolt of lightning!",targname); + if (seenbyplayer) *seenbyplayer = B_TRUE; + } + + losehp(target, rolldie(3,6), DT_ELECTRIC, caster, "a bolt of lightning"); + } else { + failed = B_TRUE; + } + + if (failed) { + fizzle(caster); + } + } else if (spellid == OT_S_CALMANIMALS) { + int i; + int powerleft; + int donesomething = B_FALSE; + cell_t *c; + powerleft = rolldie(power+1, 4); + for (i = 0; i < caster->nlos; i++) { + c = caster->los[i]; + if (c->lf && (c->lf->race->raceclass->id == RC_ANIMAL) && (gethitdice(c->lf) <= powerleft)) { + if (lfhasflag(c->lf, F_HOSTILE)) { + powerleft -= gethitdice(c->lf); + makepeaceful(c->lf); + + if (cansee(player, c->lf)) { + if (seenbyplayer) *seenbyplayer = B_TRUE; + } + donesomething++; + } + } + if (powerleft <= 0) break; + } + + if (!donesomething) { + fizzle(caster); + } + } else if (spellid == OT_S_CALMINGSCENT) { + // just announce + if (isplayer(caster)) { + msg("A relaxing aroma surrounds you."); + } } else if (spellid == OT_S_CLOUDKILL) { if (!validatespellcell(caster, &targcell, TT_MONSTER, B_FALSE, LOF_NEED, spellid, power)) return B_TRUE; @@ -1123,10 +1269,10 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ msg("%s%s intellect is too simple for you to charm.",targetname,getpossessive(targetname)); break; case E_UNDEAD: - msg("The undead are immune to possession."); + msg("The undead are immune to charming."); break; default: - msg("You cannot possesss %s.", targetname); + msg("You cannot charm %s.", targetname); break; } } @@ -1165,6 +1311,78 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ addtempflag(target->flags, F_CHARMEDBY, caster->id, NA, NA, NULL, howlong); addtempflag(target->flags, F_PETOF, caster->id, NA, NA, NULL, howlong); } + } else if (spellid == OT_S_CHARMANIMAL) { + char targetname[BUFLEN]; + if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE, LOF_DONTNEED, spellid, power)) return B_TRUE; + + target = targcell->lf; + + if (!target) { + fizzle(caster); + return B_FALSE; + } + getlfname(target, targetname); + + // only animals/humanoids + if (!lfhasflag(target, F_ANIMAL)) { + fizzle(caster); + return B_FALSE; + } + + if (!ischarmable(target)) { + if (isplayer(caster)) { + switch (reason) { + case E_DRUNK: + msg("%s%s mind is too alcohol-impaired for you to charm.",targetname,getpossessive(targetname)); + break; + case E_LOWIQ: + msg("%s%s intellect is too simple for you to charm.",targetname,getpossessive(targetname)); + break; + case E_UNDEAD: + msg("The undead are immune to charming."); + break; + default: + msg("You cannot charm %s.", targetname); + break; + } + } + return B_FALSE; + } + + if (getallegiance(caster) == AL_PEACEFUL) { + fizzle(caster); + return B_FALSE; + } + if (ispetof(target, caster)) { + if (isplayer(caster)) { + msg("%s is already allied with you!",targetname); + } + return B_FALSE; + } + + // no saving throw, just depends on hit dice. + // too powerful? + if (gethitdice(target) <= power) { + int howlong; + if (isplayer(caster) || cansee(player, target)) { + if (seenbyplayer) *seenbyplayer = B_TRUE; + } + + howlong = getspellduration(20,30,blessed) + (power*10); + + // + addtempflag(target->flags, F_CHARMEDBY, caster->id, NA, NA, NULL, howlong); + addtempflag(target->flags, F_PETOF, caster->id, NA, NA, NULL, howlong); + } else { + if (isplayer(caster) || cansee(player, target)) { + msg("%s resists.",targetname); + if (seenbyplayer) *seenbyplayer = B_TRUE; + } + // they get angry! + if (!isplayer(target) && cansee(target, caster)) { + fightback(target, caster); + } + } } else if (spellid == OT_S_COLDBURST) { int range = 1; int x,y; @@ -1237,7 +1455,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ int randomjobsok = B_TRUE; if (!targcell) { - if (power >= 5) { + if ((power >= 5) && isplayer(caster)) { // control location if (!validatespellcell(caster, &targcell, TT_NONE, B_TRUE, LOF_DONTNEED, spellid, power)) return B_TRUE; // make sure it's empty @@ -1257,7 +1475,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } // determine type of mosnter - if (power >= 7) { + if ((power >= 7) && isplayer(caster)) { // ask what kind of monster askstring("Create what kind of monster", '?', buf, BUFLEN, NULL); r = findracebyname(buf); @@ -1299,7 +1517,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } // add the monster - newlf = addmonster(targcell, r->id, randomjobsok, 1); + newlf = addmonster(targcell, r->id, randomjobsok, 1, B_FALSE); if (newlf) { // assign job if required if (forcejob) { @@ -1321,6 +1539,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (seenbyplayer) *seenbyplayer = B_TRUE; } // not worth any xp + killflagsofid(newlf->flags, F_XPVAL); addflag(newlf->flags, F_XPVAL, 0, NA, NA, NULL); rv = B_FALSE; } else { @@ -1330,6 +1549,18 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } return B_TRUE; } + } else if (spellid == OT_S_CUREPOISON) { + if (!validatespellcell(caster, &targcell,TT_ALLY, B_TRUE, LOF_DONTNEED, spellid, power)) return B_TRUE; + target = targcell->lf; + if (!target) { + fizzle(caster); + return B_FALSE; + } + killflagsofid(target->flags, F_POISONED); + + if (cansee(player, target)) { + if (seenbyplayer) *seenbyplayer = B_TRUE; + } } else if (spellid == OT_S_DARKNESS) { if (!targcell) targcell = caster->cell; // centre on the caster @@ -1462,6 +1693,51 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } else { // monsters can't use this } + } else if (spellid == OT_S_DETECTPOISON) { + if (isplayer(caster)) { + int npoisoned = 0; + int n; + for (n = 0; n < caster->nlos; n++) { + object_t *o; + for (o = caster->los[n]->obpile->first ; o ; o = o->next) { + flag_t *f; + int ispoisoned = B_FALSE, isdecayed = B_FALSE; + if (isrotting(o)) { + isdecayed = B_TRUE; + } else if (o->type->id == OT_POT_POISON) { + ispoisoned = B_TRUE; + } else { + for (f = o->flags->first ; f ; f = f->next) { + if (f->id == F_POISONED) { + ispoisoned = B_TRUE; + f->known = B_TRUE; + break; + } else if ((f->id == F_HITCONFER) && (f->val[0] == F_POISONED)) { + ispoisoned = B_TRUE; + f->known = B_TRUE; + break; + } + } + } + + + if (ispoisoned || isdecayed) { + char obname[BUFLEN]; + getobname(o, obname, o->amt); + msg("%s %s %s!", obname, (o->amt == 1) ? "is" : "are", + ispoisoned ? "poisoned" : "rotted"); + npoisoned++; + } + + if (o->type->id == OT_POT_POISON) { + makeknown(o->type->id); + } + } + } + if (!npoisoned) { + msg("You can't detect any poison nearby."); + } + } // end if isplayer } else if (spellid == OT_S_DETONATE) { // don't need line of fire! if (!validatespellcell(caster, &targcell, TT_MONSTER|TT_DOOR, B_TRUE, LOF_DONTNEED, spellid, power)) return B_TRUE; @@ -1876,7 +2152,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (haslos(caster, targcell)) { msg("%s burn%s!",lfname,isplayer(targcell->lf) ? "" : "s"); } - losehp(targcell->lf, rolldie(2,8)+3, DT_FIRE, caster, "a burst of fire"); + losehp(targcell->lf, rolldie(2,6), DT_FIRE, caster, "a burst of fire"); } } } @@ -1946,6 +2222,49 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } else { // monsters can't id things! } + } else if (spellid == OT_S_ENDUREELEMENTS) { + flag_t *f; + // always targetted at caster + if (!validatespellcell(caster, &targcell,TT_ALLY, B_TRUE, LOF_DONTNEED, spellid, power)) return B_TRUE; + target = targcell->lf; + if (!target) { + fizzle(caster); + return B_FALSE; + } + + f = addtempflag(caster->flags, F_DTRESIST, DT_FIRE, NA, NA, NULL, FROMSPELL); + f->obfrom = spellid; + f = addtempflag(caster->flags, F_DTRESIST, DT_COLD, NA, NA, NULL, FROMSPELL); + f->obfrom = spellid; + } else if (spellid == OT_S_ENTANGLE) { + char targname[BUFLEN]; + flag_t *f; + object_t *o; + + if (!validatespellcell(caster, &targcell,TT_MONSTER, B_TRUE, LOF_DONTNEED, spellid, power)) return B_TRUE; + + target = targcell->lf; + if (!target) { + fizzle(caster); + return B_TRUE; + } + getlfname(target, targname); + if (cansee(player, target)) { + msg("Magical vines grasp %s!",targname); + if (seenbyplayer) *seenbyplayer = B_TRUE; + } + + // create vine + o = addob(targcell->obpile, "entangling vine"); + // set power + f = hasflag(o->flags, F_RESTRICTMOVEMENT); + if (f) { + f->val[0] = 30 + (power/2); + } + /// remmeber creator. if they don't have los to us, spell + // is broken and vines will vanish. + setobcreatedby(o, caster); + } else if (spellid == OT_S_FLIGHT) { flag_t *f; // always targetted at caster @@ -2086,6 +2405,58 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ addtempflag(target->flags, F_POLYMORPHED, B_TRUE, NA, NA, NULL, 10); setrace(target, R_GASCLOUD, B_TRUE); } + } else if (spellid == OT_S_HAILSTORM) { + int failed = B_FALSE; + // ask for a target cell + if (!validatespellcell(caster, &targcell,TT_MONSTER, B_TRUE, LOF_DONTNEED, spellid, power)) return B_TRUE; + if (targcell) { + if (!targcell->type->solid) { + object_t *o; + int x,y; + int radius; + char *dambuf; + // centre storm here... + if (haslos(player, targcell)) { + msg("An intense storm of hail appears!"); + if (seenbyplayer) *seenbyplayer = B_TRUE; + } + + radius = power / 2; + if (radius < 1) radius = 1; + addobsinradius(targcell, radius, DT_ORTH, "hail storm", B_FALSE); + + // replace damage per sec with power d6 + asprintf(&dambuf, "%dd6", power); + for (y = targcell->y - radius; y <= targcell->y + radius; y++) { + for (x = targcell->x - radius; x <= targcell->x + radius; x++) { + cell_t *c; + c = getcellat(targcell->map, x, y); + if (c && (getcelldist(targcell, c) <= radius)) { + for (o = c->obpile->first ; o ; o = o->next) { + if (o->type->id == OT_HAILSTORM) { + flag_t *f; + f = hasflag(o->flags, F_WALKDAM); + if (f) { + free(f->text); + f->text = strdup(dambuf); + } + } + } + } + } // end forx + } // end fory + + free(dambuf); + } else { // end if targcell not solid + failed = B_TRUE; + } + } else { + failed = B_TRUE; + } + + if (failed) { + fizzle(caster); + } } else if (spellid == OT_S_HASTE) { int howlong = 15; if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE, LOF_DONTNEED, spellid, power)) return B_TRUE; @@ -2113,7 +2484,12 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } else if (spellid == OT_S_HEALING) { int donesomething = B_FALSE; - target = caster; + if (!validatespellcell(caster, &targcell,TT_ALLY, B_TRUE, LOF_DONTNEED, spellid, power)) return B_TRUE; + target = targcell->lf; + if (!target) { + fizzle(caster); + return B_FALSE; + } // cure certain bad effects if (killflagsofid(target->flags, F_PAIN)) { @@ -2158,7 +2534,12 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } else if (spellid == OT_S_HEALINGMIN) { int donesomething = B_FALSE; - target = caster; + if (!validatespellcell(caster, &targcell,TT_ALLY, B_TRUE, LOF_DONTNEED, spellid, power)) return B_TRUE; + target = targcell->lf; + if (!target) { + fizzle(caster); + return B_FALSE; + } // cure bad effects instead of healing if (killflagsofid(target->flags, F_PAIN)) { @@ -2947,13 +3328,13 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ addflag(srcportal->flags, F_OBHP, 6, 6, NA, NULL); addflag(srcportal->flags, F_OBHPDRAIN, 1, DT_DIRECT, NA, NULL); addflag(srcportal->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL); - addflag(srcportal->flags, F_DIETEXT, B_TRUE, NA, NA, "vanishes"); + addflag(srcportal->flags, F_OBDIETEXT, B_TRUE, NA, NA, "vanishes"); addflag(dstportal->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(dstportal->flags, F_OBHP, 6, 6, NA, NULL); addflag(dstportal->flags, F_OBHPDRAIN, 1, DT_DIRECT, NA, NULL); addflag(dstportal->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL); - addflag(dstportal->flags, F_DIETEXT, B_TRUE, NA, NA, "vanishes"); + addflag(dstportal->flags, F_OBDIETEXT, B_TRUE, NA, NA, "vanishes"); if (haslos(player, srccell)) { char obname[BUFLEN]; @@ -3178,6 +3559,44 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ f = addtempflag(caster->flags, F_DTIMMUNE, DT_FALL, NA, NA, NULL, FROMSPELL); f->obfrom = spellid; + } else if (spellid == OT_S_MENDING) { + object_t *o; + + if (targob) { + o = targob; + } else { + // ask for an object + o = askobject(caster->pack, "Mend which object", NULL, AO_DAMAGED); + } + if (!o) { + fizzle(caster); + return B_TRUE; + } + + if (isplayer(caster)) { + flag_t *f; + f = hasflag(o->flags, F_OBHP); + if (!f) { + nothinghappens(); + return B_TRUE; + } else { + char obname[BUFLEN]; + getobname(o, obname, o->amt); + + f->val[0] += (rnd(1,6) + power); + + if (f->val[0] >= f->val[1]) { + msg("Your %s is completely repaired!", noprefix(obname)); + f->val[0] = f->val[1]; + } else { + msg("Your %s is repaired a little!", noprefix(obname)); + } + + if (seenbyplayer) *seenbyplayer = B_TRUE; + } + } else { + // monsters can't repair things! + } } else if (spellid == OT_S_PACIFY) { char targetname[BUFLEN]; if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE, LOF_DONTNEED, spellid, power)) return B_TRUE; @@ -3347,6 +3766,142 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ fizzle(caster); return B_TRUE; } + } else if (spellid == OT_S_PURIFYFOOD) { + object_t *o; + + if (targob) { + o = targob; + } else { + // ask for an object + o = askobject(caster->pack, "Purify what?", NULL, AO_EDIBLE | AO_DRINKABLE); + } + if (!o) { + fizzle(caster); + return B_TRUE; + } + + if (isplayer(caster)) { + char obname[BUFLEN]; + flag_t *f; + + getobname(o, obname, o->amt); + + if (o->type->id == OT_POT_POISON) { + msg("Your %s sparkles for a while.", noprefix(obname)); + makeknown(o->type->id); // you now know that it was poison. + o->type = findot(OT_POT_WATER); + makeknown(o->type->id); // you now know what water is too. + } else { + f = hasflag(o->flags, F_OBHP); + if (!f) { + nothinghappens(); + return B_TRUE; + } else { + + f->val[0] = f->val[1]; + + if (isdrinkable(o)) { + msg("Your %s looks more clean now.", noprefix(obname)); + } else { + msg("Your %s looks more fresh now.", noprefix(obname)); + } + + if (seenbyplayer) *seenbyplayer = B_TRUE; + } + } + } else { + // monsters can't purify things! + } + } else if (spellid == OT_S_QUENCH) { + object_t *o,*nexto; + int ndone = 0; + + if (!validatespellcell(caster, &targcell,TT_OBJECT, B_TRUE, LOF_DONTNEED, spellid, power)) return B_TRUE; + + if (!targcell) { + fizzle(caster); + } + + if (targcell->lf) { + // all objects. + for (o = targcell->lf->pack->first ; o ; o = nexto) { + nexto = o->next; + if (o->type->material->id == MT_FIRE) { + if (haslos(player, targcell)) { + char obname[BUFLEN]; + getobname(o, obname, o->amt); + msg("%s vanishes!",obname); + if (seenbyplayer) *seenbyplayer = B_TRUE; + } + killob(o); + ndone++; + } else { + if (haslos(player, targcell)) { + if (seenbyplayer) *seenbyplayer = B_TRUE; + } + + killflagsofid(o->flags, F_ONFIRE); + ndone++; + } + } + } + + for (o = targcell->obpile->first ; o ; o = nexto) { + nexto = o->next; + if (o->type->material->id == MT_FIRE) { + if (haslos(player, targcell)) { + char obname[BUFLEN]; + getobname(o, obname, o->amt); + msg("%s vanishes!",obname); + if (seenbyplayer) *seenbyplayer = B_TRUE; + } + killob(o); + ndone++; + } else { + if (haslos(player, targcell)) { + if (seenbyplayer) *seenbyplayer = B_TRUE; + } + killflagsofid(o->flags, F_ONFIRE); + ndone++; + } + } + if (!ndone) { + fizzle(caster); + } + } else if (spellid == OT_S_LESSENPOISON) { + flag_t *f; + int ndone = 0; + if (!validatespellcell(caster, &targcell,TT_ALLY, B_TRUE, LOF_DONTNEED, spellid, power)) return B_TRUE; + target = targcell->lf; + if (!target) { + fizzle(caster); + return B_FALSE; + } + + for (f = target->flags->first ; f ; f = f->next) { + if (f->id == F_POISONED) { + // slightly lower time + if (f->lifetime > 1) { + f->lifetime--; + } + // cut power in half + f->val[1] /= 2; if (f->val[1] < 1) f->val[1] = 1; + if (isplayer(target)) { + msg("Your %s seems less intense.",getpoisonname(f->val[0])); + } + ndone++; + } + } + if (ndone) { + if (seenbyplayer) *seenbyplayer = B_TRUE; + } else { + fizzle(caster); + } + } else if (spellid == OT_S_REPELINSECTS) { + // just announce + if (isplayer(caster)) { + msg("A strange odour surrounds you..."); + } } else if (spellid == OT_S_REVEALHIDDEN) { int i; int seen = B_FALSE; @@ -3420,6 +3975,32 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (isplayer(target) || haslos(player, target->cell)) { if (seenbyplayer) *seenbyplayer = B_TRUE; } + } else if (spellid == OT_S_SLEETSTORM) { + int failed = B_FALSE; + // ask for a target cell + if (!validatespellcell(caster, &targcell,TT_MONSTER, B_TRUE, LOF_DONTNEED, spellid, power)) return B_TRUE; + if (targcell) { + if (!targcell->type->solid) { + int radius; + // centre storm here... + if (haslos(player, targcell)) { + msg("An raging storm of sleet appears!"); + if (seenbyplayer) *seenbyplayer = B_TRUE; + } + + radius = power / 2; + if (radius < 1) radius = 1; + addobsinradius(targcell, radius, DT_ORTH, "storm of sleet", B_FALSE); + } else { + failed = B_TRUE; + } + } else { + failed = B_TRUE; + } + + if (failed) { + fizzle(caster); + } } else if (spellid == OT_S_SLOW) { int howlong = 15; if (!validatespelllf(caster, &target)) return B_TRUE; @@ -3441,6 +4022,49 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (isplayer(target) || haslos(player, target->cell)) { if (seenbyplayer) *seenbyplayer = B_TRUE; } + } else if (spellid == OT_S_SOFTENEARTH) { + int seen = B_FALSE; + int ndone = 0; + int powerleft = power; + // ask for a target cell + if (!validatespellcell(caster, &targcell, TT_NONE, B_TRUE, LOF_DONTNEED, spellid, power)) return B_TRUE; + if (targcell) { + object_t *o; + enum OBTYPE badoid[2]; + int i; + cell_t *c; + // do first cell + // TODO: is it actually earth here, not stone,metal etc? + o = addob(targcell->obpile, "pool of mud"); + if (o) { + ndone++; + powerleft--; + if (haslos(player, targcell)) seen = B_TRUE; + // do the rest + badoid[0] = OT_MUDPOOL; + badoid[1] = OT_NONE; + for (i = 0; i < powerleft; i++) { + c = real_getrandomadjcell(targcell, WE_NOTWALL, B_ALLOWEXPAND, badoid); + if (c) { + o = addob(c->obpile, "pool of mud"); + if (o) { + ndone++; + if (haslos(player, targcell)) seen = B_TRUE; + // do the rest + } + } + } + } + } + + if (ndone) { + if (seen) { + if (seenbyplayer) *seenbyplayer = B_TRUE; + msg("The ground nearby softens into mud."); + } + } else { + fizzle(caster); + } } else if (spellid == OT_S_SPARK) { object_t *o,*nexto; int donesomething = B_FALSE; @@ -3461,6 +4085,106 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (targcell->lf) { losehp(targcell->lf, 0, DT_FIRE, caster, "a spark"); } + } else if (spellid == OT_S_STICKTOSNAKE) { + int i; + cell_t *poss[MAXCANDIDATES]; + int nposs; + cell_t *c = NULL,*newcell = NULL; + object_t *o,*nexto; + int ndone = 0; + + poss[0] = caster->cell; + nposs = 1; + for (i = 0; i < caster->nlos; i++) { + poss[nposs++] = caster->los[i]; + } + // for each cell we can see... + for (i = 0; i < caster->nlos; i++) { + c = poss[i]; + if (c->lf) { + if (cansee(caster, c->lf)) { + for (o = c->lf->pack->first ; o ; o = nexto) { + nexto = o->next; + if ((o->material->id == MT_WOOD) && + hasflag(o->flags, F_RODSHAPED) && + isequipped(o) && + !isblessed(o) ) { + char obname[BUFLEN]; + char lfname[BUFLEN]; + getobname(o, obname, o->amt); + getlfname(c->lf, lfname); + newcell = getrandomadjcell(c, WE_WALKABLE, B_NOEXPAND); + if (newcell) { + lifeform_t *snake; + // add a snake there. + if (rnd(1,2) == 1) { + snake = addlf(newcell, R_SNAKE, 1); + } else { + snake = addlf(newcell, R_SNAKECARPET, 1); + } + if (snake) { + msg("%s%s %s transforms into a snake!",lfname, + getpossessive(lfname), + noprefix(obname)); + killflagsofid(snake->flags, F_XPVAL); + addflag(snake->flags, F_XPVAL, 0, NA, NA, NULL); + makefriendly(snake, PERMENANT); + killob(o); + ndone++; + } + } else { + msg("%s%s %s quivers for a moment.",lfname, getpossessive(lfname), + noprefix(obname)); + ndone++; + } + } + } + } + } else { // ie. no lf there + for (o = c->obpile->first ; o ; o = nexto) { + nexto = o->next; + if ((o->material->id == MT_WOOD) && hasflag(o->flags, F_RODSHAPED) && !isblessed(o)) { + cell_t *newcell = NULL; + lifeform_t *snake; + char obname[BUFLEN]; + + getobname(o, obname, o->amt); + + // add to current cell or new one? + if (c->lf) { // ie. if a previous object made a snake here + newcell = getrandomadjcell(c, WE_WALKABLE, B_NOEXPAND); + } else { + newcell = c; + } + if (newcell) { + // add a snake there. + if (rnd(1,2) == 1) { + snake = addlf(newcell, R_SNAKE, 1); + } else { + snake = addlf(newcell, R_SNAKECARPET, 1); + } + if (snake) { + msg("%s transforms into a snake!",obname); + killob(o); + killflagsofid(snake->flags, F_XPVAL); + addflag(snake->flags, F_XPVAL, 0, NA, NA, NULL); + makefriendly(snake, PERMENANT); + ndone++; + } + } else { + msg("%s quivers for a moment.",obname); + ndone++; + } + } + } + } + } + + if (ndone) { + if (seenbyplayer) *seenbyplayer = B_TRUE; + } else { + fizzle(caster); + } } else if (spellid == OT_S_TELEPORT) { cell_t *c = NULL; lifeform_t *ally[8]; @@ -3760,6 +4484,61 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } } + } else if (spellid == OT_S_WARPWOOD) { + object_t *o,*nexto; + flag_t *f; + int ndone = 0; + + if (!validatespellcell(caster, &targcell,TT_OBJECT, B_TRUE, LOF_DONTNEED, spellid, power)) return B_TRUE; + + if (!targcell) { + fizzle(caster); + } + + if (targcell->lf) { + // weilded weapons/armour + for (o = targcell->lf->pack->first ; o ; o = nexto) { + nexto = o->next; + if (o->type->material->id == MT_WOOD) { + if (isequipped(o)) { + int dam; + f = hasflag(o->flags, F_OBHP); + if (f) { + dam = rnd(1,f->val[0]); + } else { + dam = roll("1d6"); + } + takedamage(o, dam, DT_DIRECT); + if (haslos(player, targcell)) { + if (seenbyplayer) *seenbyplayer = B_TRUE; + } + ndone++; + } + } + } + + } + + for (o = targcell->obpile->first ; o ; o = nexto) { + nexto = o->next; + if (o->type->material->id == MT_WOOD) { + int dam; + f = hasflag(o->flags, F_OBHP); + if (f) { + dam = rnd(1,f->val[0]); + } else { + dam = roll("1d6"); + } + takedamage(o, dam, DT_DIRECT); + if (haslos(player, targcell)) { + if (seenbyplayer) *seenbyplayer = B_TRUE; + } + ndone++; + } + } + if (!ndone) { + fizzle(caster); + } } else if (spellid == OT_S_WEAKEN) { // ask for target if (!validatespelllf(caster, &target)) return B_TRUE; @@ -3797,6 +4576,45 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } else { fizzle(caster); } + } else if (spellid == OT_S_WEB) { + char numbuf[BUFLEN]; + int i; + + numtotext(power, numbuf); + if (!validatespellcell(caster, &targcell,TT_MONSTER, B_TRUE, LOF_NEED, spellid, power)) return B_TRUE; + // animation + anim(caster->cell, targcell, '^', C_GREY); + if (isplayer(caster) || cansee(player, caster)) { + if (power == 1) { + msg("%s fire%s a burst of webbing.",castername,isplayer(caster) ? "" : "s"); + } else { + msg("%s fire%s %s bursts of webbing.",castername,isplayer(caster) ? "" : "s", numbuf); + } + if (seenbyplayer) *seenbyplayer = B_TRUE; + } + + // create webs + for (i = 0; i < power; i++) { + cell_t *c; + if (i == 0) { + c = targcell; + } else { + c = getrandomadjcell(targcell, WE_NOTWALL, B_ALLOWEXPAND); + } + if (c) { + addob(c->obpile, "web"); + if (c->lf) { + if (isplayer(c->lf)) { + msg("You are stuck in a web!"); + } else if (cansee(player, c->lf)) { + char lfname[BUFLEN]; + getlfname(c->lf, lfname); + msg("%s is stuck in a web!", lfname); + } + } + } + + } } else if (spellid == OT_S_WINDSHIELD) { flag_t *f; // always targetted at caster @@ -3894,8 +4712,8 @@ enum SKILL getschoolskill(enum SPELLSCHOOL ss) { return SK_SS_DEATH; case SS_DIVINATION: return SK_SS_DIVINATION; - case SS_EARTH: - return SK_SS_EARTH; + case SS_NATURE: + return SK_SS_NATURE; case SS_FIRE: return SK_SS_FIRE; case SS_ICE: @@ -3963,6 +4781,7 @@ int getspellduration(int min,int max,int blessed) { return howlong; } +// abilities count as level 0 int getspelllevel(enum OBTYPE spellid) { flag_t *f; objecttype_t *ot; @@ -4071,23 +4890,37 @@ int getspellpower(lifeform_t *lf, enum OBTYPE spellid) { statmod = 0; } - school = getspellschool(spellid); + + school = getspellschoolknown(lf, spellid); spellskill = getskill(lf, SK_SPELLCASTING); - // dont need spellcasting skill for mental/allomancy - switch (school) { - case SS_ALLOMANCY: - case SS_MENTAL: - break; - default: - if (spellskill == PR_INEPT) { - return 0; - } - break; + if (hasjob(lf, J_DRUID) && (school == SS_NATURE)) { + // druid doesn't use spellcasting skill for nature spells + // instead, they can only cast spells up to their + // player level. + if (getspelllevel(spellid) > lf->level) { + return 0; + } + } else { + // dont need spellcasting skill for mental/allomancy + switch (school) { + case SS_ALLOMANCY: + case SS_MENTAL: + break; + default: + if (spellskill == PR_INEPT) { + return 0; + } + break; + } } - // every 6 levels you get 1 more power - // ie. at level 30 you get +5 power - power = (lf->level/6) + statmod; + if (hasjob(lf, J_DRUID)) { + power = (lf->level/3) + statmod; + } else { + // every 6 levels you get 1 more power + // ie. at level 30 you get +5 power + power = (lf->level/6) + statmod; + } switch (school) { case SS_ALLOMANCY: @@ -4114,7 +4947,7 @@ int getspellpower(lifeform_t *lf, enum OBTYPE spellid) { } // specialised school skill - apply this AFTER dividing by spell level - schoolskill = getskill(lf, getschoolskill(getspellschool(spellid))); + schoolskill = getskill(lf, getschoolskill(school)); if (schoolskill != PR_INEPT) { power += ((float)schoolskill * 1.5); } @@ -4139,6 +4972,35 @@ enum SPELLSCHOOL getspellschool(enum OBTYPE spellid) { return SS_NONE; } +enum SPELLSCHOOL getspellschoolknown(lifeform_t *lf, enum OBTYPE spellid) { + flag_t *f; + enum SPELLSCHOOL thisschool; + objecttype_t *ot; + + ot = findot(spellid); + if (!ot) { + return SS_NONE; + } + + + // find a school which we know about! + for (f = ot->flags->first ; f ; f = f->next) { + if ((f->id == F_SPELLSCHOOL) && getskill(lf, getschoolskill(f->val[0]))) { + thisschool = f->val[0]; + break; + } + } + if (thisschool == SS_NONE) { + // just pick the first one. + f = hasflag(ot->flags, F_SPELLSCHOOL); + assert(f); + thisschool = f->val[0]; + } + + + return thisschool; +} + int getspellrange(enum OBTYPE spellid, int power) { objecttype_t *st; int range = UNLIMITED; @@ -4162,6 +5024,25 @@ int getspellrange(enum OBTYPE spellid, int power) { return range; } +char *getvarpowerspelldesc(enum OBTYPE spellid, int power, char *buf) { + // default + strcpy(buf, ""); + switch (spellid) { + case OT_S_BARKSKIN: + sprintf(buf, "+%d Armour Rating, Fire Vulnerability", power*2); + break; + case OT_S_PSYARMOUR: + sprintf(buf, "+%d Armour Rating", power*4); + break; + case OT_S_WINDSHIELD: + sprintf(buf, "Protection from missiles <= %d km/h",speedtokph(power)); + break; + default: + break; + } + return buf; +} + // magically propel an object into lf's hands. // if it's too big it'll hit them! void pullobto(object_t *o, lifeform_t *lf) { @@ -4301,7 +5182,9 @@ cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, i cell_t *newwhere = NULL; // validate it if (where && needlos && !haslos(caster, where) && (where != caster->cell)) { - msg("You cannot see there!"); more(); + if (isplayer(caster)) { + msg("You cannot see there!"); more(); + } where = NULL; } @@ -4317,6 +5200,8 @@ cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, i } else { where = NULL; } + } else { + where = newwhere; } } else { where = NULL; @@ -4324,7 +5209,9 @@ cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, i } if (where && (maxrange != UNLIMITED) && (getcelldist(caster->cell, where) > maxrange)) { // out of range - msg("Too far away - max range is %d.",maxrange); more(); + if (isplayer(caster)) { + msg("Too far away - max range is %d.",maxrange); more(); + } where = NULL; } diff --git a/spell.h b/spell.h index e40bffc..aba16f5 100644 --- a/spell.h +++ b/spell.h @@ -15,7 +15,9 @@ int getspellmaxpower(enum OBTYPE spellid); char *getspellname(enum OBTYPE spellid, lifeform_t *lf, char *buf); int getspellpower(lifeform_t *lf, enum OBTYPE spellid); enum SPELLSCHOOL getspellschool(enum OBTYPE spellid); +enum SPELLSCHOOL getspellschoolknown(lifeform_t *lf, enum OBTYPE spellid); int getspellrange(enum OBTYPE spellid, int power); +char *getvarpowerspelldesc(enum OBTYPE spellid, int power, char *buf); void pullobto(object_t *o, lifeform_t *lf); void stopspell(lifeform_t *caster, enum OBTYPE spellid); void stopallspells(lifeform_t *lf); diff --git a/text.c b/text.c index ada02bd..13303d7 100644 --- a/text.c +++ b/text.c @@ -4,6 +4,7 @@ #include #include "defs.h" #include "lf.h" +#include "nexus.h" #include "objects.h" #include "text.h" @@ -113,6 +114,38 @@ char *getattrname(enum ATTRIB att) { return "?badattrib?"; } +int gethitconferlifetime(char *text, int *min, int *max) { + int howlong; + int localmin,localmax; + if (text) { + char loctext[BUFLEN]; + char *word, *dummy; + strcpy(loctext,text); + word = strtok_r(loctext, "-", &dummy); + if (word) { + localmin = atoi(word); + word = strtok_r(NULL, "-", &dummy); + if (word) { + localmax = atoi(word); + howlong = rnd(localmin,localmax); + } else { + howlong = PERMENANT; + } + } else { + localmin = -1; + localmax = -1; + howlong = PERMENANT; + } + } else { + localmin = -1; + localmax = -1; + howlong = PERMENANT; + } + if (min) *min = localmin; + if (max) *max = localmax; + return howlong; +} + char *getpossessive(char *text) { char lastchar; // you -> your @@ -406,6 +439,10 @@ char *roman(int num) { return ""; } +int speedtokph(int speed) { + return speed * speed * speed; +} + void splittime(int *hours, int *mins, int *secs) { long left; left = curtime; diff --git a/text.h b/text.h index 7b79989..68cfd20 100644 --- a/text.h +++ b/text.h @@ -6,6 +6,7 @@ char *capitaliseall(char *text); char *dicetotext(int ndice, int nsides, int bonus, int *min, int *max, char *dicebuf, char *minmaxbuf); char *getattrabbrev(enum ATTRIB att); char *getattrname(enum ATTRIB att); +int gethitconferlifetime(char *text, int *min, int *max); char *getpossessive(char *text); char *getdrunktext(flag_t *drunkflag); char *getsizetext(enum LFSIZE sz); @@ -19,6 +20,7 @@ int needses(char *text); char *noprefix(char *obname); char *numtotext(int num, char *buf); char *roman(int num); +int speedtokph(int speed); void splittime(int *hours, int *mins, int *secs); char *strrep(char *text, char *oldtok, char *newtok, int *rv); char *dostrrep(char* in, char** out, char* oldtok, char* newtok, int *rv);