From c32f93294caa314dc2268c97b66285bac38b7e32 Mon Sep 17 00:00:00 2001 From: Rob Pearce Date: Mon, 11 Apr 2011 05:05:45 +0000 Subject: [PATCH] * [+] calcxp - [+] more low power rings - [+] don't think book names are being randomized - always 'azure' - [+] charm moidifications - [+] possession modifications - [+] troglodyte being made with 180180108180180 mp!! * [+] gain skills on level up for some jobs - [+] only magic/blessed weapons can hit noncorporeal things. - [+] monsters shouldn't walk into walls to attack things there. - [+] The skeleton slams you with a boulder.--More--Innate Attack: boulder . was a bug in HASATTACK - [+] no polymorphing into undead. - [+] missiles shoudl always miss noncorporeal things! - [+] need OFFMAP as well as WALLINWAY - [+] can't possess undead - [+] less charges in wands - [+] when a thrown potion misses, "xx is destroyed" rather than "xx shatters!" - [+] instead of "act:slow mv: slow", just "slow" - [+] sprinting: "you are exhausted" isn't triggering statdirty - [+] On status, use 'v.fast' 'ex.fast' usbtead if "Very" etc - [+] allies shouldn't attack peaceful things. - [+] make fleeing lfs use stairs - [+] undead can't start with blessed objects. - [+] undead can't touch blessed objects * [+] GHOST * [+] PET code - [+] can't trade items if your ally has NOPACK - [+] make sure shared xp is working * [+] firstaid skill shows extra mosnter hp info * [+] more low power wands - at the moment it's always light or pwoer - [+] pets: say 'your xxx' instead of 'the xxx' * [+] pets: dancing weapons should be pets - [+] need f_allyof as well so that allies will stay close. - [+] difference is that allies aren't called "your" - [+] AND no alignment penalty for attacking allies? - [+] in lfstats, move physical stuff BACK to first page!!! - [+] remove ally/pet flag when you die * [+] pirate job * [+] let firearms go into primary hand. test with PIRATE. - [+] when fighting with a non-weapon: "you whack the xxx with xxx" - [+] add specific attack verbs to weapons - [+] F_ATTACKVERB, dampct between v0 and v1, "stabs" - [+] make showlfarmour() use colours --- ai.c | 62 ++- attack.c | 141 +++++-- attack.h | 2 +- defs.h | 99 +++-- flag.c | 4 +- io.c | 347 +++++++++------- io.h | 2 + lf.c | 862 ++++++++++++++++++++++++++++++++++------ lf.h | 9 +- log.txt | 1137 ++++++++++++++++++++++++++++++----------------------- map.c | 11 + map.h | 1 + move.c | 27 +- nexus.c | 45 ++- objects.c | 350 +++++++++++------ objects.h | 3 + spell.c | 162 ++++++-- 17 files changed, 2273 insertions(+), 991 deletions(-) diff --git a/ai.c b/ai.c index 2f84912..581c8cc 100644 --- a/ai.c +++ b/ai.c @@ -67,6 +67,11 @@ void aiattack(lifeform_t *lf, lifeform_t *victim, int timelimit) { } } + // no longer a pet + f = lfhasflagval(lf, F_PETOF, victim->id, NA, NA, NULL); + if (f) killflag(f); + f = lfhasflagval(lf, F_ALLYOF, victim->id, NA, NA, NULL); + if (f) killflag(f); } enum OBTYPE aigetattackspell(lifeform_t *lf, lifeform_t *victim) { @@ -278,6 +283,7 @@ void aimove(lifeform_t *lf) { int icanattack = B_FALSE; object_t *curgun,*bestgun; flag_t *f; + flag_t *mf; //flag_t *nextf; // lifeform_t *fleefrom = NULL; lifeform_t *target; @@ -403,14 +409,11 @@ void aimove(lifeform_t *lf) { goingtomove = B_TRUE; - // drink boost potions if (!useitemwithflag(lf, F_AIBOOSTITEM)) { return; } - - if (goingtomove && (getcelldist(lf->cell, target->cell) == 1)) { } @@ -688,7 +691,8 @@ void aimove(lifeform_t *lf) { // cell exists and we can see it? if (c && c->lf && (c->lf != lf) && cansee(lf, c->lf)) { // player there? - if (!isplayer(c->lf)) { + //if (!isplayer(c->lf) && !ispeaceful(c->lf)) { + if (areenemies(lf, c->lf)) { if (db) dblog(".oO { found a target - lfid %d (%s) ! }",c->lf->id, c->lf->race->name); // target them! addtempflag(lf->flags, F_TARGET, c->lf->id, c->x, c->y, NULL, AI_FOLLOWTIME); @@ -719,7 +723,7 @@ void aimove(lifeform_t *lf) { } // need to train skills? - if (lf->skillpoints || lfhasflag(lf, F_STATGAINREADY)) { + if (lf->skillpoints || getattpoints(lf)) { if (canrest(lf)) { // special case - monsters don't need to actually rest to gain // skills, although they DO still need to wait until the player @@ -729,9 +733,51 @@ void aimove(lifeform_t *lf) { } // just try to move in a random direction - if (db) dblog(".oO { default - moving randomly }"); - dorandommove(lf, B_NOBADMOVES); - return; + mf = lfhasflagval(lf, F_PETOF, NA, NA, NA, NULL); + if (!mf) { + mf = lfhasflagval(lf, F_ALLYOF, NA, NA, NA, NULL); + } + if (mf && (getallegiance(lf) == AL_FRIENDLY)) { + lifeform_t *master; + master = findlf(lf->cell->map, mf->val[0]); + if (master && cansee(lf, master)) { + // can see my master - either move towards them or randomly + if (isadjacent(lf->cell, master->cell)) { + if (db) dblog(".oO { i can see my master - moving randomly }"); + dorandommove(lf, B_NOBADMOVES); + return; + } else { + // move towards master if not adjacent + if (db) dblog(".oO { i can see my master - moving towards them }"); + if (movetowards(lf, master->cell, DT_ORTH)) { + // failed + if (db) dblog(".oO { failed. moving randomly }"); + dorandommove(lf, B_NOBADMOVES); + return; + } else { + // success + if (db) dblog(".oO { success. }"); + } + return; + } + } else { + // try to move towards master's last known loc + if (mf->val[1] != NA) { + if (db) dblog(".oO { cannot see my master - adding F_TARGETCELL for last known loc }"); + addflag(lf->flags, F_TARGETCELL, mf->val[1], mf->val[2], NA, NULL); + } else { + if (db) dblog(".oO { cannot see my master and dont have a last known location. randommove. }"); + dorandommove(lf, B_NOBADMOVES); + return; + } + // exit the function without moving - next time we will do a move due to f_targetcell code. + return; + } + } else { + if (db) dblog(".oO { default - moving randomly }"); + dorandommove(lf, B_NOBADMOVES); + return; + } // if we get this far, just wait rest(lf, B_TRUE); diff --git a/attack.c b/attack.c index cda5e67..5c3a2d8 100644 --- a/attack.c +++ b/attack.c @@ -108,9 +108,11 @@ int attackcell(lifeform_t *lf, cell_t *c) { } attacktype = AT_NONE; void *attacktarget; int nweps = 0; + int innateattacks = 0; int i; int attacktime; int gotweapon = B_FALSE; + int maxattacks = ALL; // anyone there? if so just attack. if (c->lf) { @@ -176,6 +178,7 @@ int attackcell(lifeform_t *lf, cell_t *c) { validwep[nweps] = B_TRUE; damflag[nweps] = f; nweps++; + innateattacks++; } } } @@ -184,35 +187,58 @@ int attackcell(lifeform_t *lf, cell_t *c) { attacktime = getattackspeed(lf); taketime(lf, attacktime); + if (nweps <= 0) { + if (isplayer(lf)) { + msg("You cannot attack!"); + } + return B_TRUE; + } + + maxattacks = nweps; // ie. all + f = lfhasflag(lf, F_MAXATTACKS); + if (f) { + maxattacks = f->val[0]; + } else { + maxattacks = innateattacks; + } + + /* // if we have a weapon, this takes the place of one of our // attacks. // for monsters, pick which one to replace randomly. - // for players, never pick the weapon which one to replace randomly. - if (gotweapon && (nweps > 1)) { + // for players, never pick the weapon to replace randomly. + if (gotweapon && (nweps >= 2)) { if (isplayer(lf)) { validwep[rnd(1,nweps-1)] = B_FALSE; } else { validwep[rnd(0,nweps-1)] = B_FALSE; } } + */ // # valid attacks higher than our allowed attacks? - f = lfhasflag(lf, F_MAXATTACKS); - if (f) { - int max = f->val[0]; + if (nweps > maxattacks) { int nvalid; + int first; + + // player never invalidates their weapon + if (isplayer(lf) && gotweapon) { + first = 1; + } else { + first = 0; + } nvalid = 0; for (i = 0; i < nweps; i++) { if (validwep[i]) nvalid++; } - while (nvalid > max) { + while (nvalid > maxattacks) { int sel; // mark a random one as invalid - sel = rnd(0,nweps-1); + sel = rnd(first,nweps-1); while (!validwep[sel]) { - sel = rnd(0,nweps-1); + sel = rnd(first,nweps-1); } validwep[sel] = B_FALSE; @@ -227,7 +253,9 @@ int attackcell(lifeform_t *lf, cell_t *c) { for (i = 0; i < nweps; i++) { if (validwep[i]) { if (attacktype == AT_LF) { - attacklf(lf, (lifeform_t *)attacktarget, wep[i], damflag[i]); + if (!isdead((lifeform_t *)attacktarget)) { + attacklf(lf, (lifeform_t *)attacktarget, wep[i], damflag[i]); + } } else if (attacktype == AT_OB) { attackob(lf, (object_t *)attacktarget, wep[i], damflag[i]); } @@ -299,7 +327,6 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) // did you hit? ndam = 0; if (rolltohit(lf, victim, wep, &critical)) { - int n; hit = B_TRUE; if (aidb) dblog(".oO { i hit! }"); @@ -331,8 +358,9 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) // determine base damage // determine damage - dam[0] = 0; - for (n = 0; n < critical+1; n++) { + dam[0] = getdamroll(wep, victim, damflag); + if (critical) { + // critical hit means an extra damage roll. dam[0] += getdamroll(wep, victim, damflag); } if (aidb) dblog("rolled dam[%d] = %d",0,dam[0]); @@ -451,7 +479,17 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) // announce it if (isplayer(lf)) { char extradambuf[BUFLEN]; + char withwep[BUFLEN]; char *verb; + + strcpy(extradambuf, ""); + + if (wep && !ismeleeweapon(wep)) { + sprintf(withwep, " with %s", wepname); + } else { + strcpy(withwep, ""); + } + if (dam[i] == 0) { strcpy(extradambuf, " but do no damage"); } else if (lfhasflag(player, F_EXTRAINFO) || lfhasflag(player, F_OMNIPOTENT) ) { @@ -463,13 +501,13 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) if (backstab && (i == 0)) { verb = strdup("backstab"); } else if (fatal) { - verb = getkillverb(victim, damtype[i], dam[i], victim->maxhp); + verb = getkillverb(victim, wep, damtype[i], dam[i], victim->maxhp); } else { verb = getattackverb(lf, wep, damtype[i], dam[i], victim->maxhp); } - warn("You %s %s%s%s", + warn("You %s %s%s%s%s", verb, - victimname, extradambuf, + victimname, withwep,extradambuf, (fatal || backstab) ? "!" : "."); if (fatal && strstr(verb, "behead")) { @@ -843,9 +881,24 @@ char *getattackverb(lifeform_t *lf, object_t *wep, enum DAMTYPE damtype, int dam if (wep) { flag_t *f; - f = hasflag(wep->flags, F_ATTACKVERB); - if (f) { - return f->text; + for (f = wep->flags->first ; f ; f = f->next) { + if (f->id == F_ATTACKVERB) { + if ((f->val[0] == NA) && (f->val[1] == NA)) { + return f->text; + } else if (f->val[0]) { + if (pct >= f->val[0]) { + if (f->val[1] == NA) { + return f->text; + } else if (pct <= f->val[1]) { + return f->text; + } + } + } else if (f->val[1]) { + if (pct <= f->val[1]) { + return f->text; + } + } + } } } @@ -881,20 +934,6 @@ char *getattackverb(lifeform_t *lf, object_t *wep, enum DAMTYPE damtype, int dam return "savage"; } } - } else if (damtype == DT_CLAW) { - if (pct <= 5) { - return "scratch"; - } else if (pct <= 15) { - return "claw"; - } else if (pct <= 30) { - return "tear"; - } else if (pct <= 40) { - return "rake"; - } else if (pct <= 50) { - return "gouge"; - } else { - return "eviscerate"; - } } else if (damtype == DT_CHOP) { if (pct <= 5) { return "hit"; @@ -1071,7 +1110,7 @@ int getextradamwep(object_t *wep, int *dam, enum DAMTYPE *damtype, int *ndam) { return *dam; } -char *getkillverb(lifeform_t *victim, enum DAMTYPE damtype, int dam, int maxhp) { +char *getkillverb(lifeform_t *victim, object_t *wep, enum DAMTYPE damtype, int dam, int maxhp) { float pct; pct = (int)(((float) dam / (float) maxhp) * 100.0); @@ -1079,6 +1118,29 @@ char *getkillverb(lifeform_t *victim, enum DAMTYPE damtype, int dam, int maxhp) return "defeat"; } + if (wep) { + flag_t *f; + for (f = wep->flags->first ; f ; f = f->next) { + if (f->id == F_KILLVERB) { + if ((f->val[0] == NA) && (f->val[1] == NA)) { + return f->text; + } else if (f->val[0]) { + if (pct >= f->val[0]) { + if (f->val[1] == NA) { + return f->text; + } else if (pct <= f->val[1]) { + return f->text; + } + } + } else if (f->val[1]) { + if (pct <= f->val[1]) { + return f->text; + } + } + } + } + } + if ((damtype == DT_BASH) && lfhasflag(victim, F_FROZEN)) { return "shatter"; } @@ -1095,7 +1157,6 @@ char *getkillverb(lifeform_t *victim, enum DAMTYPE damtype, int dam, int maxhp) if (damtype == DT_PIERCE) return "impale"; if (damtype == DT_BASH) return "flatten"; if (damtype == DT_BITE) return "gore"; - if (damtype == DT_CLAW) return "disembowel"; if (damtype == DT_SLASH) { if (lfhasflagval(victim, F_NOBODYPART, BP_HEAD, NA, NA, NULL)) { return "bisect"; @@ -1341,7 +1402,6 @@ int isphysicaldam(enum DAMTYPE damtype) { case DT_BASH: case DT_BITE: case DT_CHOP: - case DT_CLAW: case DT_COLD: case DT_CRUSH: case DT_ELECTRIC: @@ -1375,6 +1435,17 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical) ev = getevasion(victim); acc -= ev; + // special case + if (lfhasflag(victim, F_NONCORPOREAL) && + !lfhasflag(lf, F_NONCORPOREAL) ) { + + // using a magical or blessed weapon? + if (wep && (ismagical(wep) || isblessed(wep)) ) { + } else { + return B_FALSE; // automatic miss + } + } + // size difference szlf = getlfsize(lf); szvictim = getlfsize(victim); diff --git a/attack.h b/attack.h index efa30ce..4d0dada 100644 --- a/attack.h +++ b/attack.h @@ -12,7 +12,7 @@ char *getattackverb(lifeform_t *lf, object_t *wep, enum DAMTYPE damtype, int dam enum DAMTYPE getdamtype(object_t *wep); int getextradamlf(lifeform_t *lf, int *dam, enum DAMTYPE *damtype, int *ndam); int getextradamwep(object_t *wep, int *dam, enum DAMTYPE *damtype, int *ndam); -char *getkillverb(lifeform_t *victim, enum DAMTYPE damtype, int dam, int maxhp); +char *getkillverb(lifeform_t *victim, object_t *wep, enum DAMTYPE damtype, int dam, int maxhp); void getdamrange(flag_t *f, int *min, int *max); //void getdamrangeunarmed(flag_t *f, int *min, int *max); float getdamreducepct(float armourrating); diff --git a/defs.h b/defs.h index 6c4760f..9a8ae8f 100644 --- a/defs.h +++ b/defs.h @@ -320,6 +320,7 @@ enum SPELLSCHOOL { SS_AIR, SS_DEATH, SS_DIVINATION, + SS_EARTH, SS_FIRE, SS_ICE, SS_GRAVITY, @@ -392,32 +393,31 @@ enum DAMTYPE { DT_SLASH = 1, DT_FIRE = 2, DT_COLD = 3, - DT_CLAW = 4, - DT_BASH = 5, - DT_BITE = 6, - DT_CHOP = 7, - DT_PROJECTILE = 8, - DT_HOLY = 9, - DT_WATER = 10, - DT_ACID = 11, - DT_MELT = 12, - DT_DIRECT = 13, // eg. from f_obhpdrain flag - DT_ELECTRIC = 14, - DT_EXPLOSIVE = 15, - DT_DECAY = 16, - DT_MAGIC = 17, - DT_TOUCH = 18, - DT_POISONGAS = 19, - DT_UNARMED = 20, - DT_LIGHT = 21, - DT_CRUSH = 22, - DT_FALL = 23, - DT_PETRIFY = 24, - DT_POISON = 25, - DT_NECROTIC = 26, - DT_NONE = 27, // for direclty dealt damage, not really any type + DT_BASH = 4, + DT_BITE = 5, + DT_CHOP = 6, + DT_PROJECTILE = 7, + DT_HOLY = 8, + DT_WATER = 9, + DT_ACID = 10, + DT_MELT = 11, + DT_DIRECT = 12, // eg. from f_obhpdrain flag + DT_ELECTRIC = 13, + DT_EXPLOSIVE = 14, + DT_DECAY = 15, + DT_MAGIC = 16, + DT_TOUCH = 17, + DT_POISONGAS = 18, + DT_UNARMED = 19, + DT_LIGHT = 20, + DT_CRUSH = 21, + DT_FALL = 22, + DT_PETRIFY = 23, + DT_POISON = 24, + DT_NECROTIC = 25, + DT_NONE = 26, // for direclty dealt damage, not really any type }; -#define MAXDAMTYPE 28 +#define MAXDAMTYPE 27 // Object Classes enum OBCLASS { @@ -511,6 +511,8 @@ enum RACE { R_ANT, R_ANTS, R_BAT, + R_HAWK, + R_HAWKYOUNG, R_HAWKBLOOD, R_HAWKFROST, R_NEWT, @@ -524,6 +526,7 @@ enum RACE { R_GIANTBLOWFLY, // undead R_GHAST, + R_GHOST, R_GHOUL, R_SKELETON, R_ZOMBIE, @@ -539,6 +542,7 @@ enum JOB { J_ALLOMANCER, J_BARBARIAN, J_COMMANDO, + J_PIRATE, J_PLUMBER, J_PRINCE, J_WIZARD, @@ -740,6 +744,9 @@ enum OBTYPE { // -- elemental - ice OT_SB_CONECOLD, OT_SB_FREEZEOB, + OT_SB_COLDBURST, + // -- elemental - earth + OT_SB_DIG, // -- gravity OT_SB_GRAVLOWER, OT_SB_GRAVBOOST, @@ -817,6 +824,8 @@ enum OBTYPE { OT_S_COLDBURST, OT_S_CONECOLD, OT_S_FREEZEOB, + // -- elemental - earth + OT_S_DIG, // -- gravity OT_S_GRAVLOWER, OT_S_GRAVBOOST, @@ -885,6 +894,7 @@ enum OBTYPE { // wands OT_WAND_COLD, OT_WAND_DETONATION, + OT_WAND_DIGGING, OT_WAND_DISPERSAL, OT_WAND_FIRE, OT_WAND_FIREBALL, @@ -989,6 +999,7 @@ enum OBTYPE { OT_GAUNTLETS, // armour - head OT_SUNHAT, + OT_PIRATEHAT, OT_CAP, OT_HELM, OT_GASMASK, @@ -997,6 +1008,7 @@ enum OBTYPE { OT_HELMFOOTBALL, // armour - eyes OT_SUNGLASSES, + OT_EYEPATCH, // armour - shields OT_BUCKLER, OT_SHIELD, @@ -1020,9 +1032,10 @@ enum OBTYPE { OT_RING_RESISTMAG, OT_RING_SIGHT, OT_RING_WOUNDING, - // animal weapons + // innate / animal weapons OT_CLAWS, OT_FISTS, + OT_HOOKHAND, // for pirate OT_STING, OT_TAIL, OT_TEETH, @@ -1063,6 +1076,7 @@ enum OBTYPE { OT_LONGSWORD, OT_ORNSWORD, OT_SCIMITAR, + OT_CUTLASS, // polearms OT_GLAIVE, OT_GUISARME, @@ -1244,7 +1258,8 @@ enum FLAG { F_LOCKED,// door is locked F_JAMMED, // is this door jammed? // stairs / teleporters / portals - F_CLIMBABLE, // this is a stiarcase, v0 = up/down + F_CLIMBABLE, // this is a stiarcase, v0 = up/down/in + // also use this for portals //F_STAIRDIR//, // val0 = direcion F_OPPOSITESTAIRS, // val0 = opposite kind of stairs F_MAPLINK, // val0 = map to link to. @@ -1270,6 +1285,13 @@ enum FLAG { F_SHODDY, // weps do less damage, armour protects less. // weapon flags F_ATTACKVERB, // text=verb for attacking. ie. "hit" "slash" "sting" etc + // if v0/v1 are set, only use this text if dam pct is + // between v0 and v1. + // should always be singular + F_KILLVERB, // text=verb for a fatal attacking. ie. "kill" "behead" + // if v0/v1 are set, only use this text if dam pct is + // between v0 and v1. + // should always be singular F_OBATTACKDELAY, // how long weapon takes to attack F_USESSKILL, // weapon needs skill sk_v0 F_CANHAVEOBMOD, // weapon can have obmod om_v0 applied @@ -1355,6 +1377,8 @@ enum FLAG { F_ACCURACYMOD, // modify your accuracy by val0 F_SHIELDPENALTY, // lower your accuracy by val0 due to a cumbersome // shield + F_LEVRACE, // at level v0, this race is promoted to race v1 + // must apply this to the BASE race. F_ATTRMOD, // modify attribute val0 by val1. ie. 0=A_STR,1=-3 F_ATTRSET, // forces attribute val0 to be val1. ie. 0=A_STR,1=18 F_SIZE, // val0 = lf size (enum LFSIZE) @@ -1373,6 +1397,8 @@ enum FLAG { F_STARTJOB, // val0 = %chance of starting with it, v1 = jobid F_STARTATT, // val0 = A_xxx, val0 = start bracket (ie. IQ_GENIUS) F_CORPSETYPE, // text field specifies what corpse obtype to leave + F_MYCORPSE, // text field contains obid of my corpse. + // (for ghosts) F_NOCORPSE, // monster's body crumbles to dust after death F_LFSUFFIX, // text = suffix. eg. "skeleton" F_VISRANGE, // how far you can see (in the light) @@ -1388,8 +1414,18 @@ enum FLAG { F_SWOOPRANGE, // v0 = how far a flying creature can swoop // MONSTER AI FLAGS F_XPVAL, // force xp val for killing this lf to v0 - // ...OR... monsters with this abil are worth + // ...OR if applied to an ability... + // monsters with this abil are worth // v0 more xp. + F_XPMULTIPLY, // multiply xp val for killing this lf by v0 + F_PETOF, // this lf is a pet of lfid v0 + // v1/2 = last known location of my owner. + F_ALLYOF, // this lf is a ally of lfid v0 + // v1/2 = last known location of my owner. + // difference between this an 'petof' will be that + // you don't get alignment penalties etc for your + // ally dying. + F_HOSTILE, // lf will attack the player if in sight F_FRIENDLY, // lf will attack all non-players if in sight F_WANTS, // lf will try to pick up object type val0. if @@ -1513,6 +1549,7 @@ enum FLAG { F_REGENERATES, // regenerate HP at val0 per turn F_RESISTMAG, // immunity to magic effects. v0=amt (1-20) F_MPREGEN, // regenerate MP at val0 per turn + F_RISEASGHOST, // become a ghost when you die. F_SEEINDARK, // nightvis range is val0 F_SEEINVIS, // can see invisible things F_SEEWITHOUTEYES, // doesn't need eyes to see @@ -1557,6 +1594,7 @@ enum FLAG { F_HUNGER, // val0 = hunger, higher = hungrier // for jobs + F_HASPET, // this job starts with a pet of race f->text F_IFPCT, // only add the NEXT job flag if rnd(1,100) <= v0. F_ELSE, F_IFPLAYER, @@ -1710,6 +1748,10 @@ enum ERROR { E_LOWIQ = 42, E_LOWSTR = 43, E_WONT = 44, + E_OFFMAP = 45, + // charm failure reasons + // LOWIQ = 42 + E_UNDEAD = 46, }; @@ -1949,6 +1991,7 @@ enum SKILL { SK_SS_AIR, SK_SS_DEATH, SK_SS_DIVINATION, + SK_SS_EARTH, SK_SS_FIRE, SK_SS_ICE, SK_SS_GRAVITY, diff --git a/flag.c b/flag.c index aa5c9df..0375d9c 100644 --- a/flag.c +++ b/flag.c @@ -430,7 +430,7 @@ void timeeffectsflag(flag_t *f, int howlong) { break; } } - } else if (f->lifetime == 5) { + } else if (f->lifetime == 3) { if (isplayer(f->pile->owner)) { switch (f->id) { case F_SPRINTING: @@ -514,6 +514,8 @@ void timeeffectsflag(flag_t *f, int howlong) { getlfname(who, lfname); msg("%s looks exhausted.",lfname); } + needredraw = B_TRUE; + statdirty = B_TRUE; } } } diff --git a/io.c b/io.c index 3cd4b66..35edec2 100644 --- a/io.c +++ b/io.c @@ -453,7 +453,13 @@ cell_t *askcoords(char *prompt, int targettype) { case AL_FRIENDLY: if (!isplayer(c->lf)) { if (strlen(extrainfo)) strcat(extrainfo, ", "); - strcat(extrainfo, "ally"); + if (lfhasflagval(c->lf, F_ALLYOF, player->id, NA, NA, NULL)) { + strcat(extrainfo, "ally"); + } else if (lfhasflagval(c->lf, F_PETOF, player->id, NA, NA, NULL)) { + strcat(extrainfo, "pet"); + } else { + strcat(extrainfo, "friendly"); + } } break; case AL_PEACEFUL: @@ -473,7 +479,7 @@ cell_t *askcoords(char *prompt, int targettype) { strcat(extrainfo, "asleep"); } // hp - if (isgenius(player)) { + if (isgenius(player) || (getseenlfconditioncutoff(player) == C_HEALTHY) ) { char buf2[BUFLEN]; // show actual hp sprintf(buf2, "hp %d/%d",c->lf->hp, c->lf->maxhp); @@ -490,7 +496,7 @@ cell_t *askcoords(char *prompt, int targettype) { } wep = getweapon(c->lf); - if (wep) { + if (wep && (c->lf->race->id != R_DANCINGWEAPON)) { object_t *secwep; char obname[BUFLEN]; char buf2[BUFLEN]; @@ -785,7 +791,7 @@ int announceflaggain(lifeform_t *lf, flag_t *f) { } strcat(buf, "."); */ - msg(buf, ot->name); + msg(buf, ot->name); more(); donesomething = B_TRUE; } } @@ -1002,6 +1008,12 @@ int announceflaggain(lifeform_t *lf, flag_t *f) { donesomething = B_TRUE; } break; + case F_RISEASGHOST: + if (isplayer(lf)) { // don't know if monsters get it + msg("You will rise as a ghost after death."); + donesomething = B_TRUE; + } + break; case F_SEEINVIS: if (isplayer(lf)) { // don't know if monsters get it msg("You vision seems enhanced."); @@ -1089,6 +1101,9 @@ int announceflagloss(lifeform_t *lf, flag_t *f) { lifeform_t *lf2; int donesomething = B_FALSE; + if (!lf->born) { + return B_FALSE; + } if (lf->race->id == R_DANCINGWEAPON) { return B_FALSE; } @@ -1390,6 +1405,12 @@ int announceflagloss(lifeform_t *lf, flag_t *f) { } break; */ + case F_RISEASGHOST: + if (isplayer(lf)) { // don't know if monsters get it + msg("You will no longer rise as a ghost after death."); + donesomething = B_TRUE; + } + break; case F_SEEINVIS: if (isplayer(lf)) { // don't know if monsters get it msg("You vision returns to normal."); @@ -1640,25 +1661,14 @@ void listobs(WINDOW *win, object_t **mylist, int *sellist, int *selcount, int fi sprintf(buf, "%c %c - %s", selchar, useobletters ? mylist[i]->letter : myletters[i], obname); - if (mylist[i]->blessknown) { - if (iscursed(mylist[i])) { - setcol(win, C_RED); - } else if (isblessed(mylist[i])) { - setcol(win, C_CYAN); - } - } + setobcolour(win, mylist[i]); + getobextrainfo(mylist[i], infobuf); getobequipinfo(mylist[i], equipbuf); mvwprintw(win, *y, 0, "%s%s", buf, infobuf); - if (mylist[i]->blessknown) { - if (iscursed(mylist[i])) { - unsetcol(win, C_RED); - } else if (isblessed(mylist[i])) { - unsetcol(win, C_CYAN); - } - } + unsetobcolour(win, mylist[i]); if (strlen(equipbuf)) { setcol(win, C_BROWN); @@ -2643,6 +2653,9 @@ void describeob(object_t *o) { mvwprintw(mainwin, y, 0, "%s grants you %s immunity to magic.", buf, (f->val[0] >= 10) ? "strong" : "minor"); y++; break; + case F_RISEASGHOST: + mvwprintw(mainwin, y, 0, "%s cause you to rise as a ghost after death.", buf); y++; + break; case F_SEEINVIS: mvwprintw(mainwin, y, 0, "%s allows you to see invisible things.", buf); y++; break; @@ -2899,7 +2912,7 @@ void docomms(void) { if (!isadjacent(lf->cell, player->cell)) { addchoice(&prompt, 'c', "Come here", NULL, NULL); } - if (isadjacent(lf->cell, player->cell)) { + if (isadjacent(lf->cell, player->cell) && !lfhasflag(lf, F_NOPACK)) { addchoice(&prompt, 't', "Trade items with me", NULL, NULL); } } else { @@ -5498,9 +5511,12 @@ void drawstatus(void) { wprintw(statwin, " Immobile"); unsetcol(statwin, C_RED); } else { - // show player action speed - getspeedname(getactspeed(player), buf2); - if (strcmp(buf2, "normal")) { + char actbuf[BUFLEN],movebuf[BUFLEN]; + getspeednameshort(getactspeed(player), actbuf); + getspeednameshort(getmovespeed(player), movebuf); + // both action and movement speed the same, and not "normal" ? + if (!strcmp(actbuf, movebuf) && strcmp(actbuf, "normal")) { + // show combiner action/movement speed enum COLOUR col; if (getactspeed(player) < SP_NORMAL) { col = C_GREEN; @@ -5508,25 +5524,39 @@ void drawstatus(void) { col = C_RED; } setcol(statwin, col); - wprintw(statwin, " Act:"); - capitaliseall(buf2); - wprintw(statwin, "%s", buf2); + capitaliseall(actbuf); + wprintw(statwin, " %s", actbuf); unsetcol(statwin, col); - } - // show player movement speed - getspeedname(getmovespeed(player), buf2); - if (strcmp(buf2, "normal")) { - enum COLOUR col; - if (getmovespeed(player) < SP_NORMAL) { - col = C_GREEN; - } else { - col = C_RED; + } else { + // show action/movement speed seperately + // show player action speed + if (strcmp(actbuf, "normal")) { + enum COLOUR col; + if (getactspeed(player) < SP_NORMAL) { + col = C_GREEN; + } else { + col = C_RED; + } + setcol(statwin, col); + wprintw(statwin, " Act:"); + capitaliseall(actbuf); + wprintw(statwin, "%s", actbuf); + unsetcol(statwin, col); + } + // show player movement speed + if (strcmp(movebuf, "normal")) { + enum COLOUR col; + if (getmovespeed(player) < SP_NORMAL) { + col = C_GREEN; + } else { + col = C_RED; + } + setcol(statwin, col); + wprintw(statwin, " Mv:"); + capitaliseall(movebuf); + wprintw(statwin, "%s", movebuf); + unsetcol(statwin, col); } - setcol(statwin, col); - wprintw(statwin, " Mv:"); - capitaliseall(buf2); - wprintw(statwin, "%s", buf2); - unsetcol(statwin, col); } } @@ -5778,6 +5808,7 @@ void setcol(WINDOW *win, enum COLOUR col) { } wattron(win, COLOR_PAIR(col)); } + void unsetcol(WINDOW *win, enum COLOUR col) { wattroff(win, COLOR_PAIR(col)); if (needsbold(col)) { @@ -5785,6 +5816,28 @@ void unsetcol(WINDOW *win, enum COLOUR col) { } } +void setobcolour(WINDOW *win, object_t *o) { + if (!o) return; + if (o->blessknown) { + if (iscursed(o)) { + setcol(win, C_RED); + } else if (isblessed(o)) { + setcol(win, C_CYAN); + } + } +} + +void unsetobcolour(WINDOW *win, object_t *o) { + if (!o) return; + if (o->blessknown) { + if (iscursed(o)) { + unsetcol(win, C_RED); + } else if (isblessed(o)) { + unsetcol(win, C_CYAN); + } + } +} + void showlfarmour(lifeform_t *lf) { enum BODYPART bp; object_t *o; @@ -5799,18 +5852,29 @@ void showlfarmour(lifeform_t *lf) { } y = 2; + for (bp = BP_WEAPON; bp < MAXBODYPARTS; bp++) { - sprintf(buf, "%15s:%3s",getbodypartname(bp), " "); - o = hasobwithflagval(lf->pack, F_EQUIPPED, bp, NA, NA, NULL); - if (o) { - char obname[BUFLEN]; - getobname(o, obname, o->amt); - strcat(buf, obname); - } else { - strcat(buf, "-"); + char rhs[BUFLEN]; + // default + sprintf(rhs, "-"); + + if (!lfhasflagval(lf, F_NOBODYPART, bp, NA, NA, NULL)) { + sprintf(buf, "%15s:%3s",getbodypartname(bp), " "); + o = hasobwithflagval(lf->pack, F_EQUIPPED, bp, NA, NA, NULL); + if (o) { + char obname[BUFLEN]; + getobname(o, obname, o->amt); + strcpy(rhs, obname); + } else { + strcpy(rhs, "-"); + } + + mvwprintw(mainwin, y, 0, "%s", buf); + setobcolour(mainwin, o); + wprintw(mainwin, "%s", rhs); + unsetobcolour(mainwin, o); + y++; } - mvwprintw(mainwin, y, 0, "%s", buf); - y++; } y = getmaxy(mainwin); centre(mainwin, y-1, "[Press any key]"); @@ -5939,7 +6003,7 @@ void showlfstats(lifeform_t *lf, int showall) { - if (showall) { + if (showall || (getseenlfconditioncutoff(player) == C_HEALTHY)) { mvwprintw(mainwin, y, 0, ftext, "Hit Points"); wprintw(mainwin, "%d / %d", lf->hp , lf->maxhp); y++; } else { @@ -6256,7 +6320,7 @@ void showlfstats(lifeform_t *lf, int showall) { capitalise(buf); mvwprintw(mainwin, y2, x2, ftext, "Hunger"); - wprintw(mainwin, "%-14s", buf); y++; + wprintw(mainwin, "%-14s", buf); y2++; /* if (showall) { wprintw(mainwin, "%-14s (%d)", buf, f->val[0]); y++; @@ -6266,13 +6330,89 @@ void showlfstats(lifeform_t *lf, int showall) { */ } } - y++; // skip line - // back to first column + y++; + + // obvious physical effects here. + f = lfhasknownflag(lf, F_ASLEEP); + if (f) { + mvwprintw(mainwin, y, 0, "%s %s sleeping.", you(lf), isplayer(lf) ? "are" : "is"); + y++; + } + f = lfhasknownflag(lf, F_FLYING); + if (f && (f->known)) { + mvwprintw(mainwin, y, 0, "%s %s flying.", you(lf), isplayer(lf) ? "are" : "is"); + y++; + } + f = lfhasflag(lf, F_FROZEN); + if (f && (f->known)) { + mvwprintw(mainwin, y, 0, "%s %s been turned to ice, and %s slowly melting.", you(lf), isplayer(lf) ? "have" : "has", + isplayer(lf) ? "are" : "is"); + y++; + } + f = lfhasknownflag(lf, F_GRABBEDBY); + if (f && (f->known)) { + lifeform_t *lf2; + char grabbername[BUFLEN]; + lf2 = findlf(NULL, f->val[0]); + if (lf2) { + getlfname(lf2, grabbername); + } else { + strcpy(grabbername, "something"); + } + sprintf(buf,"%s %s being held by %s.",you(lf), isplayer(lf) ? "are" : "is", grabbername); + mvwprintw(mainwin, y, 0, buf); + y++; + } + f = lfhasknownflag(lf, F_GRABBING); + if (f && (f->known)) { + lifeform_t *lf2; + char grabeename[BUFLEN]; + lf2 = findlf(NULL, f->val[0]); + if (lf2) { + getlfname(lf2, grabeename); + } else { + strcpy(grabeename, "something"); + } + sprintf(buf,"%s %s holding on to %s.",you(lf), isplayer(lf) ? "are" : "is", grabeename); + mvwprintw(mainwin, y, 0, buf); + y++; + } + f = lfhasknownflag(lf, F_INVISIBLE); + if (f && (f->known)) { + mvwprintw(mainwin, y, 0, "%s %s invisible.", you(lf), isplayer(lf) ? "are" : "is"); + y++; + } + f = lfhasknownflag(lf, F_LEVITATING); + if (f && (f->known)) { + mvwprintw(mainwin, y, 0, "%s %s levitating.", you(lf), isplayer(lf) ? "are" : "is"); + y++; + } + f = lfhasflag(lf, F_NONCORPOREAL); + if (f && (f->known)) { + mvwprintw(mainwin, y, 0, "%s %s noncorporeal and can walk through walls.", you(lf), isplayer(lf) ? "are" : "is"); + y++; + } + f = lfhasflag(lf, F_PRODUCESLIGHT); + if (f && (f->known)) { + mvwprintw(mainwin, y, 0, "%s produce%s light.", you(lf), isplayer(lf) ? "" : "s"); + y++; + } + f = lfhasknownflag(lf, F_SPRINTING); + if (f) { + if (f->val[0]) { + mvwprintw(mainwin, y, 0, "%s %s sprinting.", you(lf), isplayer(lf) ? "are" : "is"); + y++; + } else { + mvwprintw(mainwin, y, 0, "%s %s exhausted.", you(lf), isplayer(lf) ? "are" : "is"); + y++; + } + } + + - f = lfhasknownflag(lf, F_UNDEAD); if (f) { mvwprintw(mainwin, y, 0, "%s %s undead.", you(lf), isplayer(lf) ? "are" : "is"); @@ -6298,7 +6438,7 @@ void showlfstats(lifeform_t *lf, int showall) { } nmissingbp = 0; - for (bp = BP_RIGHTHAND; bp < MAXBODYPARTS; bp++) { + for (bp = BP_WEAPON; bp < MAXBODYPARTS; bp++) { if (lfhasflagval(lf, F_NOBODYPART, bp, NA, NA, NULL)) { if (bp == BP_RIGHTHAND) { if (!lfhasflagval(lf, F_NOBODYPART, BP_HANDS, NA, NA, NULL)) { @@ -6306,6 +6446,13 @@ void showlfstats(lifeform_t *lf, int showall) { nmissingbp++; } } else if (bp == BP_LEFTHAND) { + if (!lfhasflagval(lf, F_NOBODYPART, BP_HANDS, NA, NA, NULL) && + !lfhasflagval(lf, F_NOBODYPART, BP_SECWEAPON, NA, NA, NULL) + ) { + missingbp[nmissingbp] = bp; + nmissingbp++; + } + } else if (bp == BP_SECWEAPON) { if (!lfhasflagval(lf, F_NOBODYPART, BP_HANDS, NA, NA, NULL)) { missingbp[nmissingbp] = bp; nmissingbp++; @@ -6318,7 +6465,7 @@ void showlfstats(lifeform_t *lf, int showall) { } if (nmissingbp) { - sprintf(buf, "%s have no %s",you(lf),getbodypartname(missingbp[0])); + sprintf(buf, "%s %s no %s",you(lf), isplayer(lf) ? "have" : "has", getbodypartname(missingbp[0])); if (nmissingbp > 1) { // construct list of missing body parts for (i = 1; i < nmissingbp ; i++) { @@ -6336,11 +6483,6 @@ void showlfstats(lifeform_t *lf, int showall) { y++; } - if (eyesshaded(lf)) { - mvwprintw(mainwin, y, 0, "%s eyes are shaded.", your(lf), buf); - y++; - } - // fleeing? if (showall) { for (f = lf->flags->first ; f ; f = f->next) { @@ -6614,86 +6756,16 @@ void showlfstats(lifeform_t *lf, int showall) { } // obvious physical effects first. - f = lfhasknownflag(lf, F_ASLEEP); - if (f) { - mvwprintw(mainwin, y, 0, "%s %s sleeping.", you(lf), isplayer(lf) ? "are" : "is"); - y++; - } f = lfhasknownflag(lf, F_BEINGSTONED); if (f) { mvwprintw(mainwin, y, 0, "%s %s being turning to stone.", you(lf), isplayer(lf) ? "are" : "is"); y++; } - f = lfhasknownflag(lf, F_FLYING); - if (f && (f->known)) { - mvwprintw(mainwin, y, 0, "%s %s flying.", you(lf), isplayer(lf) ? "are" : "is"); + if (eyesshaded(lf)) { + mvwprintw(mainwin, y, 0, "%s eyes are shaded.", your(lf), buf); y++; } - f = lfhasflag(lf, F_FROZEN); - if (f && (f->known)) { - mvwprintw(mainwin, y, 0, "%s %s been turned to ice, and %s slowly melting.", you(lf), isplayer(lf) ? "have" : "has", - isplayer(lf) ? "are" : "is"); - y++; - } - f = lfhasknownflag(lf, F_GRABBEDBY); - if (f && (f->known)) { - lifeform_t *lf2; - char grabbername[BUFLEN]; - lf2 = findlf(NULL, f->val[0]); - if (lf2) { - getlfname(lf2, grabbername); - } else { - strcpy(grabbername, "something"); - } - sprintf(buf,"%s %s being held by %s.",you(lf), isplayer(lf) ? "are" : "is", grabbername); - mvwprintw(mainwin, y, 0, buf); - y++; - } - f = lfhasknownflag(lf, F_GRABBING); - if (f && (f->known)) { - lifeform_t *lf2; - char grabeename[BUFLEN]; - lf2 = findlf(NULL, f->val[0]); - if (lf2) { - getlfname(lf2, grabeename); - } else { - strcpy(grabeename, "something"); - } - sprintf(buf,"%s %s holding on to %s.",you(lf), isplayer(lf) ? "are" : "is", grabeename); - mvwprintw(mainwin, y, 0, buf); - y++; - } - f = lfhasknownflag(lf, F_INVISIBLE); - if (f && (f->known)) { - mvwprintw(mainwin, y, 0, "%s %s invisible.", you(lf), isplayer(lf) ? "are" : "is"); - y++; - } - f = lfhasknownflag(lf, F_LEVITATING); - if (f && (f->known)) { - mvwprintw(mainwin, y, 0, "%s %s levitating.", you(lf), isplayer(lf) ? "are" : "is"); - y++; - } - f = lfhasflag(lf, F_NONCORPOREAL); - if (f && (f->known)) { - mvwprintw(mainwin, y, 0, "%s %s noncorporeal and can walk through walls.", you(lf), isplayer(lf) ? "are" : "is"); - y++; - } - f = lfhasflag(lf, F_PRODUCESLIGHT); - if (f && (f->known)) { - mvwprintw(mainwin, y, 0, "%s produce%s light.", you(lf), isplayer(lf) ? "" : "s"); - y++; - } - f = lfhasknownflag(lf, F_SPRINTING); - if (f) { - if (f->val[0]) { - mvwprintw(mainwin, y, 0, "%s %s sprinting.", you(lf), isplayer(lf) ? "are" : "is"); - y++; - } else { - mvwprintw(mainwin, y, 0, "%s %s exhausted.", you(lf), isplayer(lf) ? "are" : "is"); - y++; - } - } @@ -6992,6 +7064,12 @@ void showlfstats(lifeform_t *lf, int showall) { y++; } + f = lfhasflag(lf, F_RISEASGHOST); + if (f && (f->known)) { + mvwprintw(mainwin, y, 0, "%s will rise as a ghost after death.", you(lf)); + y++; + } + f = lfhasflag(lf, F_STABILITY); if (f && (f->known)) { @@ -7127,6 +7205,3 @@ void tombstone(lifeform_t *lf) { endwin(); } - - - diff --git a/io.h b/io.h index 9a1a912..6f01a23 100644 --- a/io.h +++ b/io.h @@ -93,6 +93,8 @@ void redraw(void); int savequit(void); void setcol(WINDOW *win, enum COLOUR col); void unsetcol(WINDOW *win, enum COLOUR col); +void setobcolour(WINDOW *win, object_t *o); +void unsetobcolour(WINDOW *win, object_t *o); void showlfarmour(lifeform_t *lf); void showlfstats(lifeform_t *lf, int showall); void tombstone(lifeform_t *lf); diff --git a/lf.c b/lf.c index 24ddf7c..c45608b 100644 --- a/lf.c +++ b/lf.c @@ -46,6 +46,11 @@ extern int loading; extern enum ERROR reason; +// for xplist +race_t **raceposs; +int *xpposs; +int xplistlen; + job_t *addjob(enum JOB id, char *name) { job_t *a; @@ -149,12 +154,18 @@ lifeform_t *real_addlf(cell_t *cell, enum RACE rid, int level, int controller) { a->x = -1; a->y = -1; + // defaults + a->hp = 1; + a->maxhp = a->hp; + a->mp = 0; + a->maxmp = a->mp; + // init flags a->flags = addflagpile(a, NULL); // set race - this will inherit race flags a->race = NULL; - setrace(a, rid); + setrace(a, rid, B_FALSE); // update other things cell->lf = a; @@ -595,6 +606,7 @@ void bleed(lifeform_t *lf) { // figure out how much xp a race is worth int calcxp(lifeform_t *lf) { + float multiplier = 1; float xpval = 0; float offense = 0; float defence = 0; @@ -603,17 +615,27 @@ int calcxp(lifeform_t *lf) { obpile_t *op; flag_t *f; float avgdam = 0; - int db = B_TRUE; + int db = B_FALSE; int maxhdroll; float xpconstant = 1; + if (lfhasflag(lf, F_DEBUG)) { + db = B_TRUE; + } + if (db) dblog("calcxp: calculating xpval for %s",lf->race->name); + f = lfhasflag(lf, F_XPVAL); + if (f) { + multiplier = f->val[0]; + } + + f = lfhasflag(lf, F_XPVAL); if (f) { if (db) dblog("calcxp: got F_XPVAL, forcing result to %d\n",f->val[0]); - return f->val[0]; + return f->val[0] * multiplier; } // attack @@ -705,10 +727,22 @@ int calcxp(lifeform_t *lf) { maxhdroll = 4; } - defence = maxhdroll * lf->level; + defence += (maxhdroll * lf->level); //defence /= 2; // -- evasion ? + f = hasflag(lf->race->flags, F_EVASION); + if (f && (f->val[0] > 0)) { + defence += (f->val[0]); + } + + // -- armour + f = hasflag(lf->race->flags, F_ARMOURRATING); + if (f && (f->val[0] > 0)) { + defence += pctof(150, f->val[0]); + } + + if (db) dblog("calcxp: DEFENCE IS %0.1f",defence); @@ -792,13 +826,19 @@ int calcxp(lifeform_t *lf) { } } - // -- avg damage in 10 turns + // -- avg damage in 10 turns if (db) dblog("calcxp: avg damage dealt (with abilities) is %0.1f",avgdam); avgdam *= 10; offense = avgdam; if (db) dblog("calcxp: ATTACKVAL IS %0.1f",offense); + + // extra 'spells' + if (hasflag(lf->race->flags, F_INDUCEFEAR)) { + spells += 10; + } + // TOTAL: xpval = offense + defence + spells; @@ -811,6 +851,10 @@ int calcxp(lifeform_t *lf) { + if (multiplier > 1) { + xpval *= multiplier; + if (db) dblog("calcxp: mulitplier takes val to %0.1f",xpval); + } if (db) dblog("calcxp: xpval: %0.1f --> %0.1f",xpval, xpval * xpconstant); xpval *= xpconstant; @@ -824,11 +868,15 @@ int calcxp(lifeform_t *lf) { int calcxprace(enum RACE rid) { cell_t c; int xpval; + map_t m; lifeform_t *lf; + // set up fake map + m.lf = NULL; + m.lastlf = NULL; // make a fake cell setcelltype(&c, CT_CORRIDOR); c.lf = NULL; - c.map = firstmap; + c.map = &m; // make a fake lf lf = addlf(&c, rid, 1); xpval = calcxp(lf); @@ -956,10 +1004,11 @@ int canhear(lifeform_t *lf, cell_t *dest) { // can't hear noises from other maps if (lf->cell->map != dest->map) return B_FALSE; + // for player only: // can't hear if you have a hostile mosnter next to you // and you're not blind. // (you're too engrossed in the battle) - if (!isblind(lf)) { + if (isplayer(lf) && !isblind(lf)) { int dir; int inbattle = B_FALSE; for (dir = DC_N; dir <= DC_NW; dir++) { @@ -1083,6 +1132,21 @@ int canpickup(lifeform_t *lf, object_t *o, int amt) { return B_TRUE; } +// - can't turn into monsters which aren't randomly generated. +// - can't turn into unique monsters +// - can't turn into undead monsters +int canpolymorphto(enum RACE rid) { + race_t *r; + r = findrace(rid); + if (!r) return B_FALSE; + + if (!appearsrandomly(rid)) return B_FALSE; + + if (hasflag(r->flags, F_UNDEAD)) return B_FALSE; + + return B_TRUE; +} + int canpush(lifeform_t *lf, object_t *o, int dir) { cell_t *obcell, *dstcell; reason = E_OK; @@ -1241,11 +1305,32 @@ int canwear(lifeform_t *lf, object_t *o, enum BODYPART where) { int canweild(lifeform_t *lf, object_t *o) { object_t *oo; flag_t *f; + enum BODYPART weildloc,otherloc; - if (!hasbp(lf, BP_WEAPON) || !lfhasflag(lf, F_HUMANOID)) { - reason = E_NOHANDS; + weildloc = getweildloc(o, &otherloc, NULL); + + // special case... + if (lf->race->id == R_DANCINGWEAPON) { + return B_TRUE; + } + + if (!lfhasflag(lf, F_HUMANOID)) { + reason = E_IMPOSSIBLE; return B_FALSE; } + if (!hasbp(lf, weildloc)) { + if (isfirearm(o) && !getequippedob(lf->pack, otherloc)) { + int temp; + // firearm can go in other hand. + // swap locations. + temp = weildloc; + weildloc = otherloc; + otherloc = temp; + } else { + reason = E_NOHANDS; + return B_FALSE; + } + } if (o) { for (f = o->flags->first ; f; f = f->next) { @@ -1291,7 +1376,8 @@ int canweild(lifeform_t *lf, object_t *o) { return B_FALSE; } } else if (f->id == F_TWOHANDED) { - if (lfhasflagval(lf, F_NOBODYPART, BP_SECWEAPON, NA, NA, NULL)) { + // need both hands free... + if (lfhasflagval(lf, F_NOBODYPART, otherloc, NA, NA, NULL)) { reason = E_NOHANDS; return B_FALSE; } @@ -1444,6 +1530,44 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar return rv; } +/* +void checkxp(enum RACE rid) { + int i,xp; + race_t *r; + + r = findrace(rid); + if (!r) { + dblog("checkxp(): can't find race for rid %d",rid); + return; + } + xp = calcxprace(rid); + + + if (xp < xpposs[0]) { + dblog("** Recommended rarity for %s: 100 (before %s/%d)", + r->name, + raceposs[0]->name, getracerarity(raceposs[0]->id)); + } else if (xp > xpposs[xplistlen-1]) { + dblog("** Recommended rarity for %s: above %d (after %s/%d)", + r->name, getracerarity(raceposs[xplistlen-1]->id), + raceposs[xplistlen-1]->name, getracerarity(raceposs[xplistlen-1]->id)); + } else { + for (i = 0; i < xplistlen-1; i++) { + if ((raceposs[i]->d != r->id) && (raceposs[i+1] != r->id)) + if ((xp >= xpposs[i]) && (xp <= xpposs[i+1])) { + dblog("** Recommended rarity for %s: %d (between %s/%d and %s/%d)", + r->name, (int)((float)xpposs[i] + (float)xpposs[i+1])/2, + raceposs[i]->name, getracerarity(raceposs[i]->id), + raceposs[i+1]->name, getracerarity(raceposs[i+1]->id) + ); + break; + } + } + } + } +} +*/ + int countmoney(lifeform_t *lf) { object_t *o; int amt = 0; @@ -1455,12 +1579,34 @@ int countmoney(lifeform_t *lf) { return amt; } +// toggle debugging +void debug(lifeform_t *lf) { + char lfname[BUFLEN]; + flag_t *f; + getlfname(lf, lfname); + + f = hasflag(lf->flags, F_DEBUG); + if (f) { + killflag(f); + msg("%s - debugging is DISABLED.", lfname); + } else { + addflag(lf->flags, F_DEBUG, B_TRUE, NA, NA, NULL); + msg("%s - debugging is ON.", lfname); + } +} + void die(lifeform_t *lf) { char buf[BUFLEN]; flag_t *f; cell_t *where; //int dropobs = B_TRUE; int vaporised = B_FALSE; + int willbecomeghost = B_FALSE; + object_t *corpse = NULL; + + if (lfhasflag(lf, F_RISEASGHOST)) { + willbecomeghost = B_TRUE; + } if (useringofmiracles(lf, 3)) { int hunger; @@ -1477,14 +1623,16 @@ void die(lifeform_t *lf) { } - if (isplayer(lf) && hasjob(lf, J_GOD)) { - char ch; - msg("You die..."); more(); - ch = askchar("Die", "yn", "n", B_TRUE); - if (ch == 'n') { - lf->hp = lf->maxhp; - msg("Not dying."); - return; + if (!willbecomeghost) { + if (isplayer(lf) && hasjob(lf, J_GOD)) { + char ch; + msg("You die..."); more(); + ch = askchar("Die", "yn", "n", B_TRUE); + if (ch == 'n') { + lf->hp = lf->maxhp; + msg("Not dying."); + return; + } } } @@ -1498,7 +1646,10 @@ void die(lifeform_t *lf) { } - lf->alive = B_FALSE; + if (!willbecomeghost) { + lf->alive = B_FALSE; + } + if (isplayer(lf)) { // force screen redraw so you see your hp = 0 drawscreen(); @@ -1538,16 +1689,35 @@ void die(lifeform_t *lf) { // award xp (but not if another monster killed it) if (hasflag(lf->flags, F_KILLEDBYPLAYER)) { - int xpval; + int xpval,xpeach,i,nposs; + lifeform_t *poss[MAXCANDIDATES], *l; + int n; + xpval = calcxp(lf); + + // find all allies on the map + nposs = 0; + n = 0; + for (l = lf->cell->map->lf ; l ; l = l->next) { + if (l != lf) { + if (getallegiance(l) == AL_FRIENDLY) { + poss[nposs] = l; + nposs++; + } + } + } //assert(xpval > 0); - gainxp(player, xpval); + xpeach = xpval / nposs; + + for (i = 0; i < nposs; i++) { + gainxp(poss[i], xpeach); + } } } // drop/kill all objects - if (!isplayer(lf)) { + if (willbecomeghost || !isplayer(lf)) { while (lf->pack->first) { if (vaporised) { killob(lf->pack->first); @@ -1594,7 +1764,6 @@ void die(lifeform_t *lf) { } else { char corpseprefix[BUFLEN]; char corpsename[BUFLEN]; - object_t *corpse; strcpy(corpseprefix, ""); switch (lf->lastdamtype) { @@ -1651,11 +1820,34 @@ void die(lifeform_t *lf) { } } - where = lf->cell; - if (lf->controller != C_PLAYER) { - // kill lifeform - killlf(lf); - assert(where->lf == NULL); + + if (willbecomeghost) { + flag_t *f, *nextf; + // remove all job flags + lf->born = B_FALSE; + for (f = lf->flags->first ; f ; f = nextf) { + nextf = f->next; + if (f->lifetime == FROMJOB) { + killflag(f); + } + } + killflagsofid(lf->flags, F_JOB); + lf->born = B_TRUE; + // turn into a ghost + setrace(lf, R_GHOST, B_TRUE); + lf->hp = lf->maxhp; + if (corpse) { + char cid[BUFLEN]; + sprintf(cid, "%ld",corpse->id); + addflag(lf->flags, F_MYCORPSE, NA, NA, NA, cid); + } + } else { + where = lf->cell; + if (lf->controller != C_PLAYER) { + // kill lifeform + killlf(lf); + assert(where->lf == NULL); + } } } @@ -1677,14 +1869,11 @@ void dumplf(void) { dblog("END LIFEFORM DUMP (%d found)",count); } -void dumpxp(void) { +void genxplist(void) { race_t *r; - race_t **raceposs; - int *xpposs; race_t *racetemp; int xptemp; int count = 0; - int nposs; int i; int donesomething; @@ -1698,18 +1887,18 @@ void dumpxp(void) { xpposs = malloc(count * sizeof(int)); // get xpval for all races - nposs = 0; + xplistlen = 0; for (r = firstrace ; r; r = r->next) { - raceposs[nposs] = r; - xpposs[nposs] = calcxprace(r->id); - nposs++; + raceposs[xplistlen] = r; + xpposs[xplistlen] = calcxprace(r->id); + xplistlen++; } // bubblesort donesomething = B_TRUE; while (donesomething) { donesomething = B_FALSE; - for (i = 0; i < (nposs-1); i++) { + for (i = 0; i < (xplistlen-1); i++) { if (xpposs[i] > xpposs[i+1]) { // swap with next xptemp = xpposs[i]; @@ -1723,10 +1912,14 @@ void dumpxp(void) { } } } +} + +void dumpxp(void) { + int i; // dump dblog("%-10s%-30s%s","XP", "Race", "Rarity"); - for (i = 0; i < nposs; i++) { + for (i = 0; i < xplistlen; i++) { dblog("%-10d%-30s%d",xpposs[i], raceposs[i]->name,getracerarity(raceposs[i]->id)); } @@ -2181,8 +2374,8 @@ int fall(lifeform_t *lf, int announce) { return B_FALSE; } +// make 'lf' respond to damage void fightback(lifeform_t *lf, lifeform_t *attacker) { - // respond to damage if (attacker && !isdead(lf)) { // wake up killflagsofid(lf->flags, F_ASLEEP); @@ -2205,6 +2398,22 @@ void fightback(lifeform_t *lf, lifeform_t *attacker) { } } } + // special cases (which will only happen if not retreating) + } + // special cases (which will happen whether retreating or not) + if (lf->race->id == R_DARKMANTLE) { + cell_t *poss[MAXCANDIDATES]; + int i, nposs = 0; + // darkjump + for (i = 0; i < lf->nlos; i++) { + if (cellwalkable(lf, lf->los[i], NULL) && isdark(lf->los[i])) { + poss[nposs] = lf->los[i]; + nposs++; + } + } + if (nposs) { + teleportto(lf, poss[rnd(0,nposs-1)], B_FALSE); // no smoke + } } } } @@ -2332,11 +2541,12 @@ int flee(lifeform_t *lf) { } } + // found someone who we are fleeing from? if (fleefrom) { - + object_t *stairs; + // ways of fleeing other than movement? if (!isplayer(lf)) { enum OBTYPE spell; - // if AI, try to use specific spells like teleport self spell = aigetfleespell(lf); if (spell != OT_NONE) { @@ -2353,15 +2563,23 @@ int flee(lifeform_t *lf) { } } + // announce + if (isplayer(lf)) { + char buf[BUFLEN]; + drawscreen(); + getlfname(fleefrom, buf); + msg("You flee from %s!",buf); + } + + // can we flee via stairs? + stairs = hasobwithflag(lf->cell->obpile, F_CLIMBABLE); + if (stairs) { + if (!usestairs(lf, stairs)) { + return B_TRUE; + } + } // move away from them if (!moveawayfrom(lf, fleefrom->cell, DT_ORTH)) { - // announce - if (isplayer(lf)) { - char buf[BUFLEN]; - drawscreen(); - getlfname(fleefrom, buf); - msg("You flee from %s!",buf); - } return B_TRUE; } } @@ -2466,8 +2684,9 @@ void gainhp(lifeform_t *lf, int amt) { } void gainlevel(lifeform_t *lf) { - char buf[BUFLEN]; float hpratio,mpratio; + flag_t *f; + race_t *mybaserace; if (isplayer(lf)) { statdirty = B_TRUE; @@ -2480,8 +2699,8 @@ void gainlevel(lifeform_t *lf) { msg("Welcome to level %d!",lf->level); more(); } else if (cansee(player, lf)) { - getlfname(lf, buf); - msg("%s looks more confident!",buf); + //getlfname(lf, buf); + //msg("%s looks more confident!",buf); } // update hp @@ -2496,29 +2715,47 @@ void gainlevel(lifeform_t *lf) { lf->mp = mpratio * (float)lf->maxmp; } - // stat gain + // stat gain (str etc) every 3 levels if ((lf->level % 3) == 0) { flag_t *f; f = lfhasflag(lf, F_STATGAINREADY); if (f) { f->val[2]++; - msg("You feel more ready for a training session."); + if (isplayer(lf)) { + msg("You feel more ready for a training session."); + } } else { f = addflag(lf->flags, F_STATGAINREADY, NA, NA, 1, NULL); - msg("You feel ready for a training session."); + if (isplayer(lf)) { + msg("You feel ready for a training session."); + } + } + } + + // skill gain + // new skill at level 3, 5, 7, etc + if (((lf->level - 1) % 2) == 0) { + lf->skillpoints++; + if (isplayer(lf)) { + msg("You feel ready to learn something new."); } } - // new skill at level 3, 5, 7, etc - if (isplayer(lf) && (((lf->level - 1) % 2) == 0)) { - lf->skillpoints++; - msg("You feel ready to learn something new."); - } // you can now re-attempt identification of objects killflagsofid(lf->flags, F_FAILEDINSPECT); - // TODO: hand out effects based on job + // monster races can be promoted... + if (lf->race->baseid) { + mybaserace = findrace(lf->race->baseid); + } else { + mybaserace = lf->race; + } + f = hasflagval(mybaserace->flags, F_LEVRACE, lf->level, NA, NA, NULL); + if (f && (lf->race->id != f->val[1])) { + // promotion! + setrace(lf, f->val[1], B_FALSE); + } } @@ -2605,6 +2842,8 @@ int getactspeed(lifeform_t *lf) { speed += 10; break; } + + if (speed < 1) speed = 1; return speed; } @@ -2980,6 +3219,11 @@ object_t *getfirearm(lifeform_t *lf) { if (o && hasflag(o->flags, F_FIREARM)) { return o; } + o = getequippedob(lf->pack, BP_WEAPON); + if (o && hasflag(o->flags, F_FIREARM)) { + return o; + } + return NULL; } @@ -3196,14 +3440,28 @@ char *getlfconditionname(enum LFCONDITION cond) { return "?unknown condition?"; } -char *getseenlfconditionname(lifeform_t *lf, lifeform_t *viewer) { +// return the healthiest possible hurt condition that 'lf' will +// recognise when looking at someone else. +// +// this is based on intelligence and firstaid skill +enum LFCONDITION getseenlfconditioncutoff(lifeform_t *lf) { enum IQBRACKET iqb; - enum LFCONDITION cond,cutoff; + enum SKILLLEVEL slev; + enum LFCONDITION cutoff; + + // intelligence higher than 'average' doesn't count. + iqb = getiqname(getattr(lf, A_IQ), NULL); + if (iqb > IQ_AVERAGE) iqb = IQ_AVERAGE; + + // adjust for firstaid skill + slev = getskill(lf, SK_FIRSTAID); + iqb += slev; - iqb = getiqname(getattr(viewer, A_IQ), NULL); // figure out health cutoff - condition > cutoff gets no description - if (iqb >= IQ_AVERAGE) { - cutoff = C_HURT; // ie. no cutoff + if (iqb >= IQ_GENIUS) { + cutoff = C_HEALTHY; // + } else if (iqb >= IQ_AVERAGE) { + cutoff = C_HURT; // ie. no real cutoff } else if (iqb >= IQ_DOPEY) { cutoff = C_WOUNDED; } else if (iqb >= IQ_ANIMAL) { @@ -3211,6 +3469,14 @@ char *getseenlfconditionname(lifeform_t *lf, lifeform_t *viewer) { } else { cutoff = C_DEAD; } + return cutoff; +} + +char *getseenlfconditionname(lifeform_t *lf, lifeform_t *viewer) { + enum LFCONDITION cond,cutoff; + + cutoff = getseenlfconditioncutoff(viewer); + cond = getlfcondition(lf); if (cond > cutoff) { return ""; @@ -3418,6 +3684,9 @@ int getmovespeed(lifeform_t *lf) { break; } + + if (speed < 1) speed = 1; + return speed; } @@ -3428,6 +3697,9 @@ char *getmoveverb(lifeform_t *lf) { return "float"; } + if (lfhasflag(lf, F_FLEEFROM)) { + return "flee"; + } return "walk"; } @@ -3438,6 +3710,9 @@ char *getmoveverbother(lifeform_t *lf) { return "floats"; } + if (lfhasflag(lf, F_FLEEFROM)) { + return "flees"; + } return "walks"; } @@ -3466,9 +3741,17 @@ char *getlfname(lifeform_t *lf, char *buf) { char *real_getlfname(lifeform_t *lf, char *buf, int usevis) { char descstring[BUFLEN]; char jobstring[BUFLEN]; + char the[5]; job_t *j; flag_t *f; + // 'the' or 'your' ? + if (lfhasflagval(lf, F_PETOF, player->id, NA, NA, NULL)) { + strcpy(the, "your"); + } else { + strcpy(the, "the"); + } + // construct description string strcpy(descstring, ""); if (lfhasflag(lf, F_FROZEN)) { @@ -3499,9 +3782,9 @@ char *real_getlfname(lifeform_t *lf, char *buf, int usevis) { if (wep) { char obname[BUFLEN]; real_getobname(wep, obname, 1, B_TRUE, B_FALSE, B_FALSE, B_FALSE); - sprintf(buf, "the %s%s",descstring,noprefix(obname)); + sprintf(buf, "%s %s%s",the,descstring,noprefix(obname)); } else { - sprintf(buf, "the %s%s%s",descstring,lf->race->name,jobstring); + sprintf(buf, "%s %s%s%s",the,descstring,lf->race->name,jobstring); } } else { char zombiestring[BUFLEN]; @@ -3512,7 +3795,7 @@ char *real_getlfname(lifeform_t *lf, char *buf, int usevis) { sprintf(zombiestring, " %s", f->text); } - sprintf(buf, "the %s%s%s%s",descstring,lf->race->name,jobstring,zombiestring); + sprintf(buf, "%s %s%s%s%s",the,descstring,lf->race->name,jobstring,zombiestring); } } } @@ -3528,10 +3811,22 @@ char *real_getlfnamea(lifeform_t *lf, char *buf, int usevis) { sprintf(buf, "you"); } else { char buf2[BUFLEN]; + char the[5]; + real_getlfname(lf, buf2, usevis); - sprintf(buf, "%s %s", - isvowel(lf->race->name[0]) ? "an" : "a", - noprefix(buf2)); + + + if (lfhasflagval(lf, F_PETOF, player->id, NA, NA, NULL)) { + strcpy(the, "your"); + } else { + if (isvowel(lf->race->name[0])) { + strcpy(the, "an"); + } else { + strcpy(the, "a"); + } + } + + sprintf(buf, "%s %s", the, noprefix(buf2)); } return buf; } @@ -3827,6 +4122,29 @@ char *getspeedname(int speed, char *buf) { } return buf; } +char *getspeednameshort(int speed, char *buf) { + sprintf(buf, "unknownspeed"); + if (speed <= SP_GODLIKE) { + sprintf(buf, "fast+++"); + } else if (speed <= SP_ULTRAFAST) { + sprintf(buf, "fast++"); + } else if (speed <= SP_VERYFAST) { + sprintf(buf, "fast+"); + } else if (speed <= SP_FAST) { + sprintf(buf, "fast"); + } else if (speed <= SP_NORMAL) { + sprintf(buf, "normal"); + } else if (speed <= SP_SLOW) { + sprintf(buf, "slow"); + } else if (speed <= SP_VERYSLOW) { + sprintf(buf, "slow+"); + } else if (speed <= SP_ULTRASLOW) { + sprintf(buf, "slow++"); + } else { + sprintf(buf, "slow+++"); + } + return buf; +} // ie. intelligence level: xxx enum IQBRACKET getiqname(int iq, char *buf) { @@ -4055,7 +4373,7 @@ object_t *getweapon(lifeform_t *lf) { long getxpforlev(int level) { long needxp = 0; // 2.8 - float multiplier = 9.5; + float multiplier = 10; float constant = 3.2; // no xp needed for level 1 @@ -4478,7 +4796,15 @@ void givestartobs(lifeform_t *lf, flagpile_t *fp) { o = addob(lf->pack, buf); } } + + + // added an object? if (o) { + // undead can't have cursed objecst + if (lfhasflag(lf, F_UNDEAD)) { + if (o->blessed == B_BLESSED) setblessed(o, B_CURSED); + } + // player knows the objects they start with if (isplayer(lf)) { identify(o); } @@ -5222,6 +5548,39 @@ void initjobs(void) { 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_POLEARMS, NA, NA, NULL); + + addjob(J_PIRATE, "Pirate"); + // stats + addflag(lastjob->flags, F_STARTATT, A_DEX, DX_DEXTROUS, NA, NULL); + addflag(lastjob->flags, F_STARTATT, A_CON, CN_HEALTHY, NA, NULL); + // abilities + addflag(lastjob->flags, F_STABILITY, B_TRUE, NA, NA, NULL); + addflag(lastjob->flags, F_NOBODYPART, BP_LEFTHAND, NA, NA, NULL); + addflag(lastjob->flags, F_NOBODYPART, BP_SECWEAPON, NA, NA, NULL); + addflag(lastjob->flags, F_EXTRALUCK, B_TRUE, NA, NA, NULL); + addflag(lastjob->flags, F_HASPET, NA, NA, NA, "young hawk"); + addflag(lastjob->flags, F_MAXATTACKS, 2, NA, NA, NULL);// this is so that our hookhand works + addflag(lastjob->flags, F_VISRANGEMOD, -4, NA, NA, NULL); + // also: has a hook instead of fists. + // startobjects + addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "silk shirt"); + addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "cloth trousers"); + addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "eyepatch"); + addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "tricorne"); + addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "300-350 gold coins"); + addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "cutlass"); + // skills + addflag(lastjob->flags, F_STARTSKILL, SK_LONGBLADES, PR_NOVICE, NA, NULL); + addflag(lastjob->flags, F_STARTSKILL, SK_UNARMED, PR_NOVICE, NA, NULL); + addflag(lastjob->flags, F_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_POLEARMS, NA, NA, NULL); + // TODO: in-built "hook" weapon ? but have to replace 'fists' somehow. + // maybe hardcode after character creation. + addjob(J_WIZARD, "Wizard"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "knife"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "robe"); @@ -5349,11 +5708,11 @@ void initrace(void) { addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 65, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL); - addflag(lastrace->flags, F_HITDICE, 17, NA, NA, NULL); + addflag(lastrace->flags, F_HITDICE, 4, 5, NA, NULL); addflag(lastrace->flags, F_EVASION, 0, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); - addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d10"); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "2d4+1"); addflag(lastrace->flags, F_STARTATT, A_STR, ST_STRONG, NA, NULL); addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "heavy flail"); addflag(lastrace->flags, F_STARTOBCLASS, 50, OC_ARMOUR, NA, NULL); @@ -5393,7 +5752,7 @@ void initrace(void) { addflag(lastrace->flags, F_STARTATT, A_DEX, DX_SUPERSONIC, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_CON, CN_HARDY, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); - addflag(lastrace->flags, F_RARITY, H_DUNGEON, 78, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, 65, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL); addflag(lastrace->flags, F_HITDICE, 9, NA, NA, NULL); addflag(lastrace->flags, F_ARMOURRATING, 10, NA, NA, NULL); @@ -5404,7 +5763,7 @@ void initrace(void) { addflag(lastrace->flags, F_ACTIONSPEED, SP_VERYSLOW, NA, NA, ""); addflag(lastrace->flags, F_CANWILL, OT_S_DARKNESS, 7, 7, "pw:3;"); addflag(lastrace->flags, F_CANWILL, OT_A_GRAB, NA, NA, NULL); - addflag(lastrace->flags, F_CANWILL, OT_A_CRUSH, NA, NA, NULL); + addflag(lastrace->flags, F_CANWILL, OT_A_CRUSH, NA, NA, "dam:0d0+5;"); addflag(lastrace->flags, F_SPELLCASTTEXT, NA, NA, NA, "waves its tentacles"); addflag(lastrace->flags, F_HASATTACK, OT_TENTACLE, NA, NA, "2d6"); addflag(lastrace->flags, F_NOBODYPART, BP_WEAPON, NA, NA, NULL); @@ -5422,7 +5781,7 @@ void initrace(void) { addrace(R_EYEBAT, "eyebat", 5, 'e', C_BLUE, MT_FLESH); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_SMART, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); - addflag(lastrace->flags, F_RARITY, H_DUNGEON, 65, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL); addflag(lastrace->flags, F_HITDICE, 1, 3, NA, NULL); addflag(lastrace->flags, F_EVASION, 20, NA, NA, NULL); @@ -5665,7 +6024,7 @@ void initrace(void) { addflag(lastrace->flags, F_SEEINDARK, 3, NA, NA, NULL); //addflag(lastrace->flags, F_STARTJOB, 25, J_WIZARD, NA, NULL); addflag(lastrace->flags, F_DODGES, B_TRUE, NA, NA, NULL); - addflag(lastrace->flags, F_PACKATTACK, 2, DT_CLAW, 3, "goblin"); + addflag(lastrace->flags, F_PACKATTACK, 2, DT_SLASH, 3, "goblin"); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); @@ -5690,7 +6049,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, NA, NA, "shouts^a shout"); addflag(lastrace->flags, F_SEEINDARK, 3, NA, NA, NULL); addflag(lastrace->flags, F_DODGES, B_TRUE, NA, NA, NULL); - addflag(lastrace->flags, F_PACKATTACK, 2, DT_CLAW, 3, "goblin"); + addflag(lastrace->flags, F_PACKATTACK, 2, DT_SLASH, 3, "goblin"); addflag(lastrace->flags, F_MINIONS, 90, 1, 2, "goblin"); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); @@ -5716,7 +6075,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, NA, NA, "shouts^a shout"); addflag(lastrace->flags, F_SEEINDARK, 5, NA, NA, NULL); addflag(lastrace->flags, F_DODGES, B_TRUE, NA, NA, NULL); - addflag(lastrace->flags, F_PACKATTACK, 2, DT_CLAW, 3, "goblin"); + addflag(lastrace->flags, F_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_HUMANOID, B_TRUE, NA, NA, NULL); @@ -5741,7 +6100,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, NA, NA, "shouts^a shout"); addflag(lastrace->flags, F_SEEINDARK, 5, NA, NA, NULL); addflag(lastrace->flags, F_DODGES, B_TRUE, NA, NA, NULL); - addflag(lastrace->flags, F_PACKATTACK, 2, DT_CLAW, 3, "goblin"); + addflag(lastrace->flags, F_PACKATTACK, 2, DT_SLASH, 3, "goblin"); addflag(lastrace->flags, F_MPDICE, 0, 10, NA, NULL); addflag(lastrace->flags, F_MPREGEN, 3, NA, NA, NULL); addflag(lastrace->flags, F_CANCAST, OT_S_BLINDNESS, NA, NA, NULL); @@ -6085,7 +6444,7 @@ void initrace(void) { 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); - addflag(lastrace->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL); addflag(lastrace->flags, F_HITDICE, 2, NA, NA, NULL); addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL); @@ -6107,6 +6466,13 @@ void initrace(void) { addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HASSKILL, SK_SS_MENTAL, PR_EXPERT, NA, NULL); addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); + addflag(lastrace->flags, F_XPMULTIPLY, 2, NA, NA, NULL); + addflag(lastrace->flags, F_UNDEAD, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_DTIMMUNE, DT_COLD, NA, NA, NULL); + addflag(lastrace->flags, F_DTIMMUNE, DT_POISONGAS, NA, NA, NULL); + addflag(lastrace->flags, F_DTIMMUNE, DT_DECAY, NA, NA, NULL); + 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); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -6281,7 +6647,57 @@ void initrace(void) { addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL); 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 + lastrace->baseid = R_HAWK; + addflag(lastrace->flags, F_RARITY, H_DUNGEON, 70, NA, ""); + addflag(lastrace->flags, F_ANIMAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); + addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL); + addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, ""); + addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); + addflag(lastrace->flags, F_FLYING, B_TRUE, NA, NA, ""); + addflag(lastrace->flags, F_HITDICE, 1, 4, NA, ""); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d2"); + addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d2"); + addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL); + addflag(lastrace->flags, F_NOBODYPART, BP_WEAPON, NA, NA, NULL); + addflag(lastrace->flags, F_NOBODYPART, BP_SECWEAPON, NA, NA, NULL); + addflag(lastrace->flags, F_NOBODYPART, BP_SHOULDERS, NA, NA, NULL); + addflag(lastrace->flags, F_NOBODYPART, BP_HANDS, NA, NA, NULL); + addflag(lastrace->flags, F_NOPACK, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_CANWILL, OT_A_SWOOP, 3, 3, NULL); + addflag(lastrace->flags, F_SWOOPRANGE, 2, NA, NA, NULL); + + addrace(R_HAWK, "hawk", 1, 'A', C_GREY, MT_FLESH); // '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); + addflag(lastrace->flags, F_ANIMAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); + addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL); + addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, ""); + addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); + addflag(lastrace->flags, F_FLYING, B_TRUE, NA, NA, ""); + addflag(lastrace->flags, F_HITDICE, 2, 4, NA, ""); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d3"); + addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d3"); + addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL); + addflag(lastrace->flags, F_NOBODYPART, BP_WEAPON, NA, NA, NULL); + addflag(lastrace->flags, F_NOBODYPART, BP_SECWEAPON, NA, NA, NULL); + addflag(lastrace->flags, F_NOBODYPART, BP_SHOULDERS, NA, NA, NULL); + addflag(lastrace->flags, F_NOBODYPART, BP_HANDS, NA, NA, NULL); + addflag(lastrace->flags, F_NOPACK, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_CANWILL, OT_A_SWOOP, 3, 3, NULL); + addflag(lastrace->flags, F_SWOOPRANGE, 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 + lastrace->baseid = R_HAWK; addflag(lastrace->flags, F_RARITY, H_DUNGEON, 65, NA, ""); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_ANIMAL, B_TRUE, NA, NA, NULL); @@ -6291,7 +6707,8 @@ void initrace(void) { addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_FLYING, B_TRUE, NA, NA, ""); addflag(lastrace->flags, F_HITDICE, 3, 4, NA, ""); - addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d6+5"); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d3+3"); + addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d4+3"); addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_WEAPON, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_SECWEAPON, NA, NA, NULL); @@ -6301,7 +6718,7 @@ 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, 5, NA, NA, NULL); - addflag(lastrace->flags, F_MORALE, 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 addflag(lastrace->flags, F_RARITY, H_DUNGEON, 63, NA, ""); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -6515,8 +6932,8 @@ void initrace(void) { addflag(lastrace->flags, F_EVASION, -10, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_SLOW, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_SLOW, NA, NA, NULL); - addflag(lastrace->flags, F_HASATTACK, 1, 4, NA, "claws"); - addflag(lastrace->flags, F_HASATTACK, 1, 5, NA, "teeth"); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d4"); + addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d5"); addflag(lastrace->flags, F_CANWILL, OT_A_GRAB, NA, NA, NULL); addflag(lastrace->flags, F_DTIMMUNE, DT_COLD, NA, NA, NULL); addflag(lastrace->flags, F_DTIMMUNE, DT_POISONGAS, NA, NA, NULL); @@ -6533,13 +6950,13 @@ void initrace(void) { addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "5-20 bones"); addflag(lastrace->flags, F_BLOODOB, NA, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); - addflag(lastrace->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, 90, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); addflag(lastrace->flags, F_HITDICE, 2, 4, NA, NULL); addflag(lastrace->flags, F_EVASION, -10, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_SLOW, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); - addflag(lastrace->flags, F_HASATTACK, 1, 5, NA, "teeth"); + addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d5"); addflag(lastrace->flags, F_STARTOBDT, 50, DT_CHOP, NA, NULL); addflag(lastrace->flags, F_DTIMMUNE, DT_COLD, NA, NA, NULL); addflag(lastrace->flags, F_DTIMMUNE, DT_POISONGAS, NA, NA, NULL); @@ -6571,10 +6988,37 @@ void initrace(void) { addflag(lastrace->flags, F_DTIMMUNE, DT_NECROTIC, NA, NA, NULL); addflag(lastrace->flags, F_DTVULN, DT_HOLY, NA, NA, NULL); addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, NA, NA, NULL); + addflag(lastrace->flags, F_LEVITATING, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL); 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); + 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); + addflag(lastrace->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, 55, NA, NULL); + addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); + addflag(lastrace->flags, F_HITDICE, 4, 2, NA, NULL); + addflag(lastrace->flags, F_MOVESPEED, SP_SLOW, NA, NA, NULL); + addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); + addflag(lastrace->flags, F_DTIMMUNE, DT_COLD, NA, NA, NULL); + addflag(lastrace->flags, F_DTIMMUNE, DT_POISONGAS, NA, NA, NULL); + addflag(lastrace->flags, F_DTIMMUNE, DT_DECAY, NA, NA, NULL); + addflag(lastrace->flags, F_DTIMMUNE, DT_NECROTIC, NA, NA, NULL); + addflag(lastrace->flags, F_DTVULN, DT_HOLY, NA, NA, NULL); + addflag(lastrace->flags, F_NONCORPOREAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_SEEINDARK, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_XRAYVIS, 3, NA, NA, NULL); + addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); + addflag(lastrace->flags, F_INDUCEFEAR, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_CANWILL, OT_S_INVISIBILITY, 40, 40, "pw:1;"); + // 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); addflag(lastrace->flags, F_UNDEAD, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_MINDLESS, NA, NULL); @@ -6644,6 +7088,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOBODYPART, BP_LEGS, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_FEET, NA, NA, NULL); addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NODEATHANNOUNCE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SEEINDARK, UNLIMITED, NA, NA, NULL); addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); @@ -6700,6 +7145,18 @@ enum BURDENED isburdened(lifeform_t *lf) { return BR_NONE; } +int ischarmable(lifeform_t *lf) { + if (getiqname(getattr(lf, A_IQ), NULL) <= IQ_VEGETABLE) { + reason = E_LOWIQ; + return B_FALSE; + } + if (hasflag(lf->flags, F_UNDEAD)) { + reason = E_UNDEAD; + return B_FALSE; + } + return B_TRUE; +} + int isdead(lifeform_t *lf) { if (!lf->alive) return B_TRUE; if (lf->hp <= 0) return B_TRUE; @@ -6719,9 +7176,11 @@ void killlf(lifeform_t *lf) { // shouldn't need this... lf->cell = NULL; + // remove impossible flags... // check if anyone is targetting us. // if so, stop targetting us now that // we are dead. + // also: does anyone have us as a master? // TODO: check on all maps? if ((gamemode == GM_GAMESTARTED)) { for (l = m->lf ; l ; l = l->next) { @@ -6731,6 +7190,10 @@ void killlf(lifeform_t *lf) { if (f) killflag(f); f = lfhasflagval(l, F_GRABBING, lf->id, NA, NA, NULL); if (f) killflag(f); + f = lfhasflagval(l, F_PETOF, lf->id, NA, NA, NULL); + if (f) killflag(f); + f = lfhasflagval(l, F_ALLYOF, lf->id, NA, NA, NULL); + if (f) killflag(f); } } @@ -8043,6 +8506,7 @@ int rollstat(lifeform_t *lf, enum ATTRIB attr) { int scare(lifeform_t *lf, lifeform_t *scarer, int howlong) { int nfailures = 0; int i; + int penalty = 0; if (!scarer) return B_FALSE; // immune to fear? @@ -8053,11 +8517,32 @@ int scare(lifeform_t *lf, lifeform_t *scarer, int howlong) { if (getiqname(getattr(scarer, A_IQ), NULL) <= IQ_VEGETABLE) { return B_FALSE; } + + // determine morale check penalty + if (isbleeding(lf)) { + penalty += 5; + } + if (lfhasflag(lf, F_HUMANOID)) { + object_t *o; + o = getequippedob(scarer->pack, BP_EYES); + if (o && (o->type->id == OT_EYEPATCH)) { + penalty += 2; + } + o = getequippedob(scarer->pack, BP_HEAD); + if (o) { + if (o->type->id == OT_HELMBONE) { + penalty += 4; + } else if (o->type->id == OT_PIRATEHAT) { + penalty += 2; + } + } + } + // three checks nfailures = 0; for (i = 0; i < 3; i++) { - if (!skillcheckvs(lf, SC_MORALE, isbleeding(lf) ? 0 : 5 , scarer, SC_MORALE, 0)) { + if (!skillcheckvs(lf, SC_MORALE, penalty, scarer, SC_MORALE, 0)) { nfailures++; } } @@ -8178,7 +8663,7 @@ void setguntarget(lifeform_t *lf, lifeform_t *targ) { } } -void setrace(lifeform_t *lf, enum RACE rid) { +void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) { flag_t *f,*nextf; int i; race_t *newrace; @@ -8186,11 +8671,17 @@ void setrace(lifeform_t *lf, enum RACE rid) { newrace = findrace(rid); - if ((gamemode == GM_GAMESTARTED) && lf->race) { + if (isplayer(lf)) { + statdirty = B_TRUE; + } + + if (frompolymorph && (gamemode == GM_GAMESTARTED) && lf->race) { race_t *origrace; - statdirty = B_TRUE; + // remove 'become a ghost' flag + killflagsofid(lf->flags, F_RISEASGHOST); + // were we already polymorphed? f = lfhasflag(lf, F_ORIGRACE); if (f) { origrace = findrace(f->val[0]); @@ -8265,8 +8756,10 @@ void setrace(lifeform_t *lf, enum RACE rid) { for (i = 0; i < lf->level-1; i++) { lf->maxmp += rollmpdice(lf); } - lf->mp = lf->maxmp; + } else { + lf->maxmp = 0; } + lf->mp = lf->maxmp; lf->born = B_TRUE; @@ -8337,6 +8830,7 @@ void setrace(lifeform_t *lf, enum RACE rid) { } } } // end if gamestarted + } void setlastdam(lifeform_t *lf, char *buf) { @@ -8573,6 +9067,11 @@ int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *r int skillcheckvs(lifeform_t *lf1, enum CHECKTYPE ct1, int mod1, lifeform_t *lf2, enum CHECKTYPE ct2, int mod2) { int roll1,roll2; int db = B_FALSE; + + if (lfhasflag(lf1, F_DEBUG)) { + db = B_TRUE; + } + real_skillcheck(lf1, ct1, 0, mod1, &roll1); real_skillcheck(lf2, ct2, 0, mod2, &roll2); if (db) { @@ -8599,7 +9098,8 @@ int slipon(lifeform_t *lf, object_t *o) { char lfname[BUFLEN]; - if (lfhasflag(lf, F_STABILITY) || !hasbp(lf, BP_FEET)) { + if (lfhasflag(lf, F_STABILITY) || !hasbp(lf, BP_FEET) || + lfhasflag(lf, F_NONCORPOREAL) || isairborne(lf)) { return B_TRUE; } @@ -8942,7 +9442,7 @@ void timeeffectslf(lifeform_t *lf) { } r = findrace(rid); if (r) { - setrace(lf, r->id); + setrace(lf, r->id, B_TRUE); } else { if (isplayer(lf)) { msg("For some reason, you are unable to revert to your original form!"); @@ -9086,6 +9586,44 @@ void turneffectslf(lifeform_t *lf) { } } + // handle ghosts + if (lf->race->id == R_GHOST) { + f = lfhasflag(lf, F_MYCORPSE); + if (f) { + long corpseid; + cell_t *corpseloc = NULL; + object_t *corpse; + + corpseid = atol(f->text); + + corpse = findobidinmap(lf->cell->map, corpseid); + if (corpse) { + corpseloc = corpse->pile->where; + } + // can we see our corpse? + if (corpseloc && haslos(lf, corpseloc)) { + // give possession ability + if (!lfhasflagval(lf, F_CANWILL, OT_S_POSSESSION, NA, NA, NULL)) { + char pwbuf[BUFLEN]; + int power; + power = lf->level / 3; + if (power < 1) power = 1; + if (power > 10) power = 10; + sprintf(pwbuf, "pw:%d;",power); + f = addflag(lf->flags, F_CANWILL, OT_S_POSSESSION, NA, NA, pwbuf); + f->lifetime = FROMRACE; + } + } else { + // can't see corpse + f = lfhasflagval(lf, F_CANWILL, OT_S_POSSESSION, NA, NA, NULL); + if (f) killflag(f); + // drain life + if (isplayer(lf)) msg("Without your corpse, you feel yourself fading into nothingness."); + losehp(lf, 2, DT_DIRECT, NULL, "fading into nothingness"); + } + } + } + // gains/loses stench? for (l = lf->cell->map->lf ; l ; l = l->next) { if (!isdead(l) && (l != lf)) { @@ -9270,8 +9808,10 @@ void turneffectslf(lifeform_t *lf) { continue; } } - + if ((f->id == F_CHARMEDBY) || + (f->id == F_PETOF) || + (f->id == F_ALLYOF) || (f->id == F_FLEEFROM) || (f->id == F_NOFLEEFROM)) { lifeform_t *lf; @@ -9352,6 +9892,34 @@ int touch(lifeform_t *lf, object_t *o) { } } + // undead and blesed objects? + if (lfhasflag(lf, F_UNDEAD) && isblessed(o)) { + object_t *gloves; + // not wearing gloves? + gloves = getequippedob(lf->pack, BP_HANDS); + if (!gloves) { + if (isplayer(lf)) { + msg("The %s burn%s you as you touch %s!",noprefix(obname), + (o->amt == 1) ? "s" : "", + (o->amt == 1) ? "it" : "them" ); + o->blessknown = B_TRUE; + } else if (cansee(player, lf)) { + msg("%s touches %s then recoils in pain!",lfname, obname); + o->blessknown = B_TRUE; + } + // use real name here... + real_getobname(o, obname, o->amt, B_TRUE, B_FALSE, B_FALSE, B_TRUE); + sprintf(buf, "touching %s",obname); + losehp(lf, 2, DT_HOLY, NULL, buf); + // drop the object if we're holding it + if (o->pile->owner == lf) { + drop(o, ALL); + } + return B_TRUE; + } + } + + f = hasflag(o->flags, F_SHARP); if (f) { object_t *gloves; @@ -9489,6 +10057,8 @@ int usestairs(lifeform_t *lf, object_t *o) { char lfname[BUFLEN]; char obname[BUFLEN]; int isportal = B_FALSE; + lifeform_t *adjally[8]; + int nadjallies = 0; // need up update 'dlev:' if (isplayer(lf)) { @@ -9535,6 +10105,16 @@ int usestairs(lifeform_t *lf, object_t *o) { } } + // find adjacent allies + for (dir = DC_N; dir <= DC_NW; dir++) { + cell_t *c; + c = getcellindir(lf->cell, dir); + if (c && c->lf && areallies(lf, c->lf)) { + adjally[nadjallies] = c->lf; + nadjallies++; + } + } + // do stairs go somewhere? newcell = getstairdestination(o); if (!newcell) { @@ -9559,6 +10139,7 @@ int usestairs(lifeform_t *lf, object_t *o) { } if (newcell) { + int n; // check noone is in the way if (newcell->lf) { cell_t *c; @@ -9583,6 +10164,16 @@ int usestairs(lifeform_t *lf, object_t *o) { // move player to new map moveto(lf, newcell, B_TRUE); taketime(lf, getmovespeed(lf)); + + // move adjacent allies 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])); + } + } } else { dblog("ERROR - can't find opposite end of stairs/portal!"); msg("ERROR - can't find opposite end of stairs/portal!"); @@ -9636,10 +10227,15 @@ int validateraces(void) { race_t *r; flag_t *f; skill_t *sk; + job_t *j; int i; - cell_t fakecell; map_t fakemap; + + // first generate xp list + genxplist(); + + // make a fake cell fakemap.lf = NULL; fakemap.lastlf = NULL; @@ -9664,7 +10260,12 @@ int validateraces(void) { printf("ERROR in race '%s' - F_HASATTACK with bad object.\n", r->name); goterror = B_TRUE; } - if (!strlen(f->text)) { + if (strlen(f->text)) { + if (!strchr(f->text, 'd')) { + printf("ERROR in race '%s' - F_HASATTACK text does not seem to be in 'xdy' format.\n", r->name); + goterror = B_TRUE; + } + } else { printf("ERROR in race '%s' - F_HASATTACK with no damage value.\n", r->name); goterror = B_TRUE; } @@ -9739,6 +10340,17 @@ int validateraces(void) { printf("ERROR - MAXSKILLS is %d but found %d skills.\n",MAXSKILLS,i); goterror = B_TRUE; } + for (j = firstjob ; j ; j = j->next) { + f = hasflag(j->flags, F_HASPET); + if (f) { + race_t *r; + r = findracebyname(f->text); + if (!r) { + printf("ERROR - job %s has unknown pet '%s'\n",j->name,f->text); + goterror = B_TRUE; + } + } + } return goterror; } @@ -10134,8 +10746,11 @@ int weild(lifeform_t *lf, object_t *o) { case E_NOUNARMEDATTACK: msg("You cannot fight without a weapon!"); break; + case E_IMPOSSIBLE: + msg("You cannot weild weapons!"); + break; case E_NOHANDS: - msg("You are not capable of weilding a weapon!"); + msg("You do not have enough free hands to weild this weapon."); break; case E_LOWCON: msg("You are not healthy enough to use this weapon."); @@ -10158,6 +10773,21 @@ int weild(lifeform_t *lf, object_t *o) { return B_TRUE; } + // anything else weilded? + weildloc = getweildloc(o, &otherloc, &twohanded); + + // firearm in regular hand? + // note: this is the same logic as in canweild() + if (o && !hasbp(lf, weildloc) && isfirearm(o) && !getequippedob(lf->pack, otherloc)) { + int temp; + // firearm can go in other hand. + // swap locations. + temp = weildloc; + weildloc = otherloc; + otherloc = temp; + } + + // metal objects and magshield? if (lfhasflag(lf, F_MAGSHIELD)) { if (isplayer(lf)) { @@ -10166,27 +10796,6 @@ int weild(lifeform_t *lf, object_t *o) { return B_TRUE; } - - // anything else weilded? - if (o) { - if (hasflag(o->flags, F_FIREARM)) { - weildloc = BP_SECWEAPON; - otherloc = BP_WEAPON; - } else { - weildloc = BP_WEAPON; - otherloc = BP_SECWEAPON; - } - - if (hasflag(o->flags, F_TWOHANDED)) { - twohanded = B_TRUE; - } else { - twohanded = B_FALSE; - } - } else { // ie. asked to fight unarmed - weildloc = BP_WEAPON; - twohanded = B_FALSE; - } - for (oo = lf->pack->first ; oo ; oo = oo->next) { f = hasflagval(oo->flags, F_EQUIPPED, weildloc, -1, -1, NULL); if (f) { @@ -10319,7 +10928,7 @@ int weild(lifeform_t *lf, object_t *o) { strcat(buf2, "."); msg(buf2); // warn if it won't do any damage - if (!hasflag(o->flags, F_DAM) && !hasflag(o->flags, F_FIREARM)) { + if (!ismeleeweapon(o) && !isfirearm(o)) { msg("You have a feeling that this weapon will not be very effective..."); } else { // warn if unskilled in this weapon @@ -10330,11 +10939,14 @@ int weild(lifeform_t *lf, object_t *o) { } } } else if (cansee(player, lf)) { - char buf2[BUFLEN]; - getlfname(lf, buf2); - msg("%s weilds %s.", buf2, buf); - + if (lf->race->id != R_DANCINGWEAPON) { + char buf2[BUFLEN]; + getlfname(lf, buf2); + msg("%s weilds %s.", buf2, buf); + } } + + touch(lf, o); if (o->blessed == B_CURSED) { diff --git a/lf.h b/lf.h index c31054c..0c40d23 100644 --- a/lf.h +++ b/lf.h @@ -21,6 +21,7 @@ int caneat(lifeform_t *lf, object_t *o); int canhear(lifeform_t *lf, cell_t *c); int canlearn(lifeform_t *lf, enum SKILL skid); int canpickup(lifeform_t *lf, object_t *o, int amt); +int canpolymorphto(enum RACE rid); int canpush(lifeform_t *lf, object_t *o, int dir); int canquaff(lifeform_t *lf, object_t *o); int canrest(lifeform_t *lf); @@ -29,7 +30,9 @@ int canwear(lifeform_t *lf, object_t *o, enum BODYPART where); 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); int countmoney(lifeform_t *lf); +void debug(lifeform_t *lf); void die(lifeform_t *lf); void dumplf(void); void dumpxp(void); @@ -53,6 +56,7 @@ void gainhp(lifeform_t *lf, int amt); void gainlevel(lifeform_t *lf); void gainmp(lifeform_t *lf, int amt); void gainxp(lifeform_t *lf, long amt); +void genxplist(void); int getactspeed(lifeform_t *lf); enum ALLEGIENCE getallegiance(lifeform_t *lf); object_t *getarmour(lifeform_t *lf, enum BODYPART bp); @@ -82,6 +86,7 @@ int getlfaccuracy(lifeform_t *lf, object_t *wep); enum LFCONDITION getlfcondition(lifeform_t *lf); int getnightvisrange(lifeform_t *lf); char *getlfconditionname(enum LFCONDITION cond); +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); @@ -111,6 +116,7 @@ race_t *getrandomrace(map_t *map, int forcedepth); race_t *getreallyrandomrace(void); enum SKILLLEVEL getskill(lifeform_t *lf, enum SKILL id); char *getspeedname(int speed, char *buf); +char *getspeednameshort(int speed, char *buf); float getstatmod(lifeform_t *lf, enum ATTRIB att); enum CONBRACKET getconname(int str, char *buf); enum STRBRACKET getstrname(int str, char *buf); @@ -149,6 +155,7 @@ int isairborne(lifeform_t *lf); int isbleeding(lifeform_t *lf); int isblind(lifeform_t *lf); enum BURDENED isburdened(lifeform_t *lf); +int ischarmable(lifeform_t *lf); int isdead(lifeform_t *lf); int isfleeing(lifeform_t *lf); int isfreebp(lifeform_t *lf, enum BODYPART bp); @@ -198,7 +205,7 @@ int scare(lifeform_t *lf, lifeform_t *scarer, int howlong); int setammo(lifeform_t *lf, object_t *o); void setattr(lifeform_t *lf, enum ATTRIB attr, int val); void setguntarget(lifeform_t *lf, lifeform_t *targ); -void setrace(lifeform_t *lf, enum RACE rid); +void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph); void setlastdam(lifeform_t *lf, char *buf); //void setlftarget(lifeform_t *lf, lifeform_t *victim); int shoot(lifeform_t *lf); diff --git a/log.txt b/log.txt index f4c126e..cf2b081 100644 --- a/log.txt +++ b/log.txt @@ -9,11 +9,14 @@ xxx xxx xxx xxx +xxx +xxx +xxx +xxx finding random lf with rarity val 85-100 -> possibility: goblin, rarity=85 -> possibility: kobold, rarity=90 --> possibility: troglodyte, rarity=85 -> possibility: xat, rarity=90 -> possibility: giant bat, rarity=90 -> possibility: giant worker ant, rarity=85 @@ -22,12 +25,12 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 got 11 possibilities. finding random lf with rarity val 85-100 -> possibility: goblin, rarity=85 -> possibility: kobold, rarity=90 --> possibility: troglodyte, rarity=85 -> possibility: xat, rarity=90 -> possibility: giant bat, rarity=90 -> possibility: giant worker ant, rarity=85 @@ -36,12 +39,12 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 got 11 possibilities. finding random lf with rarity val 85-100 -> possibility: goblin, rarity=85 -> possibility: kobold, rarity=90 --> possibility: troglodyte, rarity=85 -> possibility: xat, rarity=90 -> possibility: giant bat, rarity=90 -> possibility: giant worker ant, rarity=85 @@ -50,12 +53,12 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 got 11 possibilities. finding random lf with rarity val 85-100 -> possibility: goblin, rarity=85 -> possibility: kobold, rarity=90 --> possibility: troglodyte, rarity=85 -> possibility: xat, rarity=90 -> possibility: giant bat, rarity=90 -> possibility: giant worker ant, rarity=85 @@ -64,12 +67,12 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 got 11 possibilities. finding random lf with rarity val 85-100 -> possibility: goblin, rarity=85 -> possibility: kobold, rarity=90 --> possibility: troglodyte, rarity=85 -> possibility: xat, rarity=90 -> possibility: giant bat, rarity=90 -> possibility: giant worker ant, rarity=85 @@ -78,12 +81,12 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 got 11 possibilities. finding random lf with rarity val 85-100 -> possibility: goblin, rarity=85 -> possibility: kobold, rarity=90 --> possibility: troglodyte, rarity=85 -> possibility: xat, rarity=90 -> possibility: giant bat, rarity=90 -> possibility: giant worker ant, rarity=85 @@ -92,12 +95,12 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 got 11 possibilities. finding random lf with rarity val 85-100 -> possibility: goblin, rarity=85 -> possibility: kobold, rarity=90 --> possibility: troglodyte, rarity=85 -> possibility: xat, rarity=90 -> possibility: giant bat, rarity=90 -> possibility: giant worker ant, rarity=85 @@ -106,12 +109,12 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 got 11 possibilities. finding random lf with rarity val 85-100 -> possibility: goblin, rarity=85 -> possibility: kobold, rarity=90 --> possibility: troglodyte, rarity=85 -> possibility: xat, rarity=90 -> possibility: giant bat, rarity=90 -> possibility: giant worker ant, rarity=85 @@ -120,12 +123,12 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 got 11 possibilities. finding random lf with rarity val 85-100 -> possibility: goblin, rarity=85 -> possibility: kobold, rarity=90 --> possibility: troglodyte, rarity=85 -> possibility: xat, rarity=90 -> possibility: giant bat, rarity=90 -> possibility: giant worker ant, rarity=85 @@ -134,12 +137,12 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 got 11 possibilities. finding random lf with rarity val 85-100 -> possibility: goblin, rarity=85 -> possibility: kobold, rarity=90 --> possibility: troglodyte, rarity=85 -> possibility: xat, rarity=90 -> possibility: giant bat, rarity=90 -> possibility: giant worker ant, rarity=85 @@ -148,12 +151,12 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 got 11 possibilities. finding random lf with rarity val 85-100 -> possibility: goblin, rarity=85 -> possibility: kobold, rarity=90 --> possibility: troglodyte, rarity=85 -> possibility: xat, rarity=90 -> possibility: giant bat, rarity=90 -> possibility: giant worker ant, rarity=85 @@ -162,12 +165,12 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 got 11 possibilities. finding random lf with rarity val 85-100 -> possibility: goblin, rarity=85 -> possibility: kobold, rarity=90 --> possibility: troglodyte, rarity=85 -> possibility: xat, rarity=90 -> possibility: giant bat, rarity=90 -> possibility: giant worker ant, rarity=85 @@ -176,12 +179,12 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 got 11 possibilities. finding random lf with rarity val 85-100 -> possibility: goblin, rarity=85 -> possibility: kobold, rarity=90 --> possibility: troglodyte, rarity=85 -> possibility: xat, rarity=90 -> possibility: giant bat, rarity=90 -> possibility: giant worker ant, rarity=85 @@ -190,12 +193,12 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 got 11 possibilities. finding random lf with rarity val 85-100 -> possibility: goblin, rarity=85 -> possibility: kobold, rarity=90 --> possibility: troglodyte, rarity=85 -> possibility: xat, rarity=90 -> possibility: giant bat, rarity=90 -> possibility: giant worker ant, rarity=85 @@ -204,54 +207,12 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 got 11 possibilities. finding random lf with rarity val 85-100 -> possibility: goblin, rarity=85 -> possibility: kobold, rarity=90 --> possibility: troglodyte, rarity=85 --> possibility: xat, rarity=90 --> possibility: giant bat, rarity=90 --> possibility: giant worker ant, rarity=85 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=90 --> possibility: brown snake, rarity=85 --> possibility: giant fly, rarity=85 --> possibility: glowbug, rarity=85 -got 11 possibilities. -finding random lf with rarity val 85-100 - --> possibility: goblin, rarity=85 --> possibility: kobold, rarity=90 --> possibility: troglodyte, rarity=85 --> possibility: xat, rarity=90 --> possibility: giant bat, rarity=90 --> possibility: giant worker ant, rarity=85 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=90 --> possibility: brown snake, rarity=85 --> possibility: giant fly, rarity=85 --> possibility: glowbug, rarity=85 -got 11 possibilities. -finding random lf with rarity val 85-100 - --> possibility: goblin, rarity=85 --> possibility: kobold, rarity=90 --> possibility: troglodyte, rarity=85 --> possibility: xat, rarity=90 --> possibility: giant bat, rarity=90 --> possibility: giant worker ant, rarity=85 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=90 --> possibility: brown snake, rarity=85 --> possibility: giant fly, rarity=85 --> possibility: glowbug, rarity=85 -got 11 possibilities. -finding random lf with rarity val 85-100 - --> possibility: goblin, rarity=85 --> possibility: kobold, rarity=90 --> possibility: troglodyte, rarity=85 -> possibility: xat, rarity=90 -> possibility: giant bat, rarity=90 -> possibility: giant worker ant, rarity=85 @@ -260,460 +221,646 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 got 11 possibilities. rollhitdice() - rolling 2d4 + 2 -rollhitdice() - mod is +44% -rollhitdice() ---- die 1/2 == 6 -rollhitdice() ---- die 2/2 == 3 -TOTAL: 9 - -> modified to: 12 +rollhitdice() - mod is +0% +rollhitdice() ---- die 1/2 == 4 +rollhitdice() ---- die 2/2 == 4 +TOTAL: 8 + -> modified to: 8 givejob() starting. -processing normal flag: 162 -processing normal flag: 162 -processing normal flag: 162 -processing normal flag: 162 -processing normal flag: 157 -processing normal flag: 157 -processing normal flag: 157 -processing normal flag: 157 -processing normal flag: 158 -processing normal flag: 158 -processing normal flag: 158 -processing normal flag: 158 -processing normal flag: 158 -processing normal flag: 158 -processing normal flag: 158 -processing normal flag: 156 -processing normal flag: 156 -processing normal flag: 156 -processing normal flag: 156 -processing normal flag: 156 -processing normal flag: 156 -processing normal flag: 156 -processing normal flag: 156 -processing normal flag: 156 -processing normal flag: 156 +processing normal flag: 164 +processing normal flag: 164 +processing normal flag: 279 +processing normal flag: 223 +processing normal flag: 223 +processing normal flag: 249 processing normal flag: 304 -processing normal flag: 304 -initial dam[0] = 1 -adjusted for lf to dam[0] = 1 -reduced by armour to dam[0] = 0 -initial dam[0] = 6 -adjusted for lf to dam[0] = 6 -reduced by armour to dam[0] = 6 -calcxp: calculating xpval for giant rat -calcxp: a teeth: == 1-2 dam, avg is 1.5 -calcxp: a claws: == 1-3 dam, avg is 1.9 -calcxp: avg damage dealt is 3.4 -calcxp: DEFENCE IS 1.0 -calcxp: avg damage dealt (with abilities) is 3.4 -calcxp: ATTACKVAL IS 34.0 -calcxp: xpval: 35.0 --> 35.0 -calcxp: ------ FINAL XPVAL: 34 ------ - -initial dam[0] = 4 -adjusted for lf to dam[0] = 4 -reduced by armour to dam[0] = 3 -initial dam[0] = 1 -adjusted for lf to dam[0] = 1 -reduced by armour to dam[0] = 1 -initial dam[0] = 1 -adjusted for lf to dam[0] = 1 -reduced by armour to dam[0] = 1 -initial dam[0] = 6 -adjusted for lf to dam[0] = 6 -reduced by armour to dam[0] = 6 -initial dam[0] = 4 -adjusted for lf to dam[0] = 4 -reduced by armour to dam[0] = 3 -initial dam[0] = 7 -adjusted for lf to dam[0] = 7 -reduced by armour to dam[0] = 6 -calcxp: calculating xpval for giant worker ant -calcxp: a teeth: == 4-4 dam, avg is 4.3 -calcxp: avg damage dealt is 4.3 -calcxp: DEFENCE IS 4.0 -calcxp: avg damage dealt (with abilities) is 4.3 -calcxp: ATTACKVAL IS 42.8 -calcxp: xpval: 46.8 --> 46.8 -calcxp: ------ FINAL XPVAL: 46 ------ - -rollhitdice() - rolling 2d4 + 2 -rollhitdice() - mod is +66% -rollhitdice() ---- die 1/2 == 6 -rollhitdice() ---- die 2/2 == 6 -TOTAL: 12 - -> modified to: 19 -nwantflags is 1 -nwantflags is 0 -nwantflags is 0 -nwantflags is 0 -nwantflags is 0 -initial dam[0] = 1 -adjusted for lf to dam[0] = 1 -reduced by armour to dam[0] = 0 -nwantflags is 0 -fireat(): dam = throwdam(5) * speed(2) = 10 -calcxp: calculating xpval for xat -calcxp: a teeth: == 1-3 dam, avg is 1.7 -calcxp: avg damage dealt is 1.7 -calcxp: DEFENCE IS 4.0 -calcxp: avg damage dealt (with abilities) is 1.7 -calcxp: ATTACKVAL IS 17.2 -calcxp: xpval: 21.2 --> 21.2 -calcxp: ------ FINAL XPVAL: 21 ------ - -nwantflags is 0 -nwantflags is 0 -initial dam[0] = 3 -adjusted for lf to dam[0] = 3 -reduced by armour to dam[0] = 2 -initial dam[0] = 1 -adjusted for lf to dam[0] = 1 -reduced by armour to dam[0] = 0 +processing normal flag: 294 +processing normal flag: 170 +processing normal flag: 159 +processing normal flag: 159 +processing normal flag: 159 +processing normal flag: 159 +processing normal flag: 159 +processing normal flag: 159 +processing normal flag: 160 +processing normal flag: 160 +processing normal flag: 158 +processing normal flag: 158 +processing normal flag: 158 +processing normal flag: 158 +processing normal flag: 158 +processing normal flag: 158 initial dam[0] = 3 adjusted for lf to dam[0] = 3 reduced by armour to dam[0] = 3 -initial dam[0] = 1 -adjusted for lf to dam[0] = 1 -reduced by armour to dam[0] = 0 initial dam[0] = 2 adjusted for lf to dam[0] = 2 reduced by armour to dam[0] = 2 -calcxp: calculating xpval for giant bat -calcxp: a teeth: == 1-2 dam, avg is 2.2 -calcxp: a claws: == 1-3 dam, avg is 2.9 -calcxp: avg damage dealt is 5.1 -calcxp: DEFENCE IS 2.0 -calcxp: avg damage dealt (with abilities) is 5.1 -calcxp: ATTACKVAL IS 51.1 -calcxp: xpval: 53.1 --> 53.1 -calcxp: ------ FINAL XPVAL: 53 ------ +xxx +xxx +xxx +xxx +xxx +xxx +xxx +xxx +finding random lf with rarity val 85-100 -nwantflags is 0 -nwantflags is 0 -nwantflags is 0 -nwantflags is 0 -initial dam[0] = 7 -adjusted for lf to dam[0] = 7 -reduced by armour to dam[0] = 6 -initial dam[0] = 6 -adjusted for lf to dam[0] = 6 -reduced by armour to dam[0] = 5 +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +nwantflags is 1 +xxx +xxx +xxx +xxx +xxx +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. +finding random lf with rarity val 85-100 + +-> possibility: goblin, rarity=85 +-> possibility: kobold, rarity=90 +-> possibility: xat, rarity=90 +-> possibility: giant bat, rarity=90 +-> possibility: giant worker ant, rarity=85 +-> possibility: giant newt, rarity=100 +-> possibility: giant rat, rarity=90 +-> possibility: brown snake, rarity=85 +-> possibility: giant fly, rarity=85 +-> possibility: glowbug, rarity=85 +-> possibility: skeleton, rarity=90 +got 11 possibilities. initial dam[0] = 4 adjusted for lf to dam[0] = 4 reduced by armour to dam[0] = 4 -calcxp: calculating xpval for goblin -calcxp: a claws: == 1-4 dam, avg is 2.7 -calcxp: a gold coin: == 0-0 dam, avg is 0.0 -calcxp: a short sword: == 1-6 dam, avg is 3.4 -calcxp: avg damage dealt is 6.1 -calcxp: DEFENCE IS 7.0 -calcxp: avg damage dealt (with abilities) is 6.1 -calcxp: ATTACKVAL IS 60.7 -calcxp: xpval: 67.7 --> 67.7 -calcxp: ------ FINAL XPVAL: 67 ------ - nwantflags is 0 -nwantflags is 0 -nwantflags is 0 -initial dam[0] = 9 -adjusted for lf to dam[0] = 9 -reduced by armour to dam[0] = 9 -calcxp: calculating xpval for giant newt -calcxp: avg damage dealt is 0.0 -calcxp: DEFENCE IS 4.0 -calcxp: avg damage dealt (with abilities) is 0.0 -calcxp: ATTACKVAL IS 0.0 -calcxp: xpval: 4.0 --> 4.0 -calcxp: ------ FINAL XPVAL: 4 ------ - -xxx -xxx -xxx -xxx -xxx -xxx -xxx -xxx -xxx -finding random lf with rarity val 85-100 - --> possibility: goblin, rarity=85 --> possibility: kobold, rarity=90 --> possibility: troglodyte, rarity=85 --> possibility: xat, rarity=90 --> possibility: giant bat, rarity=90 --> possibility: giant worker ant, rarity=85 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=90 --> possibility: brown snake, rarity=85 --> possibility: giant fly, rarity=85 --> possibility: glowbug, rarity=85 -got 11 possibilities. -finding random lf with rarity val 85-100 - --> possibility: goblin, rarity=85 --> possibility: kobold, rarity=90 --> possibility: troglodyte, rarity=85 --> possibility: xat, rarity=90 --> possibility: giant bat, rarity=90 --> possibility: giant worker ant, rarity=85 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=90 --> possibility: brown snake, rarity=85 --> possibility: giant fly, rarity=85 --> possibility: glowbug, rarity=85 -got 11 possibilities. -finding random lf with rarity val 85-100 - --> possibility: goblin, rarity=85 --> possibility: kobold, rarity=90 --> possibility: troglodyte, rarity=85 --> possibility: xat, rarity=90 --> possibility: giant bat, rarity=90 --> possibility: giant worker ant, rarity=85 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=90 --> possibility: brown snake, rarity=85 --> possibility: giant fly, rarity=85 --> possibility: glowbug, rarity=85 -got 11 possibilities. -finding random lf with rarity val 85-100 - --> possibility: goblin, rarity=85 --> possibility: kobold, rarity=90 --> possibility: troglodyte, rarity=85 --> possibility: xat, rarity=90 --> possibility: giant bat, rarity=90 --> possibility: giant worker ant, rarity=85 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=90 --> possibility: brown snake, rarity=85 --> possibility: giant fly, rarity=85 --> possibility: glowbug, rarity=85 -got 11 possibilities. -finding random lf with rarity val 85-100 - --> possibility: goblin, rarity=85 --> possibility: kobold, rarity=90 --> possibility: troglodyte, rarity=85 --> possibility: xat, rarity=90 --> possibility: giant bat, rarity=90 --> possibility: giant worker ant, rarity=85 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=90 --> possibility: brown snake, rarity=85 --> possibility: giant fly, rarity=85 --> possibility: glowbug, rarity=85 -got 11 possibilities. -finding random lf with rarity val 85-100 - --> possibility: goblin, rarity=85 --> possibility: kobold, rarity=90 --> possibility: troglodyte, rarity=85 --> possibility: xat, rarity=90 --> possibility: giant bat, rarity=90 --> possibility: giant worker ant, rarity=85 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=90 --> possibility: brown snake, rarity=85 --> possibility: giant fly, rarity=85 --> possibility: glowbug, rarity=85 -got 11 possibilities. -finding random lf with rarity val 85-100 - --> possibility: goblin, rarity=85 --> possibility: kobold, rarity=90 --> possibility: troglodyte, rarity=85 --> possibility: xat, rarity=90 --> possibility: giant bat, rarity=90 --> possibility: giant worker ant, rarity=85 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=90 --> possibility: brown snake, rarity=85 --> possibility: giant fly, rarity=85 --> possibility: glowbug, rarity=85 -got 11 possibilities. -finding random lf with rarity val 85-100 - --> possibility: goblin, rarity=85 --> possibility: kobold, rarity=90 --> possibility: troglodyte, rarity=85 --> possibility: xat, rarity=90 --> possibility: giant bat, rarity=90 --> possibility: giant worker ant, rarity=85 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=90 --> possibility: brown snake, rarity=85 --> possibility: giant fly, rarity=85 --> possibility: glowbug, rarity=85 -got 11 possibilities. -finding random lf with rarity val 85-100 - --> possibility: goblin, rarity=85 --> possibility: kobold, rarity=90 --> possibility: troglodyte, rarity=85 --> possibility: xat, rarity=90 --> possibility: giant bat, rarity=90 --> possibility: giant worker ant, rarity=85 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=90 --> possibility: brown snake, rarity=85 --> possibility: giant fly, rarity=85 --> possibility: glowbug, rarity=85 -got 11 possibilities. -finding random lf with rarity val 85-100 - --> possibility: goblin, rarity=85 --> possibility: kobold, rarity=90 --> possibility: troglodyte, rarity=85 --> possibility: xat, rarity=90 --> possibility: giant bat, rarity=90 --> possibility: giant worker ant, rarity=85 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=90 --> possibility: brown snake, rarity=85 --> possibility: giant fly, rarity=85 --> possibility: glowbug, rarity=85 -got 11 possibilities. -finding random lf with rarity val 85-100 - --> possibility: goblin, rarity=85 --> possibility: kobold, rarity=90 --> possibility: troglodyte, rarity=85 --> possibility: xat, rarity=90 --> possibility: giant bat, rarity=90 --> possibility: giant worker ant, rarity=85 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=90 --> possibility: brown snake, rarity=85 --> possibility: giant fly, rarity=85 --> possibility: glowbug, rarity=85 -got 11 possibilities. -finding random lf with rarity val 85-100 - --> possibility: goblin, rarity=85 --> possibility: kobold, rarity=90 --> possibility: troglodyte, rarity=85 --> possibility: xat, rarity=90 --> possibility: giant bat, rarity=90 --> possibility: giant worker ant, rarity=85 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=90 --> possibility: brown snake, rarity=85 --> possibility: giant fly, rarity=85 --> possibility: glowbug, rarity=85 -got 11 possibilities. -finding random lf with rarity val 85-100 - --> possibility: goblin, rarity=85 --> possibility: kobold, rarity=90 --> possibility: troglodyte, rarity=85 --> possibility: xat, rarity=90 --> possibility: giant bat, rarity=90 --> possibility: giant worker ant, rarity=85 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=90 --> possibility: brown snake, rarity=85 --> possibility: giant fly, rarity=85 --> possibility: glowbug, rarity=85 -got 11 possibilities. -finding random lf with rarity val 85-100 - --> possibility: goblin, rarity=85 --> possibility: kobold, rarity=90 --> possibility: troglodyte, rarity=85 --> possibility: xat, rarity=90 --> possibility: giant bat, rarity=90 --> possibility: giant worker ant, rarity=85 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=90 --> possibility: brown snake, rarity=85 --> possibility: giant fly, rarity=85 --> possibility: glowbug, rarity=85 -got 11 possibilities. -finding random lf with rarity val 85-100 - --> possibility: goblin, rarity=85 --> possibility: kobold, rarity=90 --> possibility: troglodyte, rarity=85 --> possibility: xat, rarity=90 --> possibility: giant bat, rarity=90 --> possibility: giant worker ant, rarity=85 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=90 --> possibility: brown snake, rarity=85 --> possibility: giant fly, rarity=85 --> possibility: glowbug, rarity=85 -got 11 possibilities. -finding random lf with rarity val 85-100 - --> possibility: goblin, rarity=85 --> possibility: kobold, rarity=90 --> possibility: troglodyte, rarity=85 --> possibility: xat, rarity=90 --> possibility: giant bat, rarity=90 --> possibility: giant worker ant, rarity=85 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=90 --> possibility: brown snake, rarity=85 --> possibility: giant fly, rarity=85 --> possibility: glowbug, rarity=85 -got 11 possibilities. -finding random lf with rarity val 85-100 - --> possibility: goblin, rarity=85 --> possibility: kobold, rarity=90 --> possibility: troglodyte, rarity=85 --> possibility: xat, rarity=90 --> possibility: giant bat, rarity=90 --> possibility: giant worker ant, rarity=85 --> possibility: giant newt, rarity=100 --> possibility: giant rat, rarity=90 --> possibility: brown snake, rarity=85 --> possibility: giant fly, rarity=85 --> possibility: glowbug, rarity=85 -got 11 possibilities. -initial dam[0] = 4 -adjusted for lf to dam[0] = 4 -reduced by armour to dam[0] = 3 -nwantflags is 1 -initial dam[0] = 4 -adjusted for lf to dam[0] = 4 -reduced by armour to dam[0] = 3 -initial dam[0] = 4 -adjusted for lf to dam[0] = 4 -reduced by armour to dam[0] = 3 -initial dam[0] = 4 -adjusted for lf to dam[0] = 4 -reduced by armour to dam[0] = 3 -initial dam[0] = 8 -adjusted for lf to dam[0] = 8 -reduced by armour to dam[0] = 6 -initial dam[0] = 4 -adjusted for lf to dam[0] = 4 -reduced by armour to dam[0] = 3 -initial dam[0] = 14 -adjusted for lf to dam[0] = 14 -reduced by armour to dam[0] = 13 -calcxp: calculating xpval for giant worker ant -calcxp: a teeth: == 4-4 dam, avg is 5.2 -calcxp: avg damage dealt is 5.2 -calcxp: DEFENCE IS 4.0 -calcxp: avg damage dealt (with abilities) is 5.2 -calcxp: ATTACKVAL IS 51.6 -calcxp: xpval: 55.6 --> 55.6 -calcxp: ------ FINAL XPVAL: 55 ------ - -nwantflags is 0 -initial dam[0] = 6 -adjusted for lf to dam[0] = 6 -reduced by armour to dam[0] = 5 initial dam[0] = 1 adjusted for lf to dam[0] = 1 reduced by armour to dam[0] = 0 -initial dam[0] = 7 -adjusted for lf to dam[0] = 7 -reduced by armour to dam[0] = 6 +initial dam[0] = 1 +adjusted for lf to dam[0] = 1 +reduced by armour to dam[0] = 1 +initial dam[0] = 3 +adjusted for lf to dam[0] = 3 +reduced by armour to dam[0] = 3 +initial dam[0] = 1 +adjusted for lf to dam[0] = 1 +reduced by armour to dam[0] = 1 diff --git a/map.c b/map.c index aa5c228..55ebbbd 100644 --- a/map.c +++ b/map.c @@ -2093,6 +2093,17 @@ int isadjacent(cell_t *src, cell_t *dst) { return B_FALSE; } +int isdark(cell_t *c) { + switch (c->lit) { + case L_PERMDARK: + case L_NOTLIT: + return B_TRUE; + default: + break; + } + return B_FALSE; +} + int isdiggable(cell_t *c) { switch (c->type->id) { case CT_WALL: return B_TRUE; diff --git a/map.h b/map.h index 242252b..0173c09 100644 --- a/map.h +++ b/map.h @@ -43,6 +43,7 @@ object_t *hasenterableobject(cell_t *c); lifeform_t *haslf(cell_t *c); int hasobject(cell_t *c); int isadjacent(cell_t *src, cell_t *dst); +int isdark(cell_t *c); int isdiggable(cell_t *c); int isdoor(object_t *o, int *isopen); int isempty(cell_t *c); diff --git a/move.c b/move.c index b7839ad..ccf0bbf 100644 --- a/move.c +++ b/move.c @@ -169,12 +169,15 @@ int cellwalkable(lifeform_t *lf, cell_t *cell, enum ERROR *error) { rdata = NULL; } if (!cell) { - if (error) *error = E_WALLINWAY; + if (error) *error = E_OFFMAP; return B_FALSE; } if (cell->type->solid) { + // mover is noncorporeal? if (lf && lfhasflag(lf, F_NONCORPOREAL)) { // ok + } else if (cell->lf && (cell->lf != lf)) { // someone (else) in the wall? + // ok } else { if (error) *error = E_WALLINWAY; return B_FALSE; @@ -504,6 +507,7 @@ int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher) { // failed to move switch (reason) { case E_WALLINWAY: + case E_OFFMAP: msg("%s slam%s into a wall!",lfname,isplayer(lf) ? "" : "s"); losehp(lf, rnd(1,6), DT_BASH, pusher, "slamming into a wall"); // stop moving @@ -538,6 +542,8 @@ 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) { flag_t *f; @@ -558,6 +564,7 @@ void moveeffects(lifeform_t *lf) { } losehp(lf, roll(f->text), f->val[0], NULL, "extreme pain"); } + if (isdead(lf)) return; } @@ -685,7 +692,6 @@ int movelf(lifeform_t *lf, cell_t *newcell) { if ((gamemode == GM_GAMESTARTED)) { for (l = newcell->map->lf ; l ; l = l->next) { if (l != lf) { - // cope with swapping locations with someone! if (haslos(l, newcell)) { int dointerrupt = B_FALSE; @@ -700,6 +706,15 @@ int movelf(lifeform_t *lf, cell_t *newcell) { dointerrupt = B_TRUE; } } else { + if (isplayer(lf) && areallies(lf, l)) { + + // remember player's last known loc + f = lfhasflag(l, F_PETOF); + if (f) { + f->val[1] = player->cell->x; + f->val[2] = player->cell->y; + } + } dointerrupt = B_TRUE; } if (dointerrupt) { @@ -1239,6 +1254,14 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) { int door, dooropen; reason = errcode; switch (errcode) { + case E_OFFMAP: + if (isplayer(lf)) { + msg("You can't go any further in that direction."); + } else if (cansee(player, lf)) { + getlfname(lf, buf); + msg("%s %ss around randomly.", buf, getmoveverb(lf)); + } + break; case E_WALLINWAY: if (isplayer(lf)) { msg("Ouch! You %s into a wall.", getmoveverb(lf)); diff --git a/nexus.c b/nexus.c index 0209188..00486fe 100644 --- a/nexus.c +++ b/nexus.c @@ -67,6 +67,9 @@ extern int statdirty; int needredraw = B_TRUE; int numdraws = 0; +// for xp list debugging +extern race_t **raceposs; +extern int *xpposs; int main(int argc, char **argv) { int newworld = B_FALSE; @@ -125,6 +128,7 @@ int main(int argc, char **argv) { job_t *j = NULL; char ch; cell_t *where; + flag_t *f; // read from input file if required if (playerfile) { @@ -172,23 +176,50 @@ int main(int argc, char **argv) { addflag(player->flags, F_NAME, NA, NA, NA, "Anonymous"); } givejob(player, j->id); - + // special case: + 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"); + } + // read cheat info from player file if (playerfile) { if (parseplayerfile(playerfile, player)) { // error! exit(0); } fclose(playerfile); + // TODO: note that we're cheaing } - // player needs hunger addflag(player->flags, F_HUNGER, 0, NA, NA, NULL); + // pet / npc / follower + f = lfhasflag(player, F_HASPET); + if (f) { + cell_t *c; + race_t *r; + lifeform_t *pet; + r = findracebyname(f->text); + assert(r); + + // create it + c = getrandomadjcell(player->cell, WE_WALKABLE, B_ALLOWEXPAND); + assert(c); + pet = addlf(c, r->id, 1); + makefriendly(pet, PERMENANT); + // mark us as its master + if (lfhasflag(pet, F_ANIMAL) || lfhasflag(pet, F_INSECT)) { + addflag(pet->flags, F_PETOF, player->id, player->cell->x, player->cell->y, NULL); + } else { + addflag(pet->flags, F_ALLYOF, player->id, player->cell->x, player->cell->y, NULL); + } + } + getplayernamefull(pname); sprintf(welcomemsg, "Greetings %s, welcome to %snexus!", pname, newworld ? "the new " : ""); - // XXX testing - //addlf(getcellindir(player->cell, D_N), R_GOBLIN, 1); - // 00:00 - 23:59 curtime = rnd(0,86399); } else { @@ -360,6 +391,10 @@ void checkendgame(void) { } void cleanup(void) { + + free(xpposs); + free(raceposs); + fclose(logfile); cleanupgfx(); diff --git a/objects.c b/objects.c index 0e95a34..b52ad83 100644 --- a/objects.c +++ b/objects.c @@ -1805,25 +1805,26 @@ int curseob(object_t *o) { int rv = B_FALSE; lifeform_t *lf; - // announce lf = o->pile->owner; // announce - if (lf) { - if (cansee(player, lf)) { - char lfname[BUFLEN]; - char obname[BUFLEN]; - getlfname(lf, lfname); - getobname(o, obname,o->amt); - msg("A black aura surrounds %s%s %s.",lfname,getpossessive(lfname),noprefix(obname)); - } - } else { // not held - cell_t *loc = NULL; - loc = getoblocation(o); - if (haslos(player, loc)) { - char obname[BUFLEN]; - getobname(o, obname,o->amt); - msg("A black aura surrounds %s.",obname); + if (gamemode == GM_GAMESTARTED) { + if (lf) { + if (cansee(player, lf)) { + char lfname[BUFLEN]; + char obname[BUFLEN]; + getlfname(lf, lfname); + getobname(o, obname,o->amt); + msg("A black aura surrounds %s%s %s.",lfname,getpossessive(lfname),noprefix(obname)); + } + } else { // not held + cell_t *loc = NULL; + loc = getoblocation(o); + if (haslos(player, loc)) { + char obname[BUFLEN]; + getobname(o, obname,o->amt); + msg("A black aura surrounds %s.",obname); + } } } @@ -2581,7 +2582,6 @@ char *getdamname(enum DAMTYPE damtype) { case DT_BASH: return "bludgeoning"; case DT_BITE: return "bite"; case DT_CHOP: return "chopping"; - case DT_CLAW: return "claw"; case DT_COLD: return "cold"; case DT_CRUSH: return "crushing"; case DT_DIRECT: return "direct"; @@ -2619,7 +2619,6 @@ char *getdamnamenoun(enum DAMTYPE damtype) { case DT_POISONGAS: return "poison gas"; case DT_POISON: return "poison"; case DT_SLASH: return "slashing damage"; - case DT_CLAW: return "claw damage"; case DT_ELECTRIC: return "electricity"; case DT_EXPLOSIVE: return "explosives"; case DT_FIRE: return "fire"; @@ -3285,56 +3284,7 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan // detect magic - append [magic] if (lfhasflag(player, F_DETECTMAGIC)) { - int ismagic = B_FALSE; - if (hasunknownmod) { - ismagic = B_TRUE; - } - switch (o->type->obclass->id) { - case OC_SCROLL: - switch (o->type->id) { - case OT_MAP: - case OT_SCR_NOTHING: - // these scrolls are non-magical - break; - default: - ismagic = B_TRUE; - break; - } - break; - case OC_RING: - case OC_WAND: - // all rings/wands are magical - ismagic = B_TRUE; - break; - case OC_POTION: - switch (o->type->id) { - case OT_POT_ACID: - case OT_POT_OIL: - case OT_POT_WATER: - case OT_POT_BLOOD: - case OT_POT_JUICE: - // these potions are non-magical - break; - default: - ismagic = B_TRUE; - break; - } - break; - case OC_BOOK: - if (hasflag(o->flags, F_LINKSPELL)) { - // ie. spellbooks - ismagic = B_TRUE; - } - break; - default: - break; - } - if (hasflag(o->flags, F_ENCHANTABLE) && hasflag(o->flags, F_BONUS)) { - ismagic = B_TRUE; - } - - - if (ismagic) { + if (ismagical(o)) { strcat(buf, " [magic]"); } } @@ -3961,6 +3911,7 @@ 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"; @@ -4046,6 +3997,39 @@ int getthrowdam(object_t *o) { return (int)dam; } +enum BODYPART getweildloc(object_t *o, enum BODYPART *otherloc, int *twohanded) { + enum BODYPART weildloc; + if (o) { + if (hasflag(o->flags, F_FIREARM)) { + weildloc = BP_SECWEAPON; + } else { + weildloc = BP_WEAPON; + } + if (twohanded) { + if (hasflag(o->flags, F_TWOHANDED)) { + *twohanded = B_TRUE; + } else { + *twohanded = B_FALSE; + } + } + } else { + // ie. unarmed + weildloc = BP_WEAPON; + if (twohanded) *twohanded = B_FALSE; + } + + + if (otherloc) { + if (weildloc == BP_WEAPON) { + *otherloc = BP_SECWEAPON; + } else { + *otherloc = BP_WEAPON; + } + } + + return weildloc; +} + int hasedibleob(obpile_t *op) { object_t *o; for (o = op->first ; o ; o = o->next) { @@ -4391,7 +4375,7 @@ void initobjects(void) { addflag(lastobjectclass->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL); addflag(lastobjectclass->flags, F_OPERABLE, B_TRUE, NA, NA, NULL); addflag(lastobjectclass->flags, F_OPERUSECHARGE, B_TRUE, NA, NA, NULL); - addflag(lastobjectclass->flags, F_RNDCHARGES, 2, 12, NA, NULL); + addflag(lastobjectclass->flags, F_RNDCHARGES, 1, 8, NA, NULL); addoc(OC_POTION, "Potions", "A strange concoction contained within a small flask.", '!', C_GREY); addflag(lastobjectclass->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL); @@ -4949,6 +4933,13 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJSELF, NA, NA, NULL); /////////////////// + // elemental - earth + /////////////////// + // 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); + /////////////////// // gravity /////////////////// // l3 @@ -5165,7 +5156,6 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL); addflag(lastot->flags, F_NEEDSGRAB, B_TRUE, NA, NA, NULL); - addflag(lastot->flags, F_XPVAL, 30, NA, NA, NULL); addot(OT_A_GRAB, "grab", "You can grab hold of nearby enemies to prevent their escape.", MT_NOTHING, 0, OC_ABILITY); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL); @@ -5358,6 +5348,10 @@ void initobjects(void) { addflag(lastot->flags, F_LINKSPELL, OT_S_DARKNESS, NA, NA, NULL); addot(OT_SB_FREEZEOB, "spellbook of freezing touch", "Teaches the spell 'freezing touch'.", MT_PAPER, 1.5, OC_BOOK); addflag(lastot->flags, F_LINKSPELL, OT_S_FREEZEOB, NA, NA, NULL); + addot(OT_SB_COLDBURST, "spellbook of cold burst", "Teaches the spell 'cold burst'.", MT_PAPER, 1.5, OC_BOOK); + addflag(lastot->flags, F_LINKSPELL, OT_S_COLDBURST, NA, NA, NULL); + addot(OT_SB_DIG, "spellbook of dig", "Teaches the spell 'dig'.", MT_PAPER, 1.5, OC_BOOK); + addflag(lastot->flags, F_LINKSPELL, OT_S_DIG, NA, NA, NULL); 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); @@ -5416,15 +5410,46 @@ void initobjects(void) { // wands + addot(OT_WAND_KNOCK, "wand of opening", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); + addflag(lastot->flags, F_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_LINKSPELL, OT_S_LIGHT, 3, NA, NULL); + addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, NA, NA, NULL); + addot(OT_WAND_SLOW, "wand of slowness", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); + addflag(lastot->flags, F_LINKSPELL, OT_S_SLOW, NA, NA, NULL); + addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); + addot(OT_WAND_DIGGING, "wand of digging", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); + addflag(lastot->flags, F_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_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_DETONATION, "wand of detonation", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL); - addflag(lastot->flags, F_LINKSPELL, OT_S_DETONATE, NA, NA, NULL); - addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER|TT_DOOR, 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_LINKSPELL, OT_S_FIREDART, NA, NA, NULL); + addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); + addot(OT_WAND_HASTE, "wand of haste", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); + addflag(lastot->flags, F_LINKSPELL, OT_S_HASTE, NA, NA, NULL); + addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL); + addot(OT_WAND_WEAKNESS, "wand of enfeeblement", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); + addflag(lastot->flags, F_LINKSPELL, OT_S_WEAKEN, NA, NA, NULL); + addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); + addot(OT_WAND_WONDER, "wand of wonder", "Produces random effects.", MT_METAL, 0.5, OC_WAND); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); + addflag(lastot->flags, F_OPERNEEDTARGET, TT_NONE, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); addot(OT_WAND_INVIS, "wand of invisibility", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND); addflag(lastot->flags, F_RARITY, H_DUNGEON, 65, NA, NULL); @@ -5442,43 +5467,16 @@ void initobjects(void) { addflag(lastot->flags, F_LINKSPELL, OT_S_FIREBALL, NA, NA, NULL); addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); - addot(OT_WAND_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_LINKSPELL, OT_S_FIREDART, NA, NA, NULL); - addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, NA, NA, NULL); + addot(OT_WAND_DETONATION, "wand of detonation", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL); + addflag(lastot->flags, F_LINKSPELL, OT_S_DETONATE, NA, NA, NULL); + addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER|TT_DOOR, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); - addot(OT_WAND_HASTE, "wand of haste", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); - addflag(lastot->flags, F_LINKSPELL, OT_S_HASTE, NA, NA, NULL); - addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, NA, NA, NULL); - addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL); - addot(OT_WAND_KNOCK, "wand of opening", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); - addflag(lastot->flags, F_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_LINKSPELL, OT_S_LIGHT, 3, NA, NULL); - addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, NA, NA, NULL); addot(OT_WAND_POLYMORPH, "wand of polymorph", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND); addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL); addflag(lastot->flags, F_LINKSPELL, OT_S_POLYMORPH, NA, NA, NULL); addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); - addot(OT_WAND_SLOW, "wand of slowness", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); - addflag(lastot->flags, F_LINKSPELL, OT_S_SLOW, NA, NA, NULL); - addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, NA, NA, NULL); - addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); - addot(OT_WAND_WEAKNESS, "wand of enfeeblement", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); - addflag(lastot->flags, F_LINKSPELL, OT_S_WEAKEN, NA, NA, NULL); - addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, NA, NA, NULL); - addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); - addot(OT_WAND_WONDER, "wand of wonder", "Produces random effects.", MT_METAL, 0.5, OC_WAND); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); - addflag(lastot->flags, F_OPERNEEDTARGET, TT_NONE, NA, NA, NULL); - addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); // tools addot(OT_BLINDFOLD, "blindfold", "Short length of wide cloth, used for blocking eyesight.", MT_CLOTH, 0.01, OC_TOOLS); @@ -5887,8 +5885,9 @@ void initobjects(void) { addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_SLIPPERY, 1, NA, NA, NULL); addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "blood stain"); - addflag(lastot->flags, F_DIECONVERTTEXT, NA, NA, NA, "dries up"); - addflag(lastot->flags, F_DIECONVERTTEXTPL, NA, NA, NA, "dry up"); + //addflag(lastot->flags, F_DIECONVERTTEXT, NA, NA, NA, "dries up"); + //addflag(lastot->flags, F_DIECONVERTTEXTPL, NA, NA, NA, "dry up"); + addflag(lastot->flags, F_NODIECONVERTTEXT, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OBHP, 30, 30, NA, NULL); addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL); addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL); @@ -6200,6 +6199,11 @@ void initobjects(void) { addflag(lastot->flags, F_ARMOURRATING, 1, NA, NA, NULL); addflag(lastot->flags, F_EVASION, -5, NA, NA, NULL); addflag(lastot->flags, F_OBHP, 1, 1, NA, NULL); + addot(OT_PIRATEHAT, "tricorne", "A three cornered hat with a skull and crossbones emblem.", MT_CLOTH, 1, OC_ARMOUR); + addflag(lastot->flags, F_RARITY, H_ALL, 70, NA, NULL); + addflag(lastot->flags, F_GOESON, BP_HEAD, NA, NA, NULL); + addflag(lastot->flags, F_ARMOURRATING, 1, NA, NA, NULL); + addflag(lastot->flags, F_OBHP, 1, 1, NA, NULL); addot(OT_CAP, "cap", "Close-fitting headwear with a short shade visor at the front.", MT_CLOTH, 1, OC_ARMOUR); addflag(lastot->flags, F_RARITY, H_ALL, 80, NA, NULL); addflag(lastot->flags, F_GOESON, BP_HEAD, NA, NA, NULL); @@ -6251,6 +6255,10 @@ void initobjects(void) { addflag(lastot->flags, F_EQUIPCONFER, F_VISRANGEMOD, -4, NA, NULL); addflag(lastot->flags, F_TINTED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOQUALITY, B_TRUE, NA, NA, NULL); + addot(OT_EYEPATCH, "eyepatch", "A small patch of black material which covers one eye. Scary looking.", MT_CLOTH, 0.01, OC_ARMOUR); + addflag(lastot->flags, F_RARITY, H_ALL, 70, NA, NULL); + addflag(lastot->flags, F_GOESON, BP_EYES, NA, NA, NULL); + addflag(lastot->flags, F_NOQUALITY, B_TRUE, NA, NA, NULL); addot(OT_NVGOGGLES, "nightvis goggles", "Special goggles which allow the wear to see in the dark.", MT_METAL, 1.5, OC_ARMOUR); addflag(lastot->flags, F_RARITY, H_ALL, 25, NA, NULL); addflag(lastot->flags, F_GOESON, BP_EYES, NA, NA, NULL); @@ -6362,6 +6370,17 @@ void initobjects(void) { addflag(lastot->flags, F_USESSKILL, SK_UNARMED, NA, NA, NULL); addflag(lastot->flags, F_UNARMEDWEP, B_TRUE, NA, NA, NULL); + // this one if for the pirate + addot(OT_HOOKHAND, "hook", "hook", MT_METAL, 0, OC_WEAPON); + addflag(lastot->flags, F_DAM, DT_PIERCE, NA, NA, "1d4"); + addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL); + addflag(lastot->flags, F_USESSKILL, SK_UNARMED, NA, NA, NULL); + addflag(lastot->flags, F_UNARMEDWEP, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_ATTACKVERB, NA, 5, NA, "scratch"); + addflag(lastot->flags, F_ATTACKVERB, 6, 15, NA, "scrape"); + addflag(lastot->flags, F_ATTACKVERB, 16, NA, NA, "rake"); + + addot(OT_TEETH, "teeth", "teeth object", MT_BONE, 0, OC_WEAPON); addflag(lastot->flags, F_DAM, DT_BITE, NA, NA, "1d2"); addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL); @@ -6370,7 +6389,14 @@ void initobjects(void) { addflag(lastot->flags, F_UNARMEDWEP, B_TRUE, NA, NA, NULL); addot(OT_CLAWS, "claws", "claws object", MT_BONE, 0, OC_WEAPON); - addflag(lastot->flags, F_DAM, DT_CLAW, NA, NA, "1d2"); + addflag(lastot->flags, F_DAM, DT_SLASH, NA, NA, "1d2"); + addflag(lastot->flags, F_ATTACKVERB, NA, 5, NA, "scratch"); + addflag(lastot->flags, F_ATTACKVERB, 6, 15, NA, "claw"); + addflag(lastot->flags, F_ATTACKVERB, 16, 30, NA, "tear"); + addflag(lastot->flags, F_ATTACKVERB, 31, 40, NA, "rake"); + addflag(lastot->flags, F_ATTACKVERB, 41, 50, NA, "gouge"); + addflag(lastot->flags, F_ATTACKVERB, 51, NA, NA, "eviscerate"); + addflag(lastot->flags, F_KILLVERB, 70, NA, NA, "disembowel"); addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_NONE, NA, NA, NULL); addflag(lastot->flags, F_UNARMEDWEP, B_TRUE, NA, NA, NULL); @@ -6384,6 +6410,7 @@ void initobjects(void) { addflag(lastot->flags, F_UNARMEDWEP, B_TRUE, NA, NA, NULL); addot(OT_TAIL, "tail", "tail object", MT_FLESH, 0, OC_WEAPON); + addflag(lastot->flags, F_ATTACKVERB, NA, NA, NA, "tailslap"); addflag(lastot->flags, F_DAM, DT_BASH, NA, NA, "1d4"); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_NONE, NA, NA, NULL); @@ -6448,7 +6475,7 @@ void initobjects(void) { addflag(lastot->flags, F_MISSILEDAM, 3, NA, NA, ""); addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, ""); addflag(lastot->flags, F_NUMAPPEAR, 1, 3, NA, ""); - addflag(lastot->flags, F_OBHP, 5, 5, NA, ""); + addflag(lastot->flags, F_OBHP, 3, 3, NA, ""); addflag(lastot->flags, F_CANHAVEOBMOD, OM_POISONED, NA, NA, NULL); addot(OT_ARROW, "arrow", "A sharp wooden arrow.", MT_WOOD, 0.5, OC_MISSILE); @@ -6632,6 +6659,12 @@ void initobjects(void) { addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_LONGBLADES, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, ST_WEAK, NA, NULL); + addot(OT_CUTLASS, "cutlass", "An accuracte, light-weight pirate blade.", MT_METAL, 1, OC_WEAPON); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); + addflag(lastot->flags, F_DAM, DT_SLASH, NA, NA, "1d7"); + addflag(lastot->flags, F_ACCURACY, 90, NA, NA, NULL); + addflag(lastot->flags, F_USESSKILL, SK_LONGBLADES, NA, NA, NULL); + addflag(lastot->flags, F_ATTREQ, A_STR, ST_VWEAK, NA, NULL); // polearms addot(OT_GLAIVE, "glaive", "A long pole with a sharpened head.", MT_METAL, 4, OC_WEAPON); @@ -7017,6 +7050,12 @@ int isdangerousob(object_t *o, lifeform_t *lf, int onlyifknown) { } } } + + // undead won't touch blessed things - don't worry about + // onlyifknown, they can sense this. + if (hasflag(lf->flags, F_UNDEAD) && isblessed(o)) { + return B_TRUE; + } return B_FALSE; } @@ -7143,6 +7182,65 @@ int isimpassableob(object_t *o, lifeform_t *lf) { return B_FALSE; } +int ismagical(object_t *o) { + if (hasflag(o->flags, F_HASBRAND)) { + return B_TRUE; + } + switch (o->type->obclass->id) { + case OC_SCROLL: + switch (o->type->id) { + case OT_MAP: + case OT_SCR_NOTHING: + // these scrolls are non-magical + break; + default: + return B_TRUE; + break; + } + break; + case OC_RING: + case OC_WAND: + // all rings/wands are magical + return B_TRUE; + break; + case OC_POTION: + switch (o->type->id) { + case OT_POT_ACID: + case OT_POT_OIL: + case OT_POT_WATER: + case OT_POT_BLOOD: + case OT_POT_JUICE: + // these potions are non-magical + break; + default: + return B_TRUE; + break; + } + break; + case OC_BOOK: + if (hasflag(o->flags, F_LINKSPELL)) { + // ie. spellbooks + return B_TRUE; + } + break; + default: + break; + } + if (hasflag(o->flags, F_ENCHANTABLE) && hasflag(o->flags, F_BONUS)) { + return B_TRUE; + } + + return B_FALSE; +} + +int ismeleeweapon(object_t *o) { + if (hasflag(o->flags, F_DAM)) { + return B_TRUE; + } + return B_FALSE; +} + + int ismetal(enum MATERIAL mat) { int metal = B_FALSE; switch (mat) { @@ -7482,7 +7580,7 @@ lifeform_t *makeanimated(lifeform_t *lf, object_t *o, int level) { addflag(lf->flags, F_NODEATHANNOUNCE, B_TRUE, NA, NA, NULL); o = relinkob(o, newlf->pack); - weild(lf, o); + weild(newlf, o); f = hasflag(o->flags, F_OBHP); if (f) { @@ -7499,6 +7597,9 @@ lifeform_t *makeanimated(lifeform_t *lf, object_t *o, int level) { addflag(newlf->flags, F_MOVESPEED, newspeed, NA, NA, NULL); } } + if (newlf) { + addflag(newlf->flags, F_PETOF, lf->id, NA, NA, NULL); + } return newlf; } @@ -8132,8 +8233,12 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { sprintf(buf, "Where will you aim %s?",obname); where = askcoords(buf, ttype); if (!haslos(lf, where)) { - msg("You can't see there!"); - return B_TRUE; + // exception - wand of digging doesn't need los + if (isknown(o) && (o->type->id == OT_WAND_DIGGING)) { + } else { + msg("You can't see there!"); + return B_TRUE; + } } } if (!where) { @@ -8239,13 +8344,14 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { enum OBTYPE spelltocast; int power; - spelltocast = f->val[0]; power = f->val[1]; if (power == NA) power = 1; if (isblessed(o)) power += 4; + power += (getskill(lf, SK_MAGITEMUSAGE)*2); + // certain wands always used the blessed version of spells // certain wands have different effects when cursed switch (o->type->id) { @@ -10331,6 +10437,15 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed, } + if (youhit && lfhasflag(target, F_NONCORPOREAL)) { + youhit = B_FALSE; + willcatch = B_FALSE; + if (seen) { + msg("%s passes straight through %s.", obname, targetname); + announcedmiss = B_TRUE; + } + } + // if someone is there, they take damage and the object might die // this should be "if target && youhit" if (youhit) { @@ -10419,7 +10534,10 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed, announcedmiss = B_TRUE; } } - } else { // no target + } + + if (!target || !youhit) { + // will it shatter on the ground? if (willshatter(o->material->id)) { if (haslos(player, where)) { char *obcaps; @@ -10454,8 +10572,8 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed, addob(where->obpile, buf); } - // potion effects? - if (shattered) { + // potion effects (only if you hit)? + if (shattered && youhit) { if (o->type->obclass->id == OC_POTION) { int observed; // some potions have special effects... diff --git a/objects.h b/objects.h index afe5cf3..8af0e96 100644 --- a/objects.h +++ b/objects.h @@ -100,6 +100,7 @@ char *getschoolname(enum SPELLSCHOOL sch); int getshatterdam(object_t *o); enum SKILLLEVEL gettechlevel(object_t *o); int getthrowdam(object_t *o); +enum BODYPART getweildloc(object_t *o, enum BODYPART *otherloc, int *twohanded); int hasedibleob(obpile_t *op); object_t *hasknownob(obpile_t *op, enum OBTYPE oid); object_t *hasob(obpile_t *op, enum OBTYPE oid); @@ -132,6 +133,8 @@ int isknown(object_t *o); int isknownot(objecttype_t *ot); int isidentified(object_t *o); int isimpassableob(object_t *o, lifeform_t *lf); +int ismagical(object_t *o); +int ismeleeweapon(object_t *o); int ismetal(enum MATERIAL mat); int isthrowmissile(object_t *o); int isoperable(object_t *o); diff --git a/spell.c b/spell.c index 346487f..6e439b0 100644 --- a/spell.c +++ b/spell.c @@ -27,6 +27,8 @@ extern WINDOW *msgwin; extern job_t *firstjob; +extern enum ERROR reason; + int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifeform_t *target, flag_t *cwflag) { char username[BUFLEN]; char killername[BUFLEN]; @@ -255,9 +257,15 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef } } else { int str; - // determine damage baesd on crusher's strength - str = getattr(user, A_STR); - dam = modifybystat((str/2), user, A_STR); + + // fixed damage? + if (strlen(damstr)) { + dam = roll(damstr); + } else { + // determine damage baesd on crusher's strength + str = getattr(user, A_STR); + dam = modifybystat((str/2), user, A_STR); + } // announce if (cansee(player, target)) { @@ -450,7 +458,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef } // this call will also remove this ability... - setrace(user, f->val[0]); + setrace(user, f->val[0], B_TRUE); } else if (abilid == OT_A_LEARN) { skill_t *sk; @@ -502,23 +510,8 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef } else if (abilid == OT_A_DEBUG) { cell_t *where; where = askcoords("Debug who?", TT_MONSTER); - if (where) { - lifeform_t *victim; - victim = where->lf; - if (victim) { - char lfname[BUFLEN]; - flag_t *f; - getlfname(victim, lfname); - - f = hasflag(victim->flags, F_DEBUG); - if (f) { - killflag(f); - msg("%s - debugging is DISABLED.", lfname); - } else { - addflag(victim->flags, F_DEBUG, B_TRUE, NA, NA, NULL); - msg("%s - debugging is ON.", lfname); - } - } + if (where && where->lf) { + debug(where->lf); } } else if (abilid == OT_A_EMPLOY) { cell_t *where; @@ -1083,6 +1076,32 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } getlfname(target, targetname); + // only animals/humanoids + if (!lfhasflag(target, F_ANIMAL) && !lfhasflag(target, F_HUMANOID)) { + if (isplayer(caster)) { + msg("%s%s mind is too alien for you to charm.",targetname,getpossessive(targetname)); + } + return B_FALSE; + } + + if (!ischarmable(target)) { + if (isplayer(caster)) { + switch (reason) { + 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 possession."); + break; + default: + msg("You cannot possesss %s.", targetname); + break; + } + } + return B_FALSE; + } + + if (getallegiance(caster) == AL_PEACEFUL) { fizzle(caster); return B_FALSE; @@ -1099,6 +1118,10 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ msg("%s resists.",targetname); if (seenbyplayer) *seenbyplayer = B_TRUE; } + // they get angry! + if (!isplayer(target) && cansee(target, caster)) { + fightback(target, caster); + } } else { int howlong; if (isplayer(caster) || cansee(player, target)) { @@ -1332,6 +1355,38 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } else { // monsters can't use this } + } else if (spellid == OT_S_DIG) { + int numseen = 0; + int maxrange; + cell_t *retcell[MAXRETCELLS]; + int nretcell,i; + + // don't need line of fire OR sight! + if (!validatespellcell(caster, &targcell, TT_NONE, B_FALSE, LOF_DONTNEED, spellid, power)) return B_TRUE; + + // calculate a line from caster to the target cell + calcbresnham(caster->cell->map, caster->cell->x, caster->cell->y, + targcell->x, targcell->y, retcell, &nretcell); + + maxrange = power; + + // get rid of rock in the cells... + for (i = 0; i < nretcell && (i <= maxrange); i++) { + if (retcell[i]->type->solid) { + setcelltype(retcell[i], getemptycelltype(retcell[i]->map->habitat)); + if (haslos(player, retcell[i])) numseen++; + } + } + + + // announce if any seen + if (numseen) { + msg("The wall%s crumble%s to dust!", + (numseen == 1) ? "" : "s", + (numseen == 1) ? "s" : "" + ); + if (seenbyplayer) *seenbyplayer = B_TRUE; + } } else if (spellid == OT_S_DETECTLIFE) { target = caster; if (isplayer(caster)) { @@ -1940,7 +1995,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ addflag(target->flags, F_ORIGRACE, target->race->id, NA, NA, NULL); // polymorph is always will be temporary addtempflag(target->flags, F_POLYMORPHED, B_TRUE, NA, NA, NULL, 10); - setrace(target, R_GASCLOUD); + setrace(target, R_GASCLOUD, B_TRUE); } } else if (spellid == OT_S_HASTE) { int howlong = 15; @@ -2527,8 +2582,26 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } + // charmable? + if (!ischarmable(target)) { + if (isplayer(caster)) { + switch (reason) { + case E_LOWIQ: + msg("%s%s intellect is too simple for you to possess.",targname,getpossessive(targname)); + break; + case E_UNDEAD: + msg("The undead are immune to possession."); + break; + default: + msg("You cannot possesss %s.", targname); + break; + } + } + return B_FALSE; + } + // saving throw.... - if (skillcheck(target, SC_RESISTMAG, 20 + power*2, 0)) { + if (skillcheck(target, SC_RESISTMAG, 16 + power*2, 0)) { if (isplayer(caster) && cansee(player, target)) { msg("%s%s mind fights off your intrusion!", targname, getpossessive(targname)); } @@ -2545,6 +2618,10 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } + + // remove 'become a ghost' flag fro mcaster + killflagsofid(caster->flags, F_RISEASGHOST); + // possess! if (isplayer(caster)) { // player name @@ -2556,7 +2633,13 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ player->controller = C_AI; player = target; target->controller = C_PLAYER; - + // now kill the caster! + die(caster); + // if they survived somehow... + if (!isdead(caster)) { + // ... they will be hostile! + fightback(caster, player); + } } else { switch (getallegiance(caster)) { case AL_HOSTILE: @@ -2571,10 +2654,10 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ makefriendly(target, PERMENANT); break; } + // now kill the caster! + die(caster); } - // now kill the caster! - die(caster); } else if (spellid == OT_S_PSYARMOUR) { flag_t *f; // always targetted at caster @@ -2836,7 +2919,12 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ int willannounce = B_FALSE; char targname[BUFLEN]; - if (!validatespellcell(caster, &targcell,TT_MONSTER, B_TRUE, LOF_DONTNEED, spellid, power)) return B_TRUE; + // special case for ghosts... + if (caster->race->id == R_GHOST) { + targcell = caster->cell; + } else { + if (!validatespellcell(caster, &targcell,TT_MONSTER, B_TRUE, LOF_DONTNEED, spellid, power)) return B_TRUE; + } target = targcell->lf; if (!target) { @@ -3104,26 +3192,21 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ // make sure race is valid: // - can't turn into monsters which aren't randomly generated. // - can't turn into unique monsters - if (r && !appearsrandomly(r->id)) { - r = NULL; - } - } else { + // - can't turn into undead monsters + if (r && !canpolymorphto(r->id)) r = NULL; + } else { // random if (isplayer(target) && lfhasflag(target, F_CONTROL)) { askstring("What will you become", '?', buf, BUFLEN, NULL); r = findracebyname(buf); // make sure race is valid: - // - can't turn into monsters which aren't randomly generated. - // - can't turn into unique monsters - if (r && !appearsrandomly(r->id)) { - r = NULL; - } + if (r && !canpolymorphto(r->id)) r = NULL; } if (!r) { // random race, but not the same! r = target->race; - while (r == target->race) { + while ((r == target->race) || !canpolymorphto(r->id)) { r = getrandomrace(NULL, 0); } } @@ -3156,7 +3239,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ // become the new race! - setrace(target, r->id); + setrace(target, r->id, B_TRUE); // if someone cast the spell at themself, they can change back at will. if (target == caster) { @@ -3643,6 +3726,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_FIRE: return SK_SS_FIRE; case SS_ICE: @@ -3876,6 +3961,7 @@ int getspellrange(enum OBTYPE spellid, int power) { case OT_S_BURNINGWAVE: // base range for this spell is 3 range += (power/3); + break; default: break; }