diff --git a/ai.c b/ai.c index d6e8057..2f84912 100644 --- a/ai.c +++ b/ai.c @@ -63,6 +63,7 @@ void aiattack(lifeform_t *lf, lifeform_t *victim, int timelimit) { if (!hasflag(lf->flags, F_HOSTILE)) { addflag(lf->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); } + killflagsofid(lf->flags, F_FRIENDLY); } } @@ -274,6 +275,7 @@ void aigoto(lifeform_t *lf, cell_t *c, int timelimit) { void aimove(lifeform_t *lf) { int db = B_FALSE; object_t *curwep,*bestwep, *o; + int icanattack = B_FALSE; object_t *curgun,*bestgun; flag_t *f; //flag_t *nextf; @@ -282,10 +284,6 @@ void aimove(lifeform_t *lf) { enum BODYPART bp; int x,y; cell_t *c; - obpile_t *unarmedpile = NULL; - flag_t *unarmedflag = NULL; - - /* if (wantdb && haslos(player, lf->cell)) { @@ -365,8 +363,9 @@ void aimove(lifeform_t *lf) { // now check whetehr we have ANY weapon - curwep = getattackwep(lf, &unarmedpile, &unarmedflag); - if (unarmedpile) killobpile(unarmedpile); + if (curwep || lfhasflag(lf, F_HASATTACK)) { + icanattack = B_TRUE; + } // before attacking targets, // look for any object which we _covet_. @@ -562,7 +561,7 @@ void aimove(lifeform_t *lf) { } // do we have a valid melee attack? - if (!curwep) { + if (!icanattack) { if (db) dblog(".oO { won't move towards target - i have no weapon. }"); goingtomove = B_FALSE; } @@ -669,7 +668,7 @@ void aimove(lifeform_t *lf) { // then move towards them... if (db) dblog(".oO { moving towards my new target }"); - if (curwep) { + if (icanattack) { if (!movetowards(lf, c, DT_ORTH)) return; } else { if (db) dblog(".oO { won't move towards target - i have no weapon. }"); diff --git a/attack.c b/attack.c index d6bd84f..cda5e67 100644 --- a/attack.c +++ b/attack.c @@ -97,24 +97,151 @@ void applyarmourdamreduction(lifeform_t *lf, object_t *wep, int reduceamt, int * int attackcell(lifeform_t *lf, cell_t *c) { + int validwep[MAXCANDIDATES]; + object_t *wep[MAXCANDIDATES]; + flag_t *damflag[MAXCANDIDATES], *f; + obpile_t *op = NULL; + enum { + AT_NONE = 0, + AT_LF = 1, + AT_OB = 2, + } attacktype = AT_NONE; + void *attacktarget; + int nweps = 0; + int i; + int attacktime; + int gotweapon = B_FALSE; + // anyone there? if so just attack. if (c->lf) { - attacklf(lf, c->lf); + if (isplayer(lf) && !areenemies(lf,c->lf)) { + char ch; + char victimname[BUFLEN]; + char buf[BUFLEN]; + getlfname(c->lf, victimname); + switch (getallegiance(c->lf)) { + case AL_PEACEFUL: + sprintf(buf, "Really attack the peaceful %s?",noprefix(victimname)); + break; + case AL_FRIENDLY: + sprintf(buf, "Really attack the allied %s?",noprefix(victimname)); + break; + default: + sprintf(buf, "Really attack the allied %s?",noprefix(victimname)); + break; + } + ch = askchar(buf, "yn","n", B_TRUE); + if (ch == 'n') { + // cancel. + return B_TRUE; + } + } + + attacktype = AT_LF; + attacktarget = c->lf; } else { object_t *o; - // has an mpassable object? + // has an impassable object? o = hasobwithflag(c->obpile, F_IMPASSABLE); if (o) { - attackob(lf, o); + attacktype = AT_OB; + attacktarget = o; } else { // TODO: attack wall? return B_TRUE; } } + + // first use our weapon... + wep[0] = getweapon(lf); + if (wep[0]) { + damflag[0] = hasflag(wep[0]->flags, F_DAM); + validwep[0] = B_TRUE; + nweps++; + gotweapon = B_TRUE; + } + + // then use all our innate attacks.. + for (f = lf->flags->first ; f; f = f->next) { + if (f->id == F_HASATTACK) { + objecttype_t *ot; + + if (!op) { + op = addobpile(NULL, NULL); + } + + ot = findot(f->val[0]); + if (ot) { + wep[nweps] = addob(op, ot->name); + validwep[nweps] = B_TRUE; + damflag[nweps] = f; + nweps++; + } + } + } + + // take time + attacktime = getattackspeed(lf); + taketime(lf, attacktime); + + // 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)) { + 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]; + int nvalid; + + nvalid = 0; + for (i = 0; i < nweps; i++) { + if (validwep[i]) nvalid++; + } + + while (nvalid > max) { + int sel; + // mark a random one as invalid + sel = rnd(0,nweps-1); + while (!validwep[sel]) { + sel = rnd(0,nweps-1); + } + validwep[sel] = B_FALSE; + + // re-count... + nvalid = 0; + for (i = 0; i < nweps; i++) { + if (validwep[i]) nvalid++; + } + } + } + + for (i = 0; i < nweps; i++) { + if (validwep[i]) { + if (attacktype == AT_LF) { + attacklf(lf, (lifeform_t *)attacktarget, wep[i], damflag[i]); + } else if (attacktype == AT_OB) { + attackob(lf, (object_t *)attacktarget, wep[i], damflag[i]); + } + } + } + + // now kill all temp obs + if (op) { + killobpile(op); + } return B_FALSE; } -int attacklf(lifeform_t *lf, lifeform_t *victim) { +int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) { int dam[100]; enum DAMTYPE damtype[100]; int ndam = 0; @@ -123,10 +250,6 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) { char victimname[BUFLEN]; int fatal = B_FALSE; int firstisbackstab = B_FALSE; - flag_t *unarmedflag = NULL; - object_t *wep; - obpile_t *op = NULL; - int attacktime; int hit = B_FALSE; int critical = 0; char wepname[BUFLEN]; @@ -134,6 +257,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) { //int ev; int i; int willheal = B_FALSE; + int isunarmed = B_FALSE; int aidb = B_FALSE; @@ -142,6 +266,10 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) { aidb = B_TRUE; } + if (hasflag(wep->flags, F_UNARMEDWEP)) { + isunarmed = B_TRUE; + } + moveeffects(lf); if (isdead(lf)) { @@ -161,54 +289,16 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) { getlfname(victim, victimname); } - if (isplayer(lf) && !areenemies(lf,victim)) { - char ch; - switch (getallegiance(victim)) { - case AL_PEACEFUL: - sprintf(buf, "Really attack the peaceful %s?",noprefix(victimname)); - break; - case AL_FRIENDLY: - sprintf(buf, "Really attack the allied %s?",noprefix(victimname)); - break; - default: - sprintf(buf, "Really attack the allied %s?",noprefix(victimname)); - break; - } - ch = askchar(buf, "yn","n", B_TRUE); - if (ch == 'n') { - // cancel. - return B_TRUE; - } - } if (aidb) dblog(".oO { trying to attack %s }", victimname); - // get weapon - //wep = getweapon(lf); - wep = getattackwep(lf, &op, &unarmedflag); - if (!wep) { - if (isplayer(lf)) { - msg("You cannot attack!"); - } else if (cansee(player, lf)) { - //msg("%s looks like it wants to attack!",attackername); - } - if (op) killobpile(op); - return B_TRUE; - } - - getobname(wep, wepname, 1); - if (aidb) dblog(".oO { my weapon is %s %s }", wepname, unarmedflag ? "(unarmed)" : ""); - - // depends on weapon, race attackspeed modifier flag, etc - attacktime = getattackspeed(lf); - - taketime(lf, attacktime); + if (aidb) dblog(".oO { my weapon is %s }", wepname); // did you hit? ndam = 0; - if (rolltohit(lf, victim, &critical)) { + if (rolltohit(lf, victim, wep, &critical)) { int n; hit = B_TRUE; if (aidb) dblog(".oO { i hit! }"); @@ -233,9 +323,6 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) { msg("%s drops to the ground.", buf); } } - if (op) { - killobpile(op); - } return B_FALSE; } } @@ -244,19 +331,9 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) { // determine base damage // determine damage - //if (unarmed && (unarmedflag->val[0] != NA)) { - // ie. if critical is 0, do this once. - // if critical is 1, do this twice. - // etc. dam[0] = 0; for (n = 0; n < critical+1; n++) { - if (unarmedflag) { - // this mosnter's unarmed attack will - // override normal damage calculation - dam[0] += getdamrollfromflag(unarmedflag); - } else { - dam[0] += getdamroll(wep, victim); - } + dam[0] += getdamroll(wep, victim, damflag); } if (aidb) dblog("rolled dam[%d] = %d",0,dam[0]); @@ -416,7 +493,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) { strcpy(buf, attackername); capitalise(buf); - if (wep && !unarmedflag && (lf->race->id != R_DANCINGWEAPON) && cansee(player, lf)) { + if (wep && !isunarmed && (lf->race->id != R_DANCINGWEAPON) && cansee(player, lf)) { sprintf(withwep, " with %s", wepname); } else { strcpy(withwep, ""); @@ -451,7 +528,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) { real_getlfname(lf, attackername2, B_FALSE); // victim loses hp // don't adjust damage - we've already done that - if (wep && !unarmedflag) { + if (wep && !isunarmed) { char wepname[BUFLEN]; getobname(wep, wepname, 1); sprintf(buf, "%s^%s %s",attackername2, @@ -471,10 +548,10 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) { } // end foreach damtype // special weapon effects - wepeffects(wep->flags, victim->cell, dam[0]); + wepeffects(wep->flags, victim->cell, damflag, dam[0]); if (!isdead(victim)) { - if (unarmedflag) { + if (isunarmed) { f = lfhasflag(lf, F_FREEZINGTOUCH); if (f) { // victim turns to ice for a while! @@ -522,7 +599,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) { } // confer flags from attacker? - wepeffects(lf->flags, victim->cell, dam[0]); + wepeffects(lf->flags, victim->cell, damflag, dam[0]); // special lifeform-based effects if ((lf->race->id == R_COCKATRICE) && dam[0]) { @@ -595,12 +672,6 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) { } } - // get rid of temp unarmed object pile - if (op) { - killobpile(op); - } - - // induction of fear? if (!isdead(victim)) { if (lfhasflag(victim, F_INDUCEFEAR)) { @@ -612,19 +683,15 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) { return B_FALSE; } -int attackob(lifeform_t *lf, object_t *o) { +int attackob(lifeform_t *lf, object_t *o, object_t *wep, flag_t *damflag) { int dam[100]; enum DAMTYPE damtype[100]; int ndam = 0; char attackername[BUFLEN]; char obname[BUFLEN]; flag_t *f; - flag_t *unarmedflag = NULL; - object_t *wep; - obpile_t *op = NULL; + int isunarmed = B_FALSE; cell_t *obloc = NULL; - int attacktime; - int unarmed = B_FALSE; char wepname[BUFLEN]; int i; //int aidb = B_TRUE; @@ -646,41 +713,15 @@ int attackob(lifeform_t *lf, object_t *o) { maxhp = 1; } - // get weapon - wep = getattackwep(lf, &op, &unarmedflag); - if (!wep) { - if (isplayer(lf)) { - msg("You cannot attack!"); - } else if (cansee(player, lf)) { - //msg("%s looks like it wants to attack!",attackername); - } - if (!isplayer(lf)) { - // if ai, take some time to avoid infinite loops! - taketime(lf, getactspeed(lf)); - } - if (op) killobpile(op); - return B_TRUE; - } - getobname(wep, wepname, 1); - // depends on weapon, race attackspeed modifier flag, etc - attacktime = getattackspeed(lf); - - taketime(lf, attacktime); // don't need to figure out accuracy - we always hit. // determine damage ndam = 0; //if (unarmedflag && (unarmedflag->val[0] != NA)) { - if (unarmedflag) { - // this mosnter's unarmed attack will - // override normal damage calculation - dam[ndam] = getdamrollfromflag(unarmedflag); - } else { - dam[ndam] = getdamroll(wep, NULL); - } + dam[ndam] = getdamroll(wep, NULL, damflag); // modify for strength if (!hasflag(wep->flags, F_NOSTRDAMMOD) && !lfhasflag(lf, F_NOSTRDAMMOD)) { @@ -712,7 +753,7 @@ int attackob(lifeform_t *lf, object_t *o) { } else if (cansee(player, lf)) { char withwep[BUFLEN]; - if (wep && !unarmed && !isblind(player)) { // announce weapon used + if (wep && !isunarmed && !isblind(player)) { // announce weapon used sprintf(withwep, " with %s", wepname); } else { strcpy(withwep, ""); @@ -724,7 +765,7 @@ int attackob(lifeform_t *lf, object_t *o) { noise(lf->cell, NULL, "sounds of fighting.", NULL); } - if ((i == 0) && unarmedflag && hasflag(o->flags, F_HARD)) { + if ((i == 0) && (wep->type->id == OT_FISTS) && hasflag(o->flags, F_HARD)) { char buf[BUFLEN]; sprintf(buf, "punching %s", obname); if ( losehp(lf, 1, DT_BASH, lf, buf)) { @@ -740,9 +781,9 @@ int attackob(lifeform_t *lf, object_t *o) { } // end foreach damtype // special weapon effects - wepeffects(wep->flags, obloc, dam[0]); + wepeffects(wep->flags, obloc, damflag, dam[0]); - if (unarmedflag) { + if (isunarmed) { // touch effects touch(lf, o); } else { @@ -760,12 +801,6 @@ int attackob(lifeform_t *lf, object_t *o) { } } - - // get rid of temp unarmed object pile - if (op) { - killobpile(op); - } - return B_FALSE; } @@ -943,6 +978,7 @@ char *getattackverb(lifeform_t *lf, object_t *wep, enum DAMTYPE damtype, int dam return "hit"; } +/* object_t *getattackwep(lifeform_t *lf, obpile_t **unarmedpile, flag_t **unarmedflag) { object_t *wep; @@ -959,12 +995,13 @@ object_t *getattackwep(lifeform_t *lf, obpile_t **unarmedpile, flag_t **unarmedf } return wep; } +*/ enum DAMTYPE getdamtype(object_t *wep) { flag_t *f; enum DAMTYPE dt = DT_NONE; - f = hasflag(wep->flags, F_DAMTYPE); + f = hasflag(wep->flags, F_DAM); if (f) { dt = f->val[0]; } else { @@ -1078,20 +1115,12 @@ char *getkillverb(lifeform_t *victim, enum DAMTYPE damtype, int dam, int maxhp) -void getdamrange(flagpile_t *fp, int *min, int *max) { +void getdamrange(flag_t *f, int *min, int *max) { int mindam,maxdam; - flag_t *f; - f = hasflag(fp, F_DAM); if (f) { int mod,ndice,sides; - ndice = f->val[0]; - sides = f->val[1]; - if (f->val[2] == NA) { - mod = 0; - } else { - mod = f->val[2]; - } + texttodice(f->text, &ndice,&sides,&mod); mindam = (ndice * 1) + mod; maxdam = (ndice * sides) + mod; @@ -1104,71 +1133,68 @@ void getdamrange(flagpile_t *fp, int *min, int *max) { if (max) *max = maxdam; } +/* void getdamrangeunarmed(flag_t *f, int *min, int *max) { - obpile_t *op; - object_t *o; - op = addobpile(NULL, NULL); - o = addob(op, f->text); - if (o) { + obpile_t *op = NULL; + object_t *o = NULL; + flag_t *damflag = NULL; + + if (strlen(f->text)) { + damflag = f; + } else { + objecttype_t *ot; + ot = findot(f->val[0]); + op = addobpile(NULL, NULL); + // create the fake weapon + o = addob(op, ot->name); + if (o) { + damflag = hasflag(o->flags, F_DAM); + } + } + + + if (damflag) { int ndice,nsides,mod; - flag_t *damflag; - - damflag = hasflag(o->flags, F_DAM); - - if (f->val[0] == NA) { - ndice = damflag->val[0]; - } else { - ndice = f->val[0]; - } - if (f->val[1] == NA) { - nsides = damflag->val[1]; - } else { - nsides = f->val[1]; - } - if (f->val[2] == NA) { - if (damflag->val[2] != NA) { - mod = damflag->val[2]; - } else { - mod = 0; - } - } else { - mod = f->val[2]; - } + texttodice(damflag->text, &ndice, &nsides, &mod); if (min) *min = (ndice * 1) + mod; if (max) *max = (ndice * nsides) + mod; - - killob(o); } else { if (min) *min = 0; if (max) *max = 0; } - free(op); + + if (o) { + killob(o); + } + if (op) { + free(op); + } } +*/ // roll for damage -int getdamroll(object_t *o, lifeform_t *victim) { +int getdamroll(object_t *o, lifeform_t *victim, flag_t *damflag) { int dam; int bonusdam = 0; flag_t *f; - f = hasflag(o->flags, F_DAM); - if (f) { - dam = getdamrollfromflag(f); + + if (damflag) { + dam = roll(damflag->text); if (isblessed(o)) { int dam2; // blessed weapons get two rolls, and take the best - dam2 = getdamrollfromflag(f); + dam2 = roll(damflag->text); if (dam2 > dam) dam = dam2; } else if (iscursed(o)) { int dam2; // cursed weapons get two rolls, and take the worst - dam2 = getdamrollfromflag(f); + dam2 = roll(damflag->text); if (dam2 < dam) dam = dam2; } - } else { - // TODO wepaon does bashing damage based on weight + // TODO weapon does bashing damage based on weight dam = rnd(1,2); } @@ -1206,55 +1232,31 @@ float getdamreducepct(float armourrating) { return reducepct; } -int getdamrollfromflag(flag_t *f) { - objecttype_t *ot; +/* +int getunarmeddamroll(flag_t *f) { int dam; - int ndice, sides, mod; flag_t *damflag = NULL; - ot = findotn(f->text); - if (ot) { + + if (f->text) { + // take damage from unarmed flag + damflag = f; + } else { + // take damage from wep type + objecttype_t *ot; + ot = findot(f->val[0]); + assert(ot); damflag = hasflag(ot->flags, F_DAM); } - // how many dice? - ndice = f->val[0]; - if (ndice == NA) { - // get it from weapon definition - if (damflag && (damflag->val[0] != NA)) { - ndice = damflag->val[0]; - } else { - ndice = 1; - } - } - - sides = f->val[1]; - if (sides == NA) { - // get it from weapon definition - if (damflag && (damflag->val[1] != NA)) { - sides = damflag->val[1]; - } else { - sides = 1; - } - } - - mod = f->val[2]; - if (mod == NA) { - // get it from weapon definition - if (damflag && (damflag->val[2] != NA)) { - mod = damflag->val[2]; - } else { - mod = 0; - } - } - - dam = rolldie(ndice, sides) + mod; + dam = roll(damflag->text); assert(dam < 1000); assert(dam >= 0); return dam; } +*/ // returns a multiplier @@ -1299,6 +1301,7 @@ float getstrdammod(lifeform_t *lf) { // determine attack type for lifeform. // allocate a pile and add weapon to it. // return the pile. remember to free it! +/* obpile_t *getunarmedweapon(lifeform_t *lf,flag_t **uflag) { int nposs; flag_t *f; @@ -1331,6 +1334,7 @@ obpile_t *getunarmedweapon(lifeform_t *lf,flag_t **uflag) { } return op; } +*/ int isphysicaldam(enum DAMTYPE damtype) { switch (damtype) { @@ -1356,10 +1360,8 @@ int isphysicaldam(enum DAMTYPE damtype) { return B_FALSE; } -int rolltohit(lifeform_t *lf, lifeform_t *victim, int *critical) { +int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical) { int acc,ev; - object_t *wep; - obpile_t *op = NULL; int gothit; enum LFSIZE szlf,szvictim; @@ -1367,8 +1369,7 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, int *critical) { *critical = 0; } - acc = getlfaccuracy(lf); - wep = getattackwep(lf, &op, NULL); + acc = getlfaccuracy(lf, wep); // modify for defender's evasion ev = getevasion(victim); @@ -1422,11 +1423,10 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, int *critical) { } - if (op) killobpile(op); return gothit; } -void wepeffects(flagpile_t *fp, cell_t *where, int dam) { +void wepeffects(flagpile_t *fp, cell_t *where, flag_t *damflag, int dam) { flag_t *f; lifeform_t *victim; lifeform_t *owner; @@ -1471,7 +1471,7 @@ void wepeffects(flagpile_t *fp, cell_t *where, int dam) { dampct = (ratio * 100); // ie. lower hp% = higher dampct if (dampct >= 50) { - getdamrange(wep->flags, NULL, &maxdam); + getdamrange(damflag, NULL, &maxdam); extradam = (int)(dampct * (float)maxdam); if (extradam > 0) { char buf[BUFLEN]; diff --git a/attack.h b/attack.h index eecc6f7..efa30ce 100644 --- a/attack.h +++ b/attack.h @@ -3,23 +3,23 @@ int applyarmourdamage(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damtype); void applyarmourdamreduction(lifeform_t *lf, object_t *wep, int reduceamt, int *dam, enum DAMTYPE damtype); int attackcell(lifeform_t *lf, cell_t *c); -int attacklf(lifeform_t *lf, lifeform_t *victim); -int attackob(lifeform_t *lf, object_t *o); +int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag); +int attackob(lifeform_t *lf, object_t *o, object_t *wep, flag_t *damflag); void confereffects(flagpile_t *fp, lifeform_t *victim); int getarmourdamreduction(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damtype); char *getattackverb(lifeform_t *lf, object_t *wep, enum DAMTYPE damtype, int dam, int maxhp); -object_t *getattackwep(lifeform_t *lf, obpile_t **unarmedpile, flag_t **unarmedflag); +//object_t *getattackwep(lifeform_t *lf, obpile_t **unarmedpile, flag_t **unarmedflag); 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); -void getdamrange(flagpile_t *fp, int *min, int *max); -void getdamrangeunarmed(flag_t *f, int *min, int *max); +void getdamrange(flag_t *f, int *min, int *max); +//void getdamrangeunarmed(flag_t *f, int *min, int *max); float getdamreducepct(float armourrating); -int getdamroll(object_t *o, lifeform_t *victim); -int getdamrollfromflag(flag_t *f); +int getdamroll(object_t *o, lifeform_t *victim, flag_t *damflag); +//int getunarmeddamroll(flag_t *f); float getstrdammod(lifeform_t *lf); -obpile_t *getunarmedweapon(lifeform_t *lf, flag_t **uflag); +//obpile_t *getunarmedweapon(lifeform_t *lf, flag_t **uflag); int isphysicaldam(enum DAMTYPE damtype); -int rolltohit(lifeform_t *lf, lifeform_t *victim, int *critical); -void wepeffects(flagpile_t *fp, cell_t *where, int dam); +int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical); +void wepeffects(flagpile_t *fp, cell_t *where, flag_t *damflag, int dam); diff --git a/defs.h b/defs.h index 60a004f..6c4760f 100644 --- a/defs.h +++ b/defs.h @@ -676,6 +676,7 @@ enum OBTYPE { OT_SCR_TURNUNDEAD, OT_SCR_WISH, // BOOKS + OT_MAN_ARMOUR, OT_MAN_ATHLETICS, OT_MAN_BACKSTAB, OT_MAN_FIRSTAID, @@ -876,8 +877,11 @@ enum OBTYPE { OT_A_EMPLOY, OT_A_HEAVYBLOW, OT_A_INSPECT, + OT_A_HURRICANESTRIKE, OT_A_POLYREVERT, OT_A_STINGACID, // need to define dam in f_canwill + OT_A_WARCRY, // uses F_NOISETEXT -> N_WARCRY if it is there. + // otherwise 'shouts a blood-curdling war cry' // wands OT_WAND_COLD, OT_WAND_DETONATION, @@ -1011,6 +1015,7 @@ enum OBTYPE { OT_RING_MIRACLES, OT_RING_MPREGEN, OT_RING_PROTFIRE, + OT_RING_PROTCOLD, OT_RING_REGENERATION, OT_RING_RESISTMAG, OT_RING_SIGHT, @@ -1119,6 +1124,7 @@ enum NOISETYPE { N_GETANGRY, N_WALK, N_FLY, + N_WARCRY, }; enum LFSIZE { @@ -1238,10 +1244,13 @@ enum FLAG { F_LOCKED,// door is locked F_JAMMED, // is this door jammed? // stairs / teleporters / portals - F_CLIMBABLE, // this is a stiarcase - F_STAIRDIR, // val0 = direcion + F_CLIMBABLE, // this is a stiarcase, v0 = up/down + //F_STAIRDIR//, // val0 = direcion F_OPPOSITESTAIRS, // val0 = opposite kind of stairs - F_MAPLINK, // val0 = map to link to. optional v1/v2 = x/y + F_MAPLINK, // val0 = map to link to. + // v1/v2 = x/y + // OR + // text = obid to link to // ob interaction flags F_HARD, // object is hard (ie. punching it will hurt!) @@ -1265,10 +1274,12 @@ enum FLAG { F_USESSKILL, // weapon needs skill sk_v0 F_CANHAVEOBMOD, // weapon can have obmod om_v0 applied F_ATTREQ, // requires attrib v0 to be at least bracket v1 - F_DAMTYPE, // val0 = damage type - F_DAM, // val0 = ndice, val1 = nsidesondie, val2 = mod + //F_DAMTYPE, // val0 = damage type + //F_DAM, // val0 = ndice, val1 = nsidesondie, val2 = mod + F_DAM, // v0 = damtype, text = 1d1+1 F_MISSILEDAM, // val0 = dam if it hits (without speed multiplier) F_ACCURACY, // 100 - val0 = penalty to tohit% (ie. higher is better) + F_UNARMEDWEP, // this is not a real weapon, ie. claws, teeth etc F_ARMOURPIERCE, // goes through armour F_TWOHANDED, // weapon uses two hands to weild F_TRIPATTACK, // weapon can trip the victim @@ -1341,7 +1352,8 @@ enum FLAG { F_DONEDARKMSG, // tells the game not to say 'it is very dark here' // lifeform flags / lf flags F_DEBUG, // debugging enabled - F_SHIELDPENALTY, // modify your accuracy by val0 due to a cumbersome + F_ACCURACYMOD, // modify your accuracy by val0 + F_SHIELDPENALTY, // lower your accuracy by val0 due to a cumbersome // shield 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 @@ -1376,6 +1388,8 @@ 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 + // v0 more xp. 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 @@ -1392,6 +1406,7 @@ enum FLAG { F_STABBEDBY, // lf has been stabbed by lfid v0. can't be stabbed // by them again until they go out of sight. F_FLEEFROM, // lf will run away from this lf id + F_NOFLEEFROM, // lf can not get f_fleefrom lfid v0 // TEMP FLAGS F_KILLEDBYPLAYER, // did the player kill this lf? @@ -1408,6 +1423,7 @@ enum FLAG { F_SPELLSPEED, // override default spellcast speed (ie. movespeed) F_RARITY, // val[0] = habitat, val[1] = rarity F_NUMAPPEAR, // when randomly appearing, can have > 1. val[0] = min, val[1] = max + F_MINIONS, // val0 % chance of appearing with v1-v2 lf of type text F_HITDICE, // val0: # d4 to roll for maxhp per level. val1: +xx F_MPDICE, // val0: # d4 to roll for maxmp per level. val1: +xx F_JOB, // val0 = player's class/job @@ -1438,12 +1454,14 @@ enum FLAG { // v2 or more monsters matching f->text next // to the victim F_PHALANX, // gain v0 AR if v2 or more adj monsters matching f->text + F_MORALE, // gain +v0 in morale checks. // INTRINSICS F_MAGICARMOUR,// armour is magically boosted. f->text is the description // ie 'magic armour', 'force field' F_ASLEEP, // is asleep F_BEINGSTONED,// turn to stone when v0 drops to zero. (drops 1/turn) F_BLIND, // cannot see anything + F_DEAF, // cannot hear F_CANCAST, // can cast the spell val0 (need MP) F_CANHEARLF, // you can hear lifeform id v0 (show their glyph) // this flag does not get announced. @@ -1519,14 +1537,15 @@ enum FLAG { F_HASSKILL, // lf has skill v0 at level v1 F_PRACTICINGSKILL, // lf is pract skill v0 // COMBAT - F_HASATTACK, // objecttype id to use when attacking unarmed - // if val0-3 are filled in, they override the object's - // damage (x y-sided dice + z) + F_MAXATTACKS, // v0 = max # attacks this lf can make per round + F_HASATTACK, // v0 = obid to use when attacking unarmed + // if text is set, it overrides the damage F_EVASION, // % chance of evading an attack // healing/resting/training F_STATGAINREADY, // ready to increase str/int etc. v2 is how many times // we can do it. + F_INTERRUPTED, // somethign interrupted our rest. stop! F_RESTING, // are we resting? cleared on any action other than rest. // v2 = if not, NA it is the training counter. // when it hits 0, you finish trainign. @@ -1544,6 +1563,13 @@ enum FLAG { F_IFMONSTER, F_ENDIFPLAYER, F_ENDIFMONSTER, + F_LEVSKILL, // at level v0, this job gains 1 point in skill v1 + F_LEVABIL, // at level v0, this job gains f_canwill v1. + // v2 = how often you can do it (or NA for unlimited) + // text = options + F_LEVSPELL, // at level v0, this job gains f_cancast v1. + F_LEVFLAG, // at level v0, this job gains flagid v1, flagval0=v2, + // flagtext = text // F_NULL = -1 @@ -1610,6 +1636,7 @@ enum SPELLTARGET { #define B_UNKNOWN (0) #define B_KNOWN (-1) +#define B_TRIED (1) #define B_NOBADMOVES (0) #define B_BADMOVESOK (1) @@ -1897,6 +1924,7 @@ typedef struct material_s { #define SK_NONE -1 enum SKILL { + SK_ARMOUR, SK_ATHLETICS, SK_BACKSTAB, SK_FIRSTAID, @@ -1931,7 +1959,7 @@ enum SKILL { SK_SS_TRANSLOCATION, SK_SS_WILD, }; -#define MAXSKILLS 32 +#define MAXSKILLS 33 // proficiency levels enum SKILLLEVEL { @@ -1959,6 +1987,7 @@ typedef struct hiddenname_s { struct hiddenname_s *next, *prev; } hiddenname_t; + typedef struct knowledge_s { enum OBTYPE id; char *hiddenname; diff --git a/flag.c b/flag.c index 247076d..aa5c9df 100644 --- a/flag.c +++ b/flag.c @@ -105,7 +105,7 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, if ((gamemode == GM_GAMESTARTED)) { if (f->pile->owner) { if (announceflaggain(f->pile->owner, f)) { - interrupt(f->pile->owner); + addflag(f->pile, F_INTERRUPTED, B_TRUE, NA, NA, NULL); // note: recursive call! f->known = B_TRUE; if (f->obfrom) { object_t *ob; @@ -322,8 +322,18 @@ void killflag(flag_t *f) { // notify if ((gamemode == GM_GAMESTARTED)) { - if (f->pile->owner) { - if (announceflagloss(f->pile->owner, f)) { + if (lf) { + // special cases + if (f->id == F_FLEEFROM) { + // once you recover from fleeing from something, + // you don't find it scary for a little while. + if (!lfhasflagval(lf, F_NOFLEEFROM, f->val[0], NA, NA, NULL)) { + addtempflag(lf->flags, F_NOFLEEFROM, f->val[0], NA, NA, NULL, 10); + } + } + + // announce + if (announceflagloss(lf, f)) { // don't include flags which interrupt will kill! switch (f->id) { case F_RESTING: @@ -331,7 +341,7 @@ void killflag(flag_t *f) { case F_AUTOCMD: break; default: - interrupt(f->pile->owner); + addflag(lf->flags, F_INTERRUPTED, B_TRUE, NA, NA, NULL); break; } } diff --git a/io.c b/io.c index d8ca87e..3cd4b66 100644 --- a/io.c +++ b/io.c @@ -382,7 +382,7 @@ cell_t *askcoords(char *prompt, int targettype) { int valid = B_FALSE; if ((targettype & TT_MONSTER) && haslf(c) && cansee(player, c->lf) && (c->lf->controller != C_PLAYER)) { valid = B_TRUE; - } else if ((targettype & TT_PLAYER) && haslf(c) && cansee(player, c->lf) && (c->lf->controller == C_PLAYER)) { + } else if ((targettype & TT_PLAYER) && haslf(c) && cansee(player, c->lf) && isplayer(c->lf)) { valid = B_TRUE; } else if ((targettype & TT_OBJECT) && hasobject(c)) { valid = B_TRUE; @@ -775,7 +775,17 @@ int announceflaggain(lifeform_t *lf, flag_t *f) { objecttype_t *ot; ot = findot(f->val[0]); if (ot && (!hasflag(ot->flags, F_NOANNOUNCE))) { - msg("You have learned the ability '%s'.", ot->name); + char buf[BUFLEN]; + sprintf(buf, "You have learned the ability '%s'.", ot->name); + /* + if (f->val[2] != NA) { + char turnbuf[BUFLEN]; + sprintf(turnbuf, " (every %d turn%s)",f->val[2], (f->val[2] == 1) ? "" : "s"); + strcat(buf, turnbuf); + } + strcat(buf, "."); + */ + msg(buf, ot->name); donesomething = B_TRUE; } } @@ -876,8 +886,13 @@ int announceflaggain(lifeform_t *lf, flag_t *f) { lf2 = findlf(NULL, f->val[0]); if (lf2) { getlfname(lf2, buf); - msg("%s turn%s to flee from %s!", lfname, isplayer(lf) ? "" : "s", - (cansee(player, lf2) || isplayer(lf2)) ? buf : "something"); + if ((f->lifetime == PERMENANT) || (f->lifetime >= 4)) { + msg("%s turn%s to flee from %s!", lfname, isplayer(lf) ? "" : "s", + (cansee(player, lf2) || isplayer(lf2)) ? buf : "something"); + } else { // jsut scared a little bit + msg("%s cower%s away from %s!", lfname, isplayer(lf) ? "" : "s", + (cansee(player, lf2) || isplayer(lf2)) ? buf : "something"); + } } break; case F_POISONED: @@ -1706,7 +1721,7 @@ object_t *doaskobject(obpile_t *op, char *prompt, int *count, long opts, ...) { // if picking form a player's pack, use the object's letters. // otherwise just label them a, b, c, etc. - if (op->owner && (op->owner->controller == C_PLAYER)) { + if (op->owner && isplayer(op->owner)) { useobletters = B_TRUE; } else { useobletters = B_FALSE; @@ -1919,7 +1934,7 @@ int askobjectmulti(obpile_t *op, char *prompt, long opts) { // if picking form a player's pack, use the object's letters. // otherwise just label them a, b, c, etc. - if (op->owner && (op->owner->controller == C_PLAYER)) { + if (op->owner && isplayer(op->owner)) { useobletters = B_TRUE; } else { useobletters = B_FALSE; @@ -2282,11 +2297,8 @@ void describeob(object_t *o) { // weapons? if (o->type->obclass->id == OC_WEAPON) { int delay; - f = hasflag(o->flags, F_DAMTYPE); - if (f) { + if (hasflag(o->flags, F_DAM)) { int bonus = 0; - int damtype; - damtype = f->val[0]; f = hasflag(o->flags, F_BONUS); if (f && f->known) { @@ -2297,9 +2309,10 @@ void describeob(object_t *o) { f = hasflag(o->flags, F_DAM); if (f) { char buf[BUFLEN]; - char dicebuf[BUFLEN]; int mindam,maxdam; - getdamrange(o->flags, &mindam, &maxdam); + enum DAMTYPE damtype; + damtype = f->val[0]; + getdamrange(f, &mindam, &maxdam); mindam += bonus; maxdam += bonus; if (mindam < 0) mindam = 0; @@ -2311,27 +2324,14 @@ void describeob(object_t *o) { sprintf(buf, "It inflicts %d-%d %s damage",mindam,maxdam, getdamname(damtype)); } - dicetotext(f->val[0], f->val[1], f->val[2], NULL, NULL, dicebuf, NULL); + //dicetotext(f->val[0], f->val[1], f->val[2], NULL, NULL, dicebuf, NULL); strcat(buf, " ("); - strcat(buf, dicebuf); + strcat(buf, f->text); strcat(buf, ")."); - /* - if (f->val[2] == NA) { - sprintf(dicebuf, " (%dd%d).", f->val[0], f->val[1]); - } else { - sprintf(dicebuf, " (%dd%d%c%d).", f->val[0], f->val[1], - (f->val[2] > 0) ? '+' : '-', - abs(f->val[2])); - } - strcat(buf,dicebuf); - */ mvwprintw(mainwin, y, 0, "%s",buf); y++; - } else { - mvwprintw(mainwin, y, 0, "It inflicts %s damage.",getdamname(damtype)); - y++; } } @@ -2383,6 +2383,19 @@ void describeob(object_t *o) { } } + if (o->type->obclass->id == OC_WAND) { + if (isidentified(o)) { + int charges; + charges = getcharges(o); + if (charges) { + mvwprintw(mainwin, y, 0, "It has %d charges left.",charges); + } else { + mvwprintw(mainwin, y, 0, "It has no charges left."); + } + y++; + } + } + f = hasflag(o->flags, F_THROWMISSILE); if (f) { @@ -5844,14 +5857,12 @@ void showlfstats(lifeform_t *lf, int showall) { objecttype_t *ot; int first; int i; - int unarmed = B_FALSE; - flag_t *uflag = NULL; float dammod; int accmod; enum BODYPART bp; enum BODYPART missingbp[MAXBODYPARTS]; int nmissingbp; - + obpile_t *op = NULL; char ch; char mode = '@'; char prompt[BUFLEN]; @@ -5912,6 +5923,12 @@ void showlfstats(lifeform_t *lf, int showall) { wprintw(mainwin, "%-20s", j->name); y++; } + + // size + mvwprintw(mainwin, y, 0, ftext, "Size"); + wprintw(mainwin, "%-20s", getsizetext(getlfsize(lf))); y++; + + if (showall) { float w; w = getlfweight(lf, B_NOOBS); @@ -6067,38 +6084,128 @@ void showlfstats(lifeform_t *lf, int showall) { // now go to second column - // WEAPON STUFF + + + // current weapon + dam w = getweapon(lf); if (w) { + int mindam,maxdam; + int bonus; + + // weapon sprintf(buf, "%s", w->type->name); - } else { - obpile_t *op = NULL; - op = getunarmedweapon(lf, &uflag); // will return a random weapon. TODO: show all? - if (op->first) { - w = op->first; - sprintf(buf, "%s (unarmed)", w->type->name); - unarmed = B_TRUE; - } else { - sprintf(buf, "N/A"); - } - killobpile(op); - } - mvwprintw(mainwin, y2, x2, ftext, "Current Weapon"); - wprintw(mainwin, "%-20s", buf); y2++; + mvwprintw(mainwin, y2, x2, ftext, "Weapon"); + wprintw(mainwin, "%-20s", buf); y2++; + if (showall) { + // damage + f = hasflag(w->flags, F_BONUS); + if (f && f->known) { + // only tell player about bonuses if they are known.! + bonus = f->val[0]; + } else { + bonus = 0; + } + + f = hasflag(w->flags, F_DAM); + if (f) { + getdamrange(f, &mindam, &maxdam); + } else { + mindam = 0; + maxdam = 0; + } + + mindam += bonus; + maxdam += bonus; + + // apply damage mod for strength + if (!hasflag(w->flags, F_NOSTRDAMMOD) && !lfhasflag(lf, F_NOSTRDAMMOD)) { + mindam = (int)((float)mindam * dammod); + maxdam = (int)((float)maxdam * dammod); + } + + if (mindam < 0) mindam = 0; + if (maxdam < 0) maxdam = 0; + + sprintf(buf, "%d-%d",(int)mindam,(int)maxdam); + + mvwprintw(mainwin, y2, x2, ftext, "Weapon Dmg"); + wprintw(mainwin, "%-20s", buf); y2++; - if (showall) { - if (w) { // chance to hit - acc = getlfaccuracy(lf); - mvwprintw(mainwin, y2, x2, ftext, "Accuracy"); + acc = getlfaccuracy(lf, w); + mvwprintw(mainwin, y2, x2, ftext, "Wep.Accuracy"); wprintw(mainwin, "%d%%", acc); y2++; } + } else { + // no damage + sprintf(buf, "N/A"); + mvwprintw(mainwin, y2, x2, ftext, "Current Weapon"); + wprintw(mainwin, "%-20s", buf); y2++; } + // skip a line + y2++; + + /* + if (showall) { + mvwprintw(mainwin, y2, x2, ftext, "Attack Dmg"); + wprintw(mainwin, "%-20s", buf); y2++; + } + */ + + + // unarmed attacks + op = addobpile(NULL, NULL); + for (f = lf->flags->first ; f ; f = f->next) { + + if (f->id == F_HASATTACK) { + object_t *o; + objecttype_t *ot; + ot = findot(f->val[0]); + o = addob(op, ot->name); + if (o) { + sprintf(buf, "%s", o->type->name); + // damage + if (showall) { + char dambuf[BUFLEN]; + int mindam,maxdam; + + getdamrange(f, &mindam, &maxdam); + + // apply damage mod for strength + if (!hasflag(o->flags, F_NOSTRDAMMOD) && !lfhasflag(lf, F_NOSTRDAMMOD)) { + mindam = (int)((float)mindam * dammod); + maxdam = (int)((float)maxdam * dammod); + } + if (mindam < 0) mindam = 0; + if (maxdam < 0) maxdam = 0; + + sprintf(dambuf, " (%d-%d dmg)",(int)mindam,(int)maxdam); + strcat(buf, dambuf); + } + + mvwprintw(mainwin, y2, x2, ftext, "Innate Attack"); + wprintw(mainwin, "%-20s", buf); y2++; + + } // end if o + } // end if fid == hasattack + } // end for each flag + + + // no attacks at all? + if (!w && !op->first) { + sprintf(buf, "N/A"); + mvwprintw(mainwin, y2, x2, ftext, "Attack"); + wprintw(mainwin, "%-20s", buf); y2++; + } + + // skip line + y2++; + // attack speed - if (w) { + if (w || op->first) { speed = getattackspeed(lf); getspeedname(speed, buf); capitalise(buf); @@ -6106,55 +6213,7 @@ void showlfstats(lifeform_t *lf, int showall) { wprintw(mainwin, "%-20s", buf); y2++; } - - // damage - if (w) { - int mindam,maxdam; - int bonus; - f = hasflag(w->flags, F_BONUS); - if (f && f->known) { - // only tell player about bonuses if they are known.! - bonus = f->val[0]; - } else { - bonus = 0; - } - - if (uflag) { - getdamrangeunarmed(uflag, &mindam, &maxdam); - } else { - f = hasflag(w->flags, F_DAM); - if (f) { - getdamrange(w->flags, &mindam, &maxdam); - } else { - mindam = 0; - maxdam = 0; - } - } - - mindam += bonus; - maxdam += bonus; - - // apply damage mod for strength - if (!hasflag(w->flags, F_NOSTRDAMMOD) && !lfhasflag(lf, F_NOSTRDAMMOD)) { - mindam = (int)((float)mindam * dammod); - maxdam = (int)((float)maxdam * dammod); - } - - if (mindam < 0) mindam = 0; - if (maxdam < 0) maxdam = 0; - - sprintf(buf, "%d-%d",(int)mindam,(int)maxdam); - } else { - // no damage - sprintf(buf, "N/A"); - } - - if (showall) { - mvwprintw(mainwin, y2, x2, ftext, "Attack Dmg"); - wprintw(mainwin, "%-20s", buf); y2++; - } - - + killobpile(op); y2++; // skip line @@ -6403,90 +6462,6 @@ void showlfstats(lifeform_t *lf, int showall) { } } - // obvious physical effects - // (NON-obvious intrinsics etc go on next page) - f = lfhasknownflag(lf, F_ASLEEP); - if (f) { - mvwprintw(mainwin, y, 0, "%s %s sleeping.", you(lf), isplayer(lf) ? "are" : "is"); - y++; - } - f = lfhasknownflag(lf, F_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"); - 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++; - } - } - - } else if (mode == 's') { int exitnow = B_FALSE; @@ -6638,6 +6613,90 @@ void showlfstats(lifeform_t *lf, int showall) { y++; } + // 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"); + 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++; + } + } + + + // show intrinsics f = lfhasknownflag(lf, F_ATTRSET); if (f && (f->known)) { @@ -6784,9 +6843,18 @@ void showlfstats(lifeform_t *lf, int showall) { } f = lfhasknownflag(lf, F_POISONED); if (f && (f->known)) { - sprintf(buf, "%s %s poisoned.", you(lf), isplayer(lf) ? "are" : "is"); + int knownfatal = B_FALSE; + + if (getskill(player, SK_FIRSTAID) >= PR_ADEPT) { + if (poisonthreatenslife(lf)) { + knownfatal = B_TRUE; + } + } + + sprintf(buf, "%s %s poisoned%s.", you(lf), isplayer(lf) ? "are" : "is", + knownfatal ? ", potentially fatally" : ""); if (lfhasflag(lf, F_EXTRAINFO) || lfhasflag(lf, F_OMNIPOTENT) || - (getskill(lf, SK_FIRSTAID) >= PR_ADEPT) ) { + (getskill(player, SK_FIRSTAID) >= PR_ADEPT) ) { char buf2[BUFLEN]; sprintf(buf2, " [max %d turns left]", f->lifetime); strcat(buf, buf2); diff --git a/lf.c b/lf.c index af7a0e4..24ddf7c 100644 --- a/lf.c +++ b/lf.c @@ -414,7 +414,7 @@ int areallies(lifeform_t *lf1, lifeform_t *lf2) { return B_FALSE; } -// make sure player has at least novice skill in all their start weapons +// make sure player has at least novice skill in all their start weapons/armour void autoskill(lifeform_t *lf) { skill_t *sk; object_t *o; @@ -435,6 +435,12 @@ void autoskill(lifeform_t *lf) { } nweps++; } + if (isarmour(o) && canwear(lf, o, BP_NONE)) { + giveskilllev(lf, SK_ARMOUR, PR_NOVICE); + } + if (isshield(o) && canwear(lf, o, BP_NONE)) { + giveskilllev(lf, SK_SHIELDS, PR_NOVICE); + } } if (!nweps) { @@ -592,12 +598,12 @@ int calcxp(lifeform_t *lf) { float xpval = 0; float offense = 0; float defence = 0; + float spells = 0; object_t *o; obpile_t *op; flag_t *f; float avgdam = 0; - float acc; - int db = B_FALSE; + int db = B_TRUE; int maxhdroll; float xpconstant = 1; @@ -615,34 +621,79 @@ int calcxp(lifeform_t *lf) { // - get average attack damage op = addobpile(NULL, NULL); avgdam = 0; - for (f = lf->flags->first ; f ; f = f->next) { + for (f = lf->race->flags->first ; f ; f = f->next) { if (f->id == F_HASATTACK) { int min,max; float thisavg; - getdamrangeunarmed(f, &min,&max); + float acc; + flag_t *of; + + objecttype_t *ot; + ot = findot(f->val[0]); + o = addob(op, ot->name); + + getdamrange(f, &min,&max); thisavg = ((float)min + (float)max) / 2.0; + + // confers anything? + for (of = o->flags->first ; of ; of = of->next) { + if (of->id == F_HITCONFER) { + thisavg += 10; + } + } + + // modify for accuracy + acc = getlfaccuracy(lf, o); + thisavg = pctof(acc, thisavg); + + avgdam += thisavg; if (db) { char obname[BUFLEN]; getobname(o,obname,1); if (db) dblog("calcxp: %s: == %d-%d dam, avg is %0.1f",obname, min, max, thisavg); } - if (thisavg > avgdam) { - if (db) dblog("calcxp: this is best so far."); - avgdam = thisavg; + } else if (f->id == F_STARTOB) { + object_t *o; + int min,max; + float thisavg; + float acc; + flag_t *of; + obpile_t *op; + + op = addobpile(NULL,NULL); + + o = addob(op, f->text); + + getdamrange(hasflag(o->flags, F_DAM), &min,&max); + thisavg = ((float)min + (float)max) / 2.0; + + // confers anything? + for (of = o->flags->first ; of ; of = of->next) { + if (of->id == F_HITCONFER) { + thisavg += 10; + } } + + // modify for accuracy + acc = getlfaccuracy(lf, o); + thisavg = pctof(acc, thisavg); + + avgdam += thisavg; + if (db) { + char obname[BUFLEN]; + getobname(o,obname,1); + if (db) dblog("calcxp: %s: == %d-%d dam, avg is %0.1f",obname, min, max, thisavg); + } + + killobpile(op); } } - if (op) killobpile(op); - if (db) dblog("calcxp: avg damage dealt is %0.1f",avgdam); - - // -- avg damage in 10 turns - avgdam *= 10; - - // -- modify with accuracy - acc = getlfaccuracy(lf); - offense = pctof(acc,avgdam); - if (db) dblog("calcxp: ATTACKVAL IS %0.1f",offense); + + if (db) dblog("calcxp: avg damage dealt is %0.1f",avgdam); + + + if (op) killobpile(op); // defense // -- hitdice @@ -655,12 +706,101 @@ int calcxp(lifeform_t *lf) { } defence = maxhdroll * lf->level; - defence /= 2; + //defence /= 2; // -- evasion ? if (db) dblog("calcxp: DEFENCE IS %0.1f",defence); - xpval = offense + defence; + + // spells + for (f = lf->flags->first ; f ; f = f->next) { + if (f->id == F_CANCAST) { + objecttype_t *ot; + int power,level; + ot = findot(f->val[0]); + power = getspellpower(lf, f->val[0]); + level = getspelllevel(f->val[0]); + spells += (power * level); + if (db) dblog("cancast %s: == power %d * spelllevel %d = %d",ot->name, power, level, power*level); + } else if (f->id == F_CANWILL) { + objecttype_t *ot; + // is this a spell? + ot = findot(f->val[0]); + if (ot && ot->obclass->id == OC_SPELL) { + int power,level; + power = getspellpower(lf, ot->id); + level = getspelllevel(ot->id); + spells += (power * level); + if (db) dblog("canwill spell %s: == power %d * spelllevel %d = %d",ot->name, power, level, power*level); + } else { + char damstr[BUFLEN]; + int needgrab = B_FALSE; + objecttype_t *ot; + + flag_t *af; + + ot = findot(f->val[0]); + + af = hasflag(ot->flags, F_XPVAL); + if (af) { + float thisamt = af->val[0]; + if (f->val[2] == NA) { + if (db) dblog("canwill ability %s == %0.1f",ot->name, thisamt); + } else { + thisamt /= f->val[2]; + if (db) dblog("canwill ability %s every %d turns == %0.1f",ot->name, f->val[2], thisamt); + } + spells += thisamt; + } + + // other special cases + switch (f->val[0]) { + case OT_A_SWOOP: + if (db) dblog("canwill SWOOP - increasing avg dam from %0.1f to %0.1f.", avgdam, avgdam*1.1); + avgdam *= 1.1; // attack bonus! + break; + default: + break; + } + // get dam from text + texttospellopts(f->text, NULL, damstr, &needgrab); + if (strlen(damstr)) { + int dice,sides,mod,min,max; + float thisavg; + texttodice(damstr, &dice,&sides,&mod); + dicetotext(dice,sides,mod, &min, &max, damstr, NULL); + thisavg = ((min+max)/2); + + if (db) dblog("canwill ability %s causes dam %0.1f",ot->name, thisavg); + // adjust if you have to grab first + if (needgrab) { + thisavg /= 2; + if (db) dblog(" (adjusted to %0.1f due to needing to grab)", thisavg); + } + // adjust based on how often we can do it + if (f->val[2] != NA) { + thisavg /= f->val[2]; + if (db) dblog(" (can do every %d turns. --> %0.1f)", f->val[2], thisavg); + } + if (ot->id == OT_A_GRAB) { + // assume can only grab once in the 10 turns. + thisavg /= 10; + } + avgdam += thisavg; + } + } + } + } + + // -- 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); + + // TOTAL: + xpval = offense + defence + spells; f = lfhasflag(lf, F_XPMOD); if (f) { @@ -668,6 +808,10 @@ int calcxp(lifeform_t *lf) { if (db) dblog("calcxp: F_XPMOD is %d",f->val[0]); } + + + + if (db) dblog("calcxp: xpval: %0.1f --> %0.1f",xpval, xpval * xpconstant); xpval *= xpconstant; @@ -806,6 +950,9 @@ int canhear(lifeform_t *lf, cell_t *dest) { // can't hear when dead. if (isdead(lf)) return B_FALSE; + // can't hear if you are deaf + if (lfhasflag(lf, F_DEAF)) return B_FALSE; + // can't hear noises from other maps if (lf->cell->map != dest->map) return B_FALSE; @@ -1016,6 +1163,8 @@ int cansee(lifeform_t *viewer, lifeform_t *viewee) { return B_TRUE; } + +// where == BP_NONE means "can i wear it anywhere?' int canwear(lifeform_t *lf, object_t *o, enum BODYPART where) { object_t *oo; flag_t *f; @@ -1666,7 +1815,7 @@ int eat(lifeform_t *lf, object_t *o) { if (nutrition == 0) { // should never happen! - if (lf->controller == C_PLAYER) { + if (isplayer(lf)) { msg("That doesn't seem very nutritious..."); } return B_TRUE; @@ -1676,7 +1825,7 @@ int eat(lifeform_t *lf, object_t *o) { // only do this check for the player - basically it should // handle the case where we have poluymorphed into something // which doesn't eat. - if (lf->controller == C_PLAYER) { + if (isplayer(lf)) { f = hasflag(lf->flags, F_HUNGER); if (!f) { msg("You don't need to %s!", drinking ? "drink" : "eat"); @@ -1691,7 +1840,7 @@ int eat(lifeform_t *lf, object_t *o) { } // announce - if (lf->controller == C_PLAYER) { + if (isplayer(lf)) { msg("You %s %s.%s", drinking ? "drink" : "eat", obname, (f->val[1] >= 20) ? " Yum!" : ""); } else if (cansee(player, lf)) { @@ -1901,8 +2050,7 @@ void enhanceskills(lifeform_t *lf) { // any skills to get? if (skillstoenhance) { char ques[BUFLEN]; - sprintf(ques, "Which skill will you enhance (%d point%s left)?", lf->skillpoints, - (lf->skillpoints == 1) ? "" : "s"); + sprintf(ques, "Enhance which skill enhance (%d left)?", lf->skillpoints); initprompt(&prompt, ques); ch = 'a'; @@ -1911,11 +2059,12 @@ void enhanceskills(lifeform_t *lf) { char buf[BUFLEN]; sprintf(buf, "%s (%s -> %s)", getskillname(f->val[0]), getskilllevelname(f->val[1]), getskilllevelname(f->val[1] + 1)); - addchoice(&prompt, ch++, buf, buf, f); + addchoice(&prompt, ch++, getskillname(f->val[0]), buf, f); } } addchoice(&prompt, '-', "None", "None", NULL); - getchoice(&prompt); + + getchoicestr(&prompt, B_FALSE, B_TRUE); f = (flag_t *)prompt.result; if (f) { whichsk = f->val[0]; @@ -1935,7 +2084,7 @@ void enhanceskills(lifeform_t *lf) { if (skillstolearn) { char ques[BUFLEN]; - sprintf(ques, "Which new skill will you learn (%d points left)?", player->skillpoints); + sprintf(ques, "Learn which new skill (%d left)?", player->skillpoints); initprompt(&prompt, ques); ch = 'a'; @@ -1943,12 +2092,12 @@ void enhanceskills(lifeform_t *lf) { // TODO: && canlearn(player, sk->id) if (!getskill(player, sk->id)) { char buf[BUFLEN]; - sprintf(buf, "%s (%s)", getskillname(sk->id), getskilldesc(sk->id)); - addchoice(&prompt, ch++, buf, buf, sk); + sprintf(buf, "%-18s(%s)", getskillname(sk->id), getskilldesc(sk->id)); + addchoice(&prompt, ch++, getskillname(sk->id), buf, sk); } } addchoice(&prompt, '-', "None", "None", NULL); - getchoice(&prompt); + getchoicestr(&prompt, B_FALSE, B_TRUE); sk = (skill_t *)prompt.result; if (sk) { giveskill(player, sk->id); @@ -1980,6 +2129,27 @@ void enhanceskills(lifeform_t *lf) { lf->skillpoints--; } // end if isplayer + // now get job-based level rewards + for (f = lf->flags->first ; f ; f = f->next) { + if (f->id == F_LEVABIL) { + if (lf->level == f->val[0]) { + addflag(lf->flags, F_CANWILL, f->val[1], f->val[2], f->val[2], f->text); + } + } else if (f->id == F_LEVFLAG) { + if (lf->level == f->val[0]) { + addflag(lf->flags, f->val[1], f->val[2], NA, NA, f->text); + } + } else if (f->id == F_LEVSKILL) { + if (lf->level == f->val[0]) { + giveskill(lf, f->val[1]); + } + } else if (f->id == F_LEVSPELL) { + if (lf->level == f->val[0]) { + addflag(lf->flags, F_CANCAST, f->val[1], NA, NA, NULL); + } + } + } + } @@ -1997,7 +2167,7 @@ int fall(lifeform_t *lf, int announce) { char lfname[BUFLEN]; getlfname(lf,lfname); - if (lfhasflag(lf, F_STABILITY)) { + if (lfhasflag(lf, F_STABILITY) || !hasbp(lf, BP_FEET)) { return B_TRUE; } if (announce) { @@ -2131,6 +2301,8 @@ enum SKILLLEVEL findskilllevbyname(char *name) { return PR_INEPT; } +// try to actually do the 'run away' action for +// anyone we are fleeing from. // returns TRUE if we ran away from something int flee(lifeform_t *lf) { flag_t *f, *nextf; @@ -2198,6 +2370,44 @@ int flee(lifeform_t *lf) { return B_FALSE; } +// start fleeing from 'enemy' +void fleefrom(lifeform_t *lf, lifeform_t *enemy, int howlong) { + flag_t *f; + + // in recovery from fleeing? + // this is to prevent constant usage of war cry! + f = hasflagval(lf->flags, F_NOFLEEFROM, enemy->id, NA, NA, NULL); + if (f) { + if (f->lifetime > 0) { + f->lifetime -= 5; + if (f->lifetime <= 0) { + killflag(f); + } + } + if (isplayer(lf)) { + msg("You flinch."); + } else if (cansee(player, lf)) { + char lfname[BUFLEN]; + getlfname(lf, lfname); + msg("%s flinches.",lfname); + } + return; + } + + // already fleeing? + f = hasflagval(lf->flags, F_FLEEFROM, enemy->id, NA, NA, NULL); + if (f) { + // update time + if (f->lifetime != PERMENANT) { + if (f->lifetime < howlong) { + f->lifetime = howlong; + } + } + } else { + addtempflag(lf->flags, F_FLEEFROM, enemy->id, NA, NA, NULL, howlong); + } +} + int freezelf(lifeform_t *freezee, lifeform_t *freezer, int howlong) { if (isimmuneto(freezee->flags, DT_COLD)) { if (isplayer(freezee)) { @@ -2580,7 +2790,12 @@ int getevasion(lifeform_t *lf) { if (hasflag(o->flags, F_EQUIPPED)) { f = hasflag(o->flags, F_EVASION); if (f) { - ev += (f->val[0]); + if (isarmour(o)) { + // adjust penalties based on armour skill. + ev += adjustarmourpenalty(lf, f->val[0]); + } else { + ev += (f->val[0]); + } if (ev < 0) ev = 0; } } @@ -2651,26 +2866,12 @@ object_t *getbestfirearm(lifeform_t *lf) { object_t *getbestweapon(lifeform_t *lf) { - obpile_t *op = NULL; + //obpile_t *op = NULL; object_t *bestwep = NULL; //int bestmaxdam = -999; object_t *o; bestwep = getweapon(lf); - if (!bestwep) { - op = getunarmedweapon(lf, NULL); - bestwep = op->first; - } - /* - if (curwep) { - f = hasflag(curwep->flags, F_DAM); - //bestmaxdam = f->val[1]; - } else { - // no current weapon, and no unarmed weapon - // anything will be better! - //bestmaxdam = -999; - } - */ for (o = lf->pack->first ; o ; o = o->next) { // if it does damage and we can weild it... @@ -2681,6 +2882,7 @@ object_t *getbestweapon(lifeform_t *lf) { } } + /* if (op && (bestwep == op->first)) { // ie. use no weapon bestwep = NULL; @@ -2689,6 +2891,7 @@ object_t *getbestweapon(lifeform_t *lf) { if (op) { killobpile(op); } + */ return bestwep; } @@ -2899,33 +3102,19 @@ job_t *getjob(lifeform_t *lf) { return NULL; } -int getlfaccuracy(lifeform_t *lf) { - obpile_t *op = NULL; - object_t *wep; +int getlfaccuracy(lifeform_t *lf, object_t *wep) { flag_t *f; int acc = 0; // get weapon - wep = getweapon(lf); if (wep) { acc = getobaccuracy(wep, lf); - } else { - // ie. unarmed - op = getunarmedweapon(lf, NULL); - - if (op->first) { - wep = op->first; - acc = getobaccuracy(wep, lf); - } else { - // cannot attack - acc = 0; - } } - if (op) killobpile(op); - for (f = lf->flags->first ;f ; f = f->next) { - if (f->id == F_SHIELDPENALTY) { + if (f->id == F_ACCURACYMOD) { + acc += f->val[0]; + } else if (f->id == F_SHIELDPENALTY) { acc -= adjustshieldpenalty(lf, f->val[0]); } } @@ -2933,7 +3122,6 @@ int getlfaccuracy(lifeform_t *lf) { // modify for weilder's level acc += (lf->level * 2); - // modify with dexterity acc += getstatmod(lf, A_DEX); @@ -3866,6 +4054,9 @@ object_t *getweapon(lifeform_t *lf) { long getxpforlev(int level) { long needxp = 0; + // 2.8 + float multiplier = 9.5; + float constant = 3.2; // no xp needed for level 1 /* @@ -3874,8 +4065,7 @@ long getxpforlev(int level) { needxp += (20 * (pow(i,2.8))); } */ - //needxp = (20 * (pow(level,2.8) - 1)); - needxp = (10 * (pow(level,2.8) - 1)); + needxp = (multiplier * (pow(level,constant) - 1)); return needxp; } @@ -4140,6 +4330,7 @@ int giveskill(lifeform_t *lf, enum SKILL id) { if (isplayer(lf) && (gamemode == GM_GAMESTARTED)) { msg("You have learned the %s %s skill!", getskilllevelname(f->val[1]), getskillname(sk->id)); } + statdirty = B_TRUE; // in case skill changes your stats } else { // gaining a new skill f = addflag(lf->flags, F_HASSKILL, id, PR_NOVICE, NA, NULL); @@ -4160,6 +4351,7 @@ int giveskill(lifeform_t *lf, enum SKILL id) { newf = addflag(lf->flags, F_CANWILL, OT_A_SPRINT, NA, NA, NULL); newf->lifetime = FROMJOB; } + statdirty = B_TRUE; // in case skill changes your stats } @@ -4200,6 +4392,7 @@ int giveskill(lifeform_t *lf, enum SKILL id) { addflag(lf->flags, F_CANCAST, OT_S_MINDSCAN, NA, NA, NULL); } } + return B_FALSE; } @@ -4859,11 +5052,6 @@ int haslos(lifeform_t *viewer, cell_t *dest) { } } - // made it to the target cell! - /* - if (viewer->controller == C_HUMAN) wreck->mazelev[z].maze[y2*MAZEW+x2].known = B_PERM; - if (viewer->controller == C_HUMAN) wreck->mazelev[z].maze[y2*MAZEW+x2].known = B_PERM; - */ return B_TRUE; } @@ -4919,7 +5107,7 @@ void initjobs(void) { addflag(lastjob->flags, F_STARTSKILL, SK_ATHLETICS, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_SPELLCASTING, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_TECHUSAGE, PR_NOVICE, NA, NULL); - addflag(lastjob->flags, F_STARTSKILL, SK_SHIELDS, PR_NOVICE, NA, NULL); + addflag(lastjob->flags, F_STARTSKILL, SK_ARMOUR, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_CANLEARN, ALL, NA, NA, NULL); addjob(J_ALLOMANCER, "Allomancer"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "1 gold coins"); @@ -4934,6 +5122,7 @@ void initjobs(void) { addflag(lastjob->flags, F_STARTATT, A_IQ, IQ_AVERAGE, NA, NULL); addflag(lastjob->flags, F_DETECTMETAL, B_TRUE, NA, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_SS_ALLOMANCY, PR_NOVICE, NA, NULL); + addflag(lastjob->flags, F_STARTSKILL, SK_ARMOUR, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_LOCKPICKING, PR_NOVICE, NA, NULL); mayusespellschool(lastjob->flags, SS_ALLOMANCY, F_CANCAST); addflag(lastjob->flags, F_CANLEARN, SK_BACKSTAB, NA, NA, NULL); @@ -4959,6 +5148,7 @@ void initjobs(void) { addflag(lastjob->flags, F_STARTSKILL, SK_SHORTBLADES, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_LONGBLADES, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_ATHLETICS, PR_NOVICE, NA, NULL); + addflag(lastjob->flags, F_STARTSKILL, SK_ARMOUR, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_SHIELDS, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_LISTEN, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_LOCKPICKING, NA, NA, NULL); @@ -4970,6 +5160,8 @@ void initjobs(void) { addflag(lastjob->flags, F_CANLEARN, SK_POLEARMS, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_STAVES, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_UNARMED, NA, NA, NULL); + addflag(lastjob->flags, F_LEVABIL, 7, OT_A_WARCRY, NA, NULL); + addflag(lastjob->flags, F_LEVABIL, 10, OT_A_HURRICANESTRIKE, 5, NULL); addjob(J_COMMANDO, "Commando"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "combat knife"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "revolver"); @@ -4989,6 +5181,7 @@ void initjobs(void) { addflag(lastjob->flags, F_STARTATT, A_CON, CN_HEALTHY, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_ATHLETICS, PR_ADEPT, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_FIRSTAID, PR_NOVICE, NA, NULL); + addflag(lastjob->flags, F_STARTSKILL, SK_ARMOUR, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_BACKSTAB, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_FIRSTAID, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_LISTEN, NA, NA, NULL); @@ -5020,6 +5213,7 @@ void initjobs(void) { addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "silk shirt"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "riding trousers"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "leather boots"); + addflag(lastjob->flags, F_STARTSKILL, SK_ARMOUR, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_SHIELDS, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_SHORTBLADES, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_LONGBLADES, PR_NOVICE, NA, NULL); @@ -5032,7 +5226,6 @@ void initjobs(void) { addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "knife"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "robe"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "2 potions of magic"); - addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "5 potions of experience"); addflag(lastjob->flags, F_CANCAST, OT_S_MANASPIKE, NA, NA, NULL); /* @@ -5057,13 +5250,12 @@ void initjobs(void) { addflag(lastjob->flags, F_RESTHEALTIME, 6, NA, NA, NULL); //addflag(lastjob->flags, F_MPREGEN, 1, SK_SPELLCASTING, 35, NULL); // can detect magic objects - addflag(lastjob->flags, F_DETECTMAGIC, B_TRUE, NA, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_RESEARCH, PR_BEGINNER, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_SPELLCASTING, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_MAGITEMUSAGE, PR_NOVICE, NA, NULL); + addflag(lastjob->flags, F_STARTSKILL, SK_STAVES, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_LISTEN, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_MAGITEMUSAGE, NA, NA, NULL); - addflag(lastjob->flags, F_CANLEARN, SK_STAVES, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_SHORTBLADES, NA, NA, NULL); // wizards can learn all spell schools except psionics and allomancy addflag(lastjob->flags, F_CANLEARN, SK_SS_AIR, NA, NA, NULL); @@ -5076,6 +5268,9 @@ void initjobs(void) { addflag(lastjob->flags, F_CANLEARN, SK_SS_SUMMONING, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_SS_TRANSLOCATION, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_SS_WILD, NA, NA, NULL); + addflag(lastjob->flags, F_LEVFLAG, 3, F_DETECTMAGIC, B_TRUE, NULL); + addflag(lastjob->flags, F_LEVFLAG, 7, F_DETECTAURAS, B_TRUE, NULL); + addflag(lastjob->flags, F_LEVFLAG, 10, F_CONTROL, B_TRUE, NULL); // for monster wizards only: addflag(lastjob->flags, F_IFMONSTER, NA, NA, NA, NULL); @@ -5104,7 +5299,7 @@ void initrace(void) { addflag(lastrace->flags, F_HITDICE, 2, 2, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, NULL); - addflag(lastrace->flags, F_HASATTACK, NA, NA, NA, "fists"); + addflag(lastrace->flags, F_HASATTACK, OT_FISTS, NA, NA, "1d2"); addflag(lastrace->flags, F_STARTOB, 80, NA, NA, "1-50 gold coins"); addflag(lastrace->flags, F_STARTOBCLASS, 65, OC_WEAPON, NA, NULL); addflag(lastrace->flags, F_STARTOBCLASS, 65, OC_ARMOUR, NA, NULL); @@ -5137,7 +5332,7 @@ void initrace(void) { addflag(lastrace->flags, F_CANWILL, OT_S_SLEEP, NA, NA, "pw:2;"); addflag(lastrace->flags, F_CANWILL, OT_S_PULL, NA, NA, "pw:2;"); addflag(lastrace->flags, F_CANWILL, OT_S_PARALYZE, NA, NA, "pw:2;"); - addflag(lastrace->flags, F_HASATTACK, 2, 4, NA, "teeth"); + addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "2d4"); addflag(lastrace->flags, F_SPELLCASTTEXT, NA, NA, NA, "gazes at you"); addflag(lastrace->flags, F_NOBODYPART, BP_WEAPON, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_SECWEAPON, NA, NA, NULL); @@ -5148,6 +5343,7 @@ void initrace(void) { addflag(lastrace->flags, F_SEEINDARK, UNLIMITED, NA, NA, NULL); addflag(lastrace->flags, F_HASSKILL, SK_SPELLCASTING, PR_EXPERT, NA, NULL); addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); addrace(R_BUGBEAR, "bugbear", 120, 'G', C_BROWN, MT_FLESH); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -5157,7 +5353,7 @@ void initrace(void) { addflag(lastrace->flags, F_EVASION, 0, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); - addflag(lastrace->flags, F_HASATTACK, 1, 10, NA, "claws"); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d10"); 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); @@ -5167,6 +5363,8 @@ void initrace(void) { addflag(lastrace->flags, F_SEEINDARK, 3, NA, NA, NULL); addflag(lastrace->flags, F_CANWILL, OT_A_HEAVYBLOW, 2, 2, NULL); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MINIONS, 50, 1, 3, "goblin"); + addflag(lastrace->flags, F_MINIONS, 20, 1, 3, "goblin warrior"); addrace(R_COCKATRICE, "cockatrice", 5, 'c', C_YELLOW, MT_FLESH); addflag(lastrace->flags, F_STARTATT, A_DEX, DX_SWIFT, NA, NULL); @@ -5185,7 +5383,8 @@ void initrace(void) { addflag(lastrace->flags, F_NOPACK, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_DTIMMUNE, DT_PETRIFY, B_TRUE, NA, NULL); - addflag(lastrace->flags, F_HASATTACK, 1, 6, 3, "teeth"); + addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d6+3"); + addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); // special attack handled in attack.c addrace(R_DARKMANTLE, "darkmantle", 70, 'Q', C_BLUE, MT_FLESH); @@ -5207,7 +5406,7 @@ void initrace(void) { 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_SPELLCASTTEXT, NA, NA, NA, "waves its tentacles"); - addflag(lastrace->flags, F_HASATTACK, 2, 6, NA, "tentacle"); + addflag(lastrace->flags, F_HASATTACK, OT_TENTACLE, NA, NA, "2d6"); 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); @@ -5217,6 +5416,8 @@ void initrace(void) { addflag(lastrace->flags, F_SEEINDARK, UNLIMITED, NA, NA, NULL); addflag(lastrace->flags, F_DTVULN, DT_LIGHT, NA, NA, "0d6+5"); addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); + addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); addrace(R_EYEBAT, "eyebat", 5, 'e', C_BLUE, MT_FLESH); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_SMART, NA, NULL); @@ -5244,6 +5445,7 @@ void initrace(void) { addflag(lastrace->flags, F_SEEINDARK, UNLIMITED, NA, NA, NULL); addflag(lastrace->flags, F_HASSKILL, SK_SPELLCASTING, PR_EXPERT, NA, NULL); addflag(lastrace->flags, F_NOISETEXT, N_FLY, NA, NA, "^flapping wings"); + addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); addrace(R_GIANTHILL, "hill giant", 160, 'H', C_BROWN, MT_FLESH); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 55, NA, NULL); @@ -5254,7 +5456,7 @@ void initrace(void) { addflag(lastrace->flags, F_EVASION, -20, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_SLOW, NA, NA, NULL); - addflag(lastrace->flags, F_HASATTACK, 2, 5, NA, "fists"); + addflag(lastrace->flags, F_HASATTACK, OT_FISTS, NA, NA, "2d5"); addflag(lastrace->flags, F_STARTOB, 90, NA, NA, "25-100 gold coins"); addflag(lastrace->flags, F_STARTOB, 70, NA, NA, "1-2 boulders"); addflag(lastrace->flags, F_IFPCT, 70, NA, NA, NULL); @@ -5282,7 +5484,7 @@ void initrace(void) { addflag(lastrace->flags, F_EVASION, -20, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, NULL); - addflag(lastrace->flags, F_HASATTACK, 2, 5, NA, "fists"); + addflag(lastrace->flags, F_HASATTACK, OT_FISTS, NA, NA, "2d5+3"); addflag(lastrace->flags, F_STARTOB, 90, NA, NA, "25-100 gold coins"); addflag(lastrace->flags, F_IFPCT, 70, NA, NA, NULL); addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "flaming greatsword"); @@ -5314,7 +5516,7 @@ void initrace(void) { addflag(lastrace->flags, F_EVASION, -20, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, NULL); - addflag(lastrace->flags, F_HASATTACK, 2, 5, NA, "fists"); + addflag(lastrace->flags, F_HASATTACK, OT_FISTS, NA, NA, "2d5+3"); addflag(lastrace->flags, F_STARTOB, 90, NA, NA, "25-100 gold coins"); addflag(lastrace->flags, F_IFPCT, 70, NA, NA, NULL); addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "flaming morningstar"); @@ -5347,7 +5549,7 @@ void initrace(void) { addflag(lastrace->flags, F_EVASION, -30, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, NULL); - addflag(lastrace->flags, F_HASATTACK, 2, 5, 8, "fists"); + addflag(lastrace->flags, F_HASATTACK, OT_FISTS, NA, NA, "2d5+8"); addflag(lastrace->flags, F_STARTOB, 90, NA, NA, "100-300 gold coins"); addflag(lastrace->flags, F_IFPCT, 65, NA, NA, NULL); addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "flaming greatsword of pyromania"); @@ -5379,11 +5581,10 @@ void initrace(void) { addflag(lastrace->flags, F_ARMOURRATING, 9, NA, NA, NULL); addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); - addflag(lastrace->flags, F_ACTIONSPEED, SP_FAST, NA, NA, ""); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_AVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_DEX, DX_DEXTROUS, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, ST_STRONG, NA, NULL); - addflag(lastrace->flags, F_HASATTACK, 1, 6, 4, "claws"); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d6+4"); addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "leather armour"); addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "1-40 gold coins"); addflag(lastrace->flags, F_WANTSBETTERWEP, B_TRUE, NA, NA, NULL); @@ -5406,7 +5607,7 @@ void initrace(void) { addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_DOPEY, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_DEX, DX_DEXTROUS, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, ST_STRONG, NA, NULL); - addflag(lastrace->flags, F_HASATTACK, 1, 6, 4, "claws"); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d6+4"); addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "leather armour"); addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "longbow"); addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "10-20 arrows"); @@ -5415,6 +5616,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, NA, NA, "shouts^a shout"); addflag(lastrace->flags, F_SEEINDARK, 2, NA, NA, NULL); addflag(lastrace->flags, F_PACKATTACK, 5, NA, 2, "gnoll"); + addflag(lastrace->flags, F_MINIONS, 75, 1, 2, "gnoll"); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); addrace(R_GNOLLMR, "gnoll marauder", 130, 'h', C_BROWN, MT_FLESH); @@ -5431,7 +5633,7 @@ void initrace(void) { addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_DOPEY, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_DEX, DX_DEXTROUS, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, ST_STRONG, NA, NULL); - addflag(lastrace->flags, F_HASATTACK, 1, 4, 2, "claws"); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d4+2"); addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "leather armour"); addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "spear"); addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "buckler"); @@ -5439,6 +5641,7 @@ void initrace(void) { addflag(lastrace->flags, F_SEEINDARK, 2, NA, NA, NULL); addflag(lastrace->flags, F_QUICKBITE, 1, 6, 2, NULL); addflag(lastrace->flags, F_PACKATTACK, 5, NA, 2, "gnoll"); + addflag(lastrace->flags, F_MINIONS, 75, 1, 2, "gnoll"); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); addrace(R_GOBLIN, "goblin", 20, 'g', C_BROWN, MT_FLESH); @@ -5449,7 +5652,7 @@ void initrace(void) { addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); - addflag(lastrace->flags, F_HASATTACK, 1, 4, NA, "claws"); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d4"); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_DOPEY, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, ST_AVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_DEX, DX_DEXTROUS, NA, NULL); @@ -5476,7 +5679,7 @@ void initrace(void) { addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); - addflag(lastrace->flags, F_HASATTACK, 1, 4, NA, "claws"); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d4+2"); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_DOPEY, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, ST_AVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_DEX, DX_DEXTROUS, NA, NULL); @@ -5488,6 +5691,7 @@ void initrace(void) { 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_MINIONS, 90, 1, 2, "goblin"); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); addrace(R_GOBLINSHOOTER, "goblin sharpshooter", 20, 'g', C_BROWN, MT_FLESH); @@ -5500,7 +5704,7 @@ void initrace(void) { addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); - addflag(lastrace->flags, F_HASATTACK, 1, 4, NA, "claws"); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d4"); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_DOPEY, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, ST_AVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_DEX, DX_DEXTROUS, NA, NULL); @@ -5513,6 +5717,7 @@ void initrace(void) { 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_MINIONS, 70, 1, 2, "goblin"); // TODO: can hide in shadows (need cansee function first) addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); @@ -5527,7 +5732,7 @@ 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_NORMAL, NA, NA, ""); - addflag(lastrace->flags, F_HASATTACK, 1, 4, NA, "claws"); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d4"); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_AVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, ST_AVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_DEX, DX_DEXTROUS, NA, NULL); @@ -5543,6 +5748,7 @@ void initrace(void) { addflag(lastrace->flags, F_CANCAST, OT_S_PAIN, NA, NA, NULL); addflag(lastrace->flags, F_HASSKILL, SK_SPELLCASTING, PR_ADEPT, NA, NULL); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MINIONS, 90, 1, 2, "goblin"); addrace(R_HOBGOBLIN, "hobgoblin", 90, 'g', C_GREEN, MT_FLESH); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -5554,7 +5760,7 @@ void initrace(void) { addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); - addflag(lastrace->flags, F_HASATTACK, 1, 6, NA, "claws"); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d6+2"); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_SMART, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, ST_MIGHTY, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_DEX, DX_DEXTROUS, NA, NULL); @@ -5569,6 +5775,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, NA, NA, "shouts^a shout"); addflag(lastrace->flags, F_SEEINDARK, 10, NA, NA, NULL); addflag(lastrace->flags, F_PHALANX, 5, NA, 1, "hobgoblin"); + addflag(lastrace->flags, F_MINIONS, 50, 1, 2, "goblin"); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); addrace(R_HOBGOBLINWAR, "hobgoblin warrior", 90, 'g', C_GREEN, MT_FLESH); @@ -5582,7 +5789,7 @@ void initrace(void) { addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); - addflag(lastrace->flags, F_HASATTACK, 1, 6, NA, "claws"); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d6+4"); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_SMART, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, ST_MIGHTY, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_DEX, DX_DEXTROUS, NA, NULL); @@ -5597,6 +5804,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, NA, NA, "shouts^a shout"); addflag(lastrace->flags, F_SEEINDARK, 10, NA, NA, NULL); addflag(lastrace->flags, F_PHALANX, 8, NA, 1, "hobgoblin"); + addflag(lastrace->flags, F_MINIONS, 50, 1, 4, "goblin"); addflag(lastrace->flags, F_NOFLEE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); @@ -5605,7 +5813,7 @@ void initrace(void) { addrace(R_KOBOLD, "kobold", 18, 'k', C_BROWN, MT_FLESH); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); - addflag(lastrace->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, 90, NA, NULL); addflag(lastrace->flags, F_POISONOUS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NUMAPPEAR, 1, 3, NA, ""); addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL); @@ -5613,7 +5821,7 @@ void initrace(void) { addflag(lastrace->flags, F_EVASION, 15, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); - addflag(lastrace->flags, F_HASATTACK, 0, 1, 4, "claws"); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d3"); addflag(lastrace->flags, F_STARTATT, A_STR, ST_WEAK, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_DOPEY, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_DEX, DX_NIMBLE, NA, NULL); @@ -5634,17 +5842,16 @@ void initrace(void) { addflag(lastrace->flags, F_POISONOUS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL); - addflag(lastrace->flags, F_RARITY, H_DUNGEON, 85, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); addflag(lastrace->flags, F_HITDICE, 1, NA, NA, NULL); addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL); addflag(lastrace->flags, F_ARMOURRATING, 10, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); - addflag(lastrace->flags, F_ACTIONSPEED, SP_FAST, NA, NA, ""); addflag(lastrace->flags, F_STARTATT, A_STR, ST_MIGHTY, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_DIMWITTED, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_DEX, DX_AVERAGE, NA, NULL); - addflag(lastrace->flags, F_HASATTACK, 1, 2, 0, "fists"); - addflag(lastrace->flags, F_HASATTACK, 1, 2, 0, "tail"); + addflag(lastrace->flags, F_HASATTACK, OT_FISTS, NA, NA, "1d2"); + addflag(lastrace->flags, F_HASATTACK, OT_TAIL, NA, NA, "1d3"); addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "club"); addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "buckler"); addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "1-10 gold coins"); @@ -5661,12 +5868,11 @@ void initrace(void) { addflag(lastrace->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); addflag(lastrace->flags, F_HITDICE, 6, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); - addflag(lastrace->flags, F_ACTIONSPEED, SP_FAST, NA, NA, ""); addflag(lastrace->flags, F_STARTATT, A_STR, ST_MIGHTY, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_DOPEY, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_DEX, DX_DEXTROUS, NA, NULL); - addflag(lastrace->flags, F_HASATTACK, 1, 5, 1, "claws"); - addflag(lastrace->flags, F_HASATTACK, 1, 4, 0, "tail"); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d5+1"); + addflag(lastrace->flags, F_HASATTACK, OT_TAIL, NA, NA, "1d4"); addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "1-50 gold coins"); addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "spear"); addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "1-2 javelins"); @@ -5700,6 +5906,8 @@ void initrace(void) { addflag(lastrace->flags, F_SEEINDARK, UNLIMITED, NA, NA, NULL); addflag(lastrace->flags, F_INDUCEFEAR, B_TRUE, 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_DEAF, B_TRUE, NA, NA, NULL); addrace(R_OGRE, "ogre", 160, 'O', C_BROWN, MT_FLESH); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -5710,7 +5918,8 @@ void initrace(void) { addflag(lastrace->flags, F_ARMOURRATING, 11, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); - addflag(lastrace->flags, F_HASATTACK, 2, 4, 0, "fists"); + addflag(lastrace->flags, F_HASATTACK, OT_FISTS, NA, NA, "2d4"); + addflag(lastrace->flags, F_HASATTACK, OT_FISTS, NA, NA, "2d4"); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_STUPID, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_DEX, DX_AVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, ST_MIGHTY, NA, NULL); @@ -5724,6 +5933,9 @@ void initrace(void) { addflag(lastrace->flags, F_STARTOB, 70, NA, NA, "leather armour"); addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "1-70 gold coins"); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MINIONS, 50, 1, 5, "orc"); + addflag(lastrace->flags, F_MINIONS, 20, 1, 2, "orc warrior"); + addflag(lastrace->flags, F_MORALE, 20, NA, NA, NULL); addrace(R_OGRESAVAGE, "ogre savage", 160, 'O', C_BROWN, MT_FLESH); lastrace->baseid = R_OGRE; @@ -5735,7 +5947,8 @@ void initrace(void) { addflag(lastrace->flags, F_ARMOURRATING, 11, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); - addflag(lastrace->flags, F_HASATTACK, 3, 4, 0, "claws"); + addflag(lastrace->flags, F_HASATTACK, OT_FISTS, NA, NA, "3d4"); + addflag(lastrace->flags, F_HASATTACK, OT_FISTS, NA, NA, "3d4"); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_STUPID, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_DEX, DX_AVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, ST_MIGHTY, NA, NULL); @@ -5749,6 +5962,9 @@ void initrace(void) { addflag(lastrace->flags, F_STARTOB, 80, NA, NA, "leather armour"); addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "1-70 gold coins"); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 20, NA, NA, NULL); + addflag(lastrace->flags, F_MINIONS, 50, 1, 5, "orc"); + addflag(lastrace->flags, F_MINIONS, 50, 1, 3, "orc warrior"); addrace(R_OGREWARHULK, "ogre warhulk", 160, 'O', C_BROWN, MT_FLESH); lastrace->baseid = R_OGRE; @@ -5760,7 +5976,8 @@ void initrace(void) { addflag(lastrace->flags, F_ARMOURRATING, 11, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); - addflag(lastrace->flags, F_HASATTACK, 2, 4, NA, "fists"); + addflag(lastrace->flags, F_HASATTACK, OT_FISTS, NA, NA, "4d4"); + addflag(lastrace->flags, F_HASATTACK, OT_FISTS, NA, NA, "4d4"); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_STUPID, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_DEX, DX_AVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, ST_MIGHTY, NA, NULL); @@ -5775,6 +5992,9 @@ void initrace(void) { addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "1-100 gold coins"); addflag(lastrace->flags, F_HEAVYBLOW, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); + addflag(lastrace->flags, F_MINIONS, 25, 1, 8, "orc"); + addflag(lastrace->flags, F_MINIONS, 25, 1, 2, "orc warrior"); addrace(R_ORC, "orc", 90, 'o', C_BROWN, MT_FLESH); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -5786,7 +6006,7 @@ void initrace(void) { addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_DOPEY, NA, NULL); - addflag(lastrace->flags, F_HASATTACK, 1, 4, 0, "claws"); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d4"); addflag(lastrace->flags, F_IFPCT, 70, NA, NA, NULL); addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "club"); addflag(lastrace->flags, F_ELSE, NA, NA, NA, NULL); @@ -5815,7 +6035,7 @@ void initrace(void) { addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_DOPEY, NA, NULL); - addflag(lastrace->flags, F_HASATTACK, 1, 4, 0, "claws"); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d4"); addflag(lastrace->flags, F_IFPCT, 70, NA, NA, NULL); addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "battleaxe"); addflag(lastrace->flags, F_ELSE, NA, NA, NA, NULL); @@ -5843,7 +6063,7 @@ void initrace(void) { addflag(lastrace->flags, F_EVASION, 0, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); - addflag(lastrace->flags, F_HASATTACK, 1, 4, 0, "claws"); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d4"); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_AVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTOBDT, 100, DT_SLASH, NA, NULL); addflag(lastrace->flags, F_STARTOBDT, 30, DT_BASH, NA, NULL); @@ -5886,6 +6106,7 @@ void initrace(void) { addflag(lastrace->flags, F_SEEINDARK, UNLIMITED, NA, NA, NULL); addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HASSKILL, SK_SS_MENTAL, PR_EXPERT, NA, NULL); + addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); addrace(R_SHADOWCAT, "shadowcat", 5, 'f', C_BLUE, MT_FLESH); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -5894,12 +6115,13 @@ void initrace(void) { addflag(lastrace->flags, F_HITDICE, 2, 3, NA, NULL); addflag(lastrace->flags, F_EVASION, 40, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); - addflag(lastrace->flags, F_ACTIONSPEED, SP_FAST, NA, NA, ""); - addflag(lastrace->flags, F_HASATTACK, 1, 4, 0, "claws"); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d4"); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d4"); addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, NA, NA, "hisses^a hiss"); addflag(lastrace->flags, F_SEEINDARK, 8, NA, NA, NULL); addflag(lastrace->flags, F_CANSEETHROUGHMAT, MT_GAS, NA, NA, NULL); addflag(lastrace->flags, F_AUTOCREATEOB, 1, NA, NA, "cloud of smoke"); + addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); addrace(R_OOZEGREY, "grey ooze", 10, 'j', C_GREY, MT_SLIME); addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "pool of slime"); @@ -5922,12 +6144,14 @@ 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_NOPACK, B_TRUE, NA, NA, NULL); - addflag(lastrace->flags, F_HASATTACK, 1, 6, 5, "acidattack"); + addflag(lastrace->flags, F_HASATTACK, OT_ACIDATTACK, NA, NA, "1d6+5"); addflag(lastrace->flags, F_SEEINDARK, UNLIMITED, NA, NA, NULL); addflag(lastrace->flags, F_SEEWITHOUTEYES, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOISETEXT, N_WALK, NA, NA, "^slurping."); addflag(lastrace->flags, F_DTIMMUNE, DT_ACID, B_TRUE, NA, NULL); addflag(lastrace->flags, F_AUTOCREATEOB, 0, NA, NA, "puddle of acid"); + addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); + addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); addrace(R_SPRITEFIRE, "fire sprite", 5, 'n', C_RED, MT_FIRE); addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "small fire"); @@ -5945,13 +6169,14 @@ void initrace(void) { addflag(lastrace->flags, F_MPREGEN, 1, NA, NA, NULL); addflag(lastrace->flags, F_CANCAST, OT_S_FIREDART, NA, NA, NULL); addflag(lastrace->flags, F_SPELLCASTTEXT, NA, NA, NA, "gestures"); - addflag(lastrace->flags, F_HASATTACK, 1, 3, 0, "claws"); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d3"); addflag(lastrace->flags, F_PRODUCESLIGHT, 2, NA, NA, NULL); addflag(lastrace->flags, F_DTIMMUNE, DT_FIRE, NA, NA, NULL); addflag(lastrace->flags, F_NOISETEXT, N_WALK, NA, NA, "^crackling flames."); addflag(lastrace->flags, F_HASSKILL, SK_SPELLCASTING, PR_NOVICE, NA, NULL); addflag(lastrace->flags, F_HASSKILL, SK_SS_FIRE, PR_BEGINNER, NA, NULL); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); addrace(R_TROLL, "troll", 100, 't', C_GREEN, MT_FLESH); @@ -5961,13 +6186,14 @@ void initrace(void) { addflag(lastrace->flags, F_HITDICE, 3, 0, NA, NULL); addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); - addflag(lastrace->flags, F_ACTIONSPEED, SP_FAST, NA, NA, ""); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_DIMWITTED, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, ST_STRONG, NA, NULL); - addflag(lastrace->flags, F_HASATTACK, 1, 6, 0, "claws"); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d6"); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d6"); addflag(lastrace->flags, F_REGENERATES, 2, NA, NA, NULL); addflag(lastrace->flags, F_SEEINDARK, 5, NA, NA, NULL); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); addrace(R_XAT, "xat", 2, 'x', C_BROWN, MT_FLESH); @@ -5982,7 +6208,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOBODYPART, BP_WEAPON, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_SECWEAPON, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_HANDS, NA, NA, NULL); - addflag(lastrace->flags, F_HASATTACK, 1, 3, 0, "teeth"); + addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d3"); // end monsters @@ -5994,11 +6220,11 @@ void initrace(void) { 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_VERYFAST, NA, NA, ""); - addflag(lastrace->flags, F_ACTIONSPEED, SP_FAST, NA, NA, ""); addflag(lastrace->flags, F_FLYING, B_TRUE, NA, NA, ""); addflag(lastrace->flags, F_HITDICE, 0, 2, NA, ""); - addflag(lastrace->flags, F_HASATTACK, 1, 2, 0, "teeth"); - addflag(lastrace->flags, F_HASATTACK, 1, 3, 0, "claws"); + addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d2"); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d3"); + addflag(lastrace->flags, F_MAXATTACKS, 1, NA, NA, NULL); 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); @@ -6028,12 +6254,13 @@ void initrace(void) { addflag(lastrace->flags, F_NOPACK, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, NA, NA, NULL); - addflag(lastrace->flags, F_HASATTACK, 0, 1, 4, "teeth"); + addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "0d1+4"); addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL); + addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); addrace(R_ANTS, "giant soldier ant", 5, 'a', C_BROWN, MT_FLESH); lastrace->baseid = R_ANT; addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); - addflag(lastrace->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, 65, NA, NULL); addflag(lastrace->flags, F_ANIMAL, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_ARMOURRATING, 9, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); @@ -6048,12 +6275,14 @@ void initrace(void) { 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_HASATTACK, 0, 1, 4, "teeth"); + addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "0d1+4"); addflag(lastrace->flags, F_CANWILL, OT_A_GRAB, NA, NA, "dam:1d8+3;"); addflag(lastrace->flags, F_CANWILL, OT_A_STINGACID, NA, NA, "dam:1d6+3;needgrab:1;"); addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL); + addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MINIONS, 50, 1, 3, "giant worker ant"); addrace(R_HAWKBLOOD, "blood hawk", 1, 'A', C_RED, MT_FLESH); // 'A' for Avian - addflag(lastrace->flags, F_RARITY, H_DUNGEON, 80, NA, ""); + addflag(lastrace->flags, F_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); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); @@ -6062,7 +6291,7 @@ 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, 1, 6, 5, "claws"); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d6+5"); 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); @@ -6072,8 +6301,9 @@ void initrace(void) { addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_CANWILL, OT_A_SWOOP, 3, 3, NULL); addflag(lastrace->flags, F_SWOOPRANGE, 5, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 5, NA, NA, NULL); addrace(R_HAWKFROST, "frost hawk", 1, 'A', C_CYAN, MT_FLESH); // 'A' for Avian - addflag(lastrace->flags, F_RARITY, H_DUNGEON, 75, NA, ""); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, 63, NA, ""); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_ANIMAL, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); @@ -6082,7 +6312,7 @@ 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, 10, NA, NA, ""); - addflag(lastrace->flags, F_HASATTACK, 1, 6, 5, "claws"); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d6+5"); addflag(lastrace->flags, F_EXTRADAM, DT_COLD, NA, NA, "1d6"); addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_WEAPON, NA, NA, NULL); @@ -6095,6 +6325,7 @@ void initrace(void) { addflag(lastrace->flags, F_SWOOPRANGE, 8, NA, NA, NULL); addflag(lastrace->flags, F_CANWILL, OT_S_COLDBURST, 2, 2, "pw:2;"); addflag(lastrace->flags, F_SPELLCASTTEXT, NA, NA, NA, "screeches"); + addflag(lastrace->flags, F_MORALE, 10, NA, NA, NULL); addrace(R_NEWT, "giant newt", 4, ':', C_BROWN, MT_FLESH); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 100, NA, NULL); addflag(lastrace->flags, F_COLDBLOOD, B_TRUE, NA, NA, NULL); @@ -6112,6 +6343,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOPACK, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_DTRESIST, DT_FIRE, B_TRUE, NA, NULL); + addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); addrace(R_RAT, "giant rat", 3, 'r', C_BROWN, MT_FLESH); addflag(lastrace->flags, F_ANIMAL, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -6122,8 +6354,9 @@ void initrace(void) { addflag(lastrace->flags, F_MOVESPEED, SP_FAST, NA, NA, ""); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 90, NA, ""); addflag(lastrace->flags, F_HITDICE, 0, 1, NA, ""); - addflag(lastrace->flags, F_HASATTACK, 1, 2, 0, "teeth"); - addflag(lastrace->flags, F_HASATTACK, 1, 3, 0, "claws"); + addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d2"); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d3"); + addflag(lastrace->flags, F_MAXATTACKS, 1, NA, NA, NULL); addflag(lastrace->flags, F_EVASION, 20, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_WEAPON, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_SECWEAPON, NA, NA, NULL); @@ -6144,7 +6377,7 @@ void initrace(void) { addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_HITDICE, 2, NA, NA, ""); - addflag(lastrace->flags, F_HASATTACK, 1, 4, 0, "teeth"); + addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d4"); addflag(lastrace->flags, F_HITCONFER, F_POISONED, SC_POISON, 20, "3-5"); addflag(lastrace->flags, F_NOBODYPART, BP_WEAPON, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_SECWEAPON, NA, NA, NULL); @@ -6155,16 +6388,17 @@ void initrace(void) { addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_DTVULN, DT_COLD, NA, NA, NULL); addflag(lastrace->flags, F_NOISETEXT, N_WALK, NA, NA, "^hissing"); + addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); addrace(R_WOLF, "wolf", 10, 'd', C_BROWN, MT_FLESH); addflag(lastrace->flags, F_ANIMAL, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); - addflag(lastrace->flags, F_ACTIONSPEED, SP_FAST, NA, NA, ""); addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_FAST, NA, NA, ""); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 80, NA, ""); addflag(lastrace->flags, F_HITDICE, 2, 0, NA, ""); - addflag(lastrace->flags, F_HASATTACK, 1, 5, 0, "teeth"); - addflag(lastrace->flags, F_HASATTACK, 1, 5, 0, "claws"); + addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d5"); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d5"); + addflag(lastrace->flags, F_MAXATTACKS, 1, NA, NA, NULL); 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); @@ -6195,6 +6429,7 @@ void initrace(void) { addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_PRODUCESLIGHT, 2, NA, NA, NULL); addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL); + addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); addrace(R_GIANTFLY, "giant fly", 1, 'i', C_GREY, MT_FLESH); lastrace->baseid = R_GIANTFLY; addflag(lastrace->flags, F_INSECT, B_TRUE, NA, NA, NULL); @@ -6207,7 +6442,7 @@ void initrace(void) { addflag(lastrace->flags, F_RARITY, H_DUNGEON, 85, NA, ""); addflag(lastrace->flags, F_HITDICE, 1, 0, NA, ""); addflag(lastrace->flags, F_EVASION, 50, NA, NA, NULL); - addflag(lastrace->flags, F_HASATTACK, 1, 2, 0, "teeth"); + addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d2"); addflag(lastrace->flags, F_NOBODYPART, BP_WEAPON, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_SECWEAPON, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_SHOULDERS, NA, NA, NULL); @@ -6217,6 +6452,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, NA, NA, "buzzes angrily^an angry buzzing"); addflag(lastrace->flags, F_NOISETEXT, N_FLY, NA, NA, "^buzzing"); addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL); + addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); addrace(R_GIANTBLOWFLY, "giant blowfly", 2, 'i', C_WHITE, MT_FLESH); lastrace->baseid = R_GIANTFLY; addflag(lastrace->flags, F_INSECT, B_TRUE, NA, NA, NULL); @@ -6225,12 +6461,11 @@ void initrace(void) { addflag(lastrace->flags, F_NUMAPPEAR, 1, 2, NA, ""); addflag(lastrace->flags, F_MOVESPEED, SP_VERYFAST, NA, NA, ""); addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL); - addflag(lastrace->flags, F_ACTIONSPEED, SP_FAST, NA, NA, ""); addflag(lastrace->flags, F_FLYING, B_TRUE, NA, NA, ""); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 60, NA, ""); addflag(lastrace->flags, F_HITDICE, 1, 1, NA, ""); addflag(lastrace->flags, F_EVASION, 40, NA, NA, NULL); - addflag(lastrace->flags, F_HASATTACK, 1, 3, 0, "teeth"); + addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d3"); 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); @@ -6241,6 +6476,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, NA, NA, "buzzes angrily^an angry buzzing"); addflag(lastrace->flags, F_NOISETEXT, N_FLY, NA, NA, "^buzzing"); addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL); + addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); addrace(R_GLOWBUG, "glowbug", 1, 'i', C_WHITE, MT_FLESH); addflag(lastrace->flags, F_INSECT, B_TRUE, NA, NA, NULL); @@ -6252,7 +6488,7 @@ void initrace(void) { addflag(lastrace->flags, F_RARITY, H_DUNGEON, 85, NA, ""); addflag(lastrace->flags, F_HITDICE, 1, 0, NA, ""); addflag(lastrace->flags, F_EVASION, 60, NA, NA, NULL); - addflag(lastrace->flags, F_HASATTACK, 1, 2, 0, "zapper"); + addflag(lastrace->flags, F_HASATTACK, OT_ZAPPER, NA, NA, "1d2"); addflag(lastrace->flags, F_NOBODYPART, BP_WEAPON, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_SECWEAPON, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_SHOULDERS, NA, NA, NULL); @@ -6262,6 +6498,7 @@ void initrace(void) { addflag(lastrace->flags, F_PRODUCESLIGHT, 2, NA, NA, NULL); addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL); addflag(lastrace->flags, F_NOISETEXT, N_FLY, NA, NA, "^buzzing"); + addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); // undead addrace(R_ZOMBIE, "zombie", 50, 'Z', C_BLUE, MT_FLESH); @@ -6287,6 +6524,8 @@ 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_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_SKELETON, "skeleton", 20, 'Z', C_GREY, MT_BONE); addflag(lastrace->flags, F_UNDEAD, B_TRUE, NA, NA, NULL); @@ -6310,6 +6549,8 @@ void initrace(void) { addflag(lastrace->flags, F_DTVULN, DT_BASH, NA, NA, NULL); addflag(lastrace->flags, F_DTVULN, DT_HOLY, NA, NA, NULL); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); addrace(R_GHAST, "ghast", 50, 'Z', C_MAGENTA, MT_FLESH); @@ -6323,8 +6564,7 @@ void initrace(void) { 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_HASATTACK, 1, 4, 4, "teeth"); - addflag(lastrace->flags, F_HASATTACK, NA, NA, NA, "strong paralyzing touch"); + addflag(lastrace->flags, F_HASATTACK, OT_TOUCHPARALYZE2, NA, NA, "0d1+0"); 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); @@ -6332,6 +6572,8 @@ void initrace(void) { addflag(lastrace->flags, F_DTVULN, DT_HOLY, NA, NA, NULL); addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, NA, NA, NULL); addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); addrace(R_GHOUL, "ghoul", 50, 'Z', C_BLUE, MT_FLESH); addflag(lastrace->flags, F_UNDEAD, B_TRUE, NA, NA, NULL); @@ -6345,8 +6587,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, ""); - addflag(lastrace->flags, F_HASATTACK, 1, 5, 3, "teeth"); - addflag(lastrace->flags, F_HASATTACK, NA, NA, NA, "paralyzing touch"); + addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d5+3"); + addflag(lastrace->flags, F_HASATTACK, OT_TOUCHPARALYZE, NA, NA, "0d1+0"); 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); @@ -6354,6 +6596,8 @@ void initrace(void) { addflag(lastrace->flags, F_DTVULN, DT_HOLY, NA, NA, NULL); addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, B_COVETS, NA, NULL); addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); // special monsters addrace(R_GASCLOUD, "cloud of gas", 0.1, '}', C_GREY, MT_GAS); @@ -6380,6 +6624,8 @@ void initrace(void) { addflag(lastrace->flags, F_SEEINDARK, 4, NA, NA, NULL); addflag(lastrace->flags, F_DTIMMUNE, DT_ALL, 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_DANCINGWEAPON, "dancing weapon", 0, ')', C_GREY, MT_METAL); addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL); @@ -6400,6 +6646,8 @@ void initrace(void) { addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SEEINDARK, UNLIMITED, NA, NA, NULL); addflag(lastrace->flags, F_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); } int isairborne(lifeform_t *lf) { @@ -6900,7 +7148,8 @@ void makenauseated(lifeform_t *lf, int amt, int howlong) { flag_t *f; if (lfhasflag(lf, F_UNDEAD)) return; - if (isdead(lf)) return; + if (!hasbp(lf, BP_HEAD)) return; // can't smell with no head + if (lfhasflag(lf, F_UNDEAD)) return; if (!lfhasflag(lf, F_HUMANOID)) return; @@ -6967,6 +7216,8 @@ void makenoise(lifeform_t *lf, enum NOISETYPE nid) { if (strlen(movetext)) { noise(lf->cell, lf, movetext, NULL); } + } else if (nid == N_WARCRY) { + noise(lf->cell, lf, "a blood-curdling war cry!", "shouts a blood-curdling war-cry!"); } } @@ -7277,7 +7528,7 @@ int pickup(lifeform_t *lf, object_t *what, int howmany, int fromground) { if (!canpickup(lf, what,howmany)){ // tell the player why! - if (lf->controller == C_PLAYER) { + if (isplayer(lf)) { switch (reason) { case E_INSUBSTANTIAL: msg("Your hand passes straight through %s.",obname); @@ -7345,7 +7596,7 @@ int pickup(lifeform_t *lf, object_t *what, int howmany, int fromground) { testammo(lf, o); } else { // tell the player why! - if (lf->controller == C_PLAYER) { + if (isplayer(lf)) { switch (reason) { case E_NOSPACE: msg("Your pack is too full to fit any more objects."); @@ -7387,6 +7638,15 @@ void poison(lifeform_t *lf, int howlong, char *fromwhat) { (f->lifetime > 0) ){ f->lifetime += howlong; found = B_TRUE; + // announce - announceflaggain won't be called + // since this isn't a new flag. + if (isplayer(lf)) { + msg("You feel more sick."); + } else if (cansee(player, lf)) { + char lfname[BUFLEN]; + getlfname(lf, lfname); + msg("%s looks even more sick.", lfname); + } } } @@ -7502,7 +7762,7 @@ int push(lifeform_t *lf, object_t *o, int dir) { moveto(lf, obcell, B_TRUE); // announce - if (lf->controller == C_PLAYER) { + if (isplayer(lf)) { msg("You push %s.", obname); } else if (haslos(player, dstcell)) { char buf[BUFLEN]; @@ -7577,7 +7837,7 @@ void startresting(lifeform_t *lf, int willtrain) { addflag(lf->flags, F_RESTING, B_TRUE, NA, traincounter, NULL); - if (lf->controller == C_PLAYER) { + if (isplayer(lf)) { msg("You start %s...",(traincounter == NA) ? "resting" : "training"); drawmsg(); drawcursor(); @@ -7781,6 +8041,8 @@ int rollstat(lifeform_t *lf, enum ATTRIB attr) { // returns TRUE if something happened int scare(lifeform_t *lf, lifeform_t *scarer, int howlong) { + int nfailures = 0; + int i; if (!scarer) return B_FALSE; // immune to fear? @@ -7788,24 +8050,34 @@ int scare(lifeform_t *lf, lifeform_t *scarer, int howlong) { return B_FALSE; } // not intelligent enough to be scared? - if (getdexname(getattr(scarer, A_IQ), NULL) <= IQ_VEGETABLE) { + if (getiqname(getattr(scarer, A_IQ), NULL) <= IQ_VEGETABLE) { return B_FALSE; } - if (!skillcheck(lf, SC_MORALE, 15, 0)) { - flag_t *f; - // already fleeing? - f = hasflagval(lf->flags, F_FLEEFROM, scarer->id, NA, NA, NULL); - if (f) { - // update time - if (f->lifetime != PERMENANT) { - if (f->lifetime < howlong) { - f->lifetime = howlong; - } - } - } else { - addtempflag(lf->flags, F_FLEEFROM, scarer->id, NA, NA, NULL, howlong); + // three checks + nfailures = 0; + for (i = 0; i < 3; i++) { + if (!skillcheckvs(lf, SC_MORALE, isbleeding(lf) ? 0 : 5 , scarer, SC_MORALE, 0)) { + nfailures++; } + } + + if (nfailures == 1) { + // cower + fleefrom(lf, scarer, rnd(1,3)); + return B_TRUE; + } else if (nfailures == 2) { + // flee for given time + fleefrom(lf, scarer, howlong); + return B_TRUE; + } else if (nfailures == 3) { + object_t *wep; + // drop weapon and flee for given time + wep = getweapon(lf); + if (wep) { + drop(wep, ALL); + } + fleefrom(lf, scarer, howlong); return B_TRUE; } return B_FALSE; @@ -8075,6 +8347,7 @@ void setlastdam(lifeform_t *lf, char *buf) { } void initskills(void) { + addskill(SK_ARMOUR, "Armour", "Reduces your evasion penalty for wearing armour."); addskill(SK_ATHLETICS, "Athletics", "Assists with sprinting and exhaustion recovery."); addskill(SK_BACKSTAB, "Backstab", "Lets you inflict massive damage with stabs when unseen."); addskill(SK_FIRSTAID, "First Aid", "Increases your healing rate and reduces duration of poison."); @@ -8181,6 +8454,7 @@ int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *r int roll; int luckmod = 0; char mbuf[BUFLEN]; + flag_t *f; if (lfhasflag(lf, F_DEBUG)) { db = B_TRUE; @@ -8200,10 +8474,15 @@ int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *r attrib = getattr(lf, A_DEX); break; case SC_IQ: - case SC_MORALE: case SC_WILL: attrib = getattr(lf, A_IQ); break; + case SC_MORALE: // based on level/hitdice and size. + attrib = (lf->hp / 4); + attrib += ((float)getlfsize(lf) * 1.5); + f = lfhasflag(lf, F_MORALE); + if (f) attrib += f->val[0]; + break; case SC_SLIP: attrib = getattr(lf, A_DEX); break; @@ -8234,8 +8513,8 @@ int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *r if (getequippedob(lf->pack, BP_FEET)) { othermod += 5; } - if (lfhasflag(lf, F_STABILITY)) { - othermod += 10; + if (lfhasflag(lf, F_STABILITY) || !hasbp(lf, BP_FEET)) { + othermod += 20; } } else if (ct == SC_OPENLOCKS) { enum SKILLLEVEL slev; @@ -8318,6 +8597,12 @@ int skillcheckvs(lifeform_t *lf1, enum CHECKTYPE ct1, int mod1, lifeform_t *lf2, int slipon(lifeform_t *lf, object_t *o) { char obname[BUFLEN]; char lfname[BUFLEN]; + + + if (lfhasflag(lf, F_STABILITY) || !hasbp(lf, BP_FEET)) { + return B_TRUE; + } + getlfname(lf,lfname); getobname(o, obname, 1); // slip! @@ -8454,8 +8739,13 @@ void stopresting(lifeform_t *lf) { if (f->val[2] != NA) { training = B_TRUE; } + + /* + if (training && f->val[2] == 0) { killflag(f); + */ //lf->timespent = 0; + killflag(f); if (isplayer(lf)) { msg("Your %s is interrupted!", training ? "training" : "rest"); } else if (cansee(player, lf)) { @@ -8507,7 +8797,7 @@ int takeoff(lifeform_t *lf, object_t *o) { if (!cantakeoff(lf, o)) { switch (reason) { case E_CURSED: - if (lf->controller == C_PLAYER) { + if (isplayer(lf)) { msg("Your %s appears to be stuck to you!", noprefix(obname)); o->blessknown = B_TRUE; } @@ -8515,12 +8805,12 @@ int takeoff(lifeform_t *lf, object_t *o) { taketime(lf, getactspeed(lf)); break; case E_NOTEQUIPPED: - if (lf->controller == C_PLAYER) { + if (isplayer(lf)) { msg("You are not wearing that!"); } break; default: - if (lf->controller == C_PLAYER) { + if (isplayer(lf)) { msg("For some reason, you cannot remove your %s!", noprefix(obname)); } // still take time @@ -8536,7 +8826,7 @@ int takeoff(lifeform_t *lf, object_t *o) { taketime(lf, getactspeed(lf)); if ((gamemode == GM_GAMESTARTED)) { - if (lf->controller == C_PLAYER) { + if (isplayer(lf)) { msg("You take off %s.", obname); } else if (cansee(player, lf)) { getlfname(lf, buf); @@ -8620,57 +8910,20 @@ int throwat(lifeform_t *thrower, object_t *o, cell_t *where) { } // lf effects which happen every xx ticks +// IMPORTANT - don't call taketime() during this function. void timeeffectslf(lifeform_t *lf) { - flag_t *f; object_t *o, *nexto; - - f = hasflag(lf->flags, F_POISONED); - if (f) { - // chance of fighting it off - gets easier over time. - // - if (skillcheck(lf, SC_POISON, (f->lifetime * 9), 0 )) { - killflag(f); - } else { - // chance of losing hp - if (rnd(1,100) <= POISONDAMCHANCE) { - char buf[BUFLEN]; - if (isplayer(lf)) { - msg("You vomit violently."); - } else if (cansee(player, lf)) { - char lfname[BUFLEN]; - getlfname(lf, lfname); - msg("%s vomits violently.", lfname); - } - sprintf(buf, "poisoning^from %s",f->text); - losehp(lf, POISONDAM, DT_DIRECT, NULL, buf); - taketime(lf,5); - - addob(lf->cell->obpile, "pool of vomit"); - - loseconcentration(lf); - } - } - } - f = hasflag(lf->flags, F_NAUSEATED); - if (f) { - // chance of being delayed - if (rnd(0,3) == 0) { - if (isplayer(lf)) { - msg("You %s!", rnd(0,1) ? "retch" : "gag"); - } else if (cansee(player, lf)) { - char lfname[BUFLEN]; - getlfname(lf, lfname); - msg("%s %s.", lfname, rnd(0,1) ? "retches" : "gags"); - } - taketime(lf,5); - - loseconcentration(lf); - } - } + flag_t *f; // decrement flags timeeffectsflags(lf->flags); + f = lfhasflag(lf, F_INTERRUPTED); + if (f) { + interrupt(lf); + killflag(f); + } + if (isdead(lf)) { return; } @@ -8759,6 +9012,8 @@ void turneffectslf(lifeform_t *lf) { } } + + if (lfhasflag(lf, F_MAGSHIELD)) { object_t *nexto; // metal weapons? @@ -8850,7 +9105,52 @@ void turneffectslf(lifeform_t *lf) { } } - // any potentiall damaging effects have to go after here... + // IMPORTANT: any potentiall damaging effects have to go after here... + f = hasflag(lf->flags, F_POISONED); + if (f) { + // chance of fighting it off - gets easier over time. + // + if (skillcheck(lf, SC_POISON, (f->lifetime * 9), 0 )) { + killflag(f); + } else { + // chance of losing hp + if (rnd(1,100) <= POISONDAMCHANCE) { + char buf[BUFLEN]; + if (isplayer(lf)) { + msg("You vomit violently."); + } else if (cansee(player, lf)) { + char lfname[BUFLEN]; + getlfname(lf, lfname); + msg("%s vomits violently.", lfname); + } + sprintf(buf, "poisoning^from %s",f->text); + losehp(lf, POISONDAM, DT_DIRECT, NULL, buf); + taketime(lf,5); + + addob(lf->cell->obpile, "pool of vomit"); + + loseconcentration(lf); + } + } + } + + f = hasflag(lf->flags, F_NAUSEATED); + if (f) { + // chance of being delayed + if (rnd(0,3) == 0) { + if (isplayer(lf)) { + msg("You %s!", rnd(0,1) ? "retch" : "gag"); + } else if (cansee(player, lf)) { + char lfname[BUFLEN]; + getlfname(lf, lfname); + msg("%s %s.", lfname, rnd(0,1) ? "retches" : "gags"); + } + taketime(lf,5); + + loseconcentration(lf); + } + } + if (lfhasflag(lf, F_FROZEN)) { // melt... if (rnd(1,2)) { @@ -8970,10 +9270,13 @@ void turneffectslf(lifeform_t *lf) { continue; } } - if (f->id == F_CHARMEDBY) { - lifeform_t *cb; - cb = findlf(NULL, f->val[0]); - if (!cb) { + + if ((f->id == F_CHARMEDBY) || + (f->id == F_FLEEFROM) || + (f->id == F_NOFLEEFROM)) { + lifeform_t *lf; + lf = findlf(NULL, f->val[0]); + if (!lf) { killflag(f); continue; } @@ -9038,7 +9341,7 @@ int touch(lifeform_t *lf, object_t *o) { // want to decrement it each turn. f->val[0]--; if (f->val[0] <= 0) { - if (lf->controller == C_PLAYER) { + if (isplayer(lf)) { msg("Your hands stop glowing blue."); } else if (cansee(player, lf)) { getlfname(lf, buf); @@ -9099,7 +9402,7 @@ int unweild(lifeform_t *lf, object_t *o) { if (!cantakeoff(lf, o)) { switch (reason) { case E_CURSED: - if (lf->controller == C_PLAYER) { + if (isplayer(lf)) { msg("Your %s appears to be stuck to your hand!", noprefix(obname)); if (!o->blessknown) { o->blessknown = B_TRUE; @@ -9107,12 +9410,12 @@ int unweild(lifeform_t *lf, object_t *o) { } break; case E_NOTEQUIPPED: - if (lf->controller == C_PLAYER) { + if (isplayer(lf)) { msg("You are not weilding that!"); } break; default: - if (lf->controller == C_PLAYER) { + if (isplayer(lf)) { msg("For some reason, you cannot stop weilding your %s!", noprefix(obname)); } break; @@ -9126,7 +9429,7 @@ int unweild(lifeform_t *lf, object_t *o) { // unweilding doesn't take any time if (gamemode == GM_GAMESTARTED) { - if (lf->controller == C_PLAYER) { + if (isplayer(lf)) { msg("You are no longer weilding %s.", obname); } else if (cansee(player, lf)) { getlfname(lf, buf); @@ -9180,9 +9483,7 @@ int usestairs(lifeform_t *lf, object_t *o) { flag_t *f; map_t *curmap; map_t *newmap; - int newx,newy; cell_t *newcell; - objecttype_t *ot; int dir; int newdepth; char lfname[BUFLEN]; @@ -9234,16 +9535,9 @@ int usestairs(lifeform_t *lf, object_t *o) { } } - // do stairs already go somewhere? - f = hasflag(o->flags, F_MAPLINK); - if (f) { - newmap = findmap(f->val[0]); - newx = f->val[1]; - newy = f->val[2]; - assert(newmap); - // find dst x/y - newcell = getcellat(newmap, newx, newy); - } else { + // do stairs go somewhere? + newcell = getstairdestination(o); + if (!newcell) { if (isportal) { // unconnected portal if (isplayer(lf)) msg("This portal doesn't seem to go anywhere."); @@ -9251,26 +9545,15 @@ int usestairs(lifeform_t *lf, object_t *o) { // is there already a level of the correct depth? newmap = findmapofdepth(newdepth); if (newmap) { - // find other end of stairs - ot = getoppositestairs(o->type); - newcell = findobinmap(newmap, ot->id); - assert(newcell); - // link these stairs to it - addflag_real(o->flags, F_MAPLINK, newmap->id, newcell->x, newcell->y, NULL, PERMENANT, B_UNKNOWN, -1); + dblog("ERROR - unlinked stairs!\n"); + msg("ERROR - unlinked stairs!\n"); } else { - // need to create a new map! - - // get return stair ob type - ot = getoppositestairs(o->type); - - // generate a new map! + // generate a new map! this will fill in the destination of our stairs newmap = addmap(); - createmap(newmap, newdepth, curmap->habitat, curmap, ot); + createmap(newmap, newdepth, curmap->habitat); - newcell = findobinmap(newmap, ot->id); - assert(newcell); - // link current map to new one - addflag_real(o->flags, F_MAPLINK, newmap->id, newcell->x, newcell->y, NULL, PERMENANT, B_UNKNOWN, -1); + // NOW our stairs should have a destination + newcell = getstairdestination(o); } } } @@ -9358,11 +9641,18 @@ int validateraces(void) { cell_t fakecell; map_t fakemap; // make a fake cell + fakemap.lf = NULL; + fakemap.lastlf = NULL; setcelltype(&fakecell, CT_CORRIDOR); fakecell.lf = NULL; fakecell.map = &fakemap; for (r = firstrace ; r ; r = r->next) { + lifeform_t *lf; + + // add a fake lf + lf = addlf(&fakecell, r->id, 1); + if (!hasflag(r->flags, F_SIZE)) { printf("ERROR in race '%s' - missing F_SIZE.\n", r->name); goterror = B_TRUE; @@ -9370,16 +9660,13 @@ int validateraces(void) { } for (f = r->flags->first ; f ; f = f->next) { if (f->id == F_HASATTACK) { - if (!f->text || (strlen(f->text) == 0)) { - printf("ERROR in race '%s' - F_HASATTACK with zero length text.\n", r->name); + if (!findot(f->val[0])) { + printf("ERROR in race '%s' - F_HASATTACK with bad object.\n", r->name); + goterror = B_TRUE; + } + if (!strlen(f->text)) { + printf("ERROR in race '%s' - F_HASATTACK with no damage value.\n", r->name); goterror = B_TRUE; - } else { - objecttype_t *ot; - ot = findotn(f->text); - if (!ot) { - printf("ERROR in race '%s' - F_HASATTACK with bad object: '%s'\n", r->name,f->text); - goterror = B_TRUE; - } } } else if (f->id == F_STARTOB) { if (!f->text || (strlen(f->text) == 0)) { @@ -9397,9 +9684,6 @@ int validateraces(void) { (school == SS_ALLOMANCY) || (school == SS_MENTAL) ) { int power; - lifeform_t *lf; - // add a fake lf - lf = addlf(&fakecell, r->id, 1); //power = (1 + ff->val[1]) / getspelllevel(f->val[0]); power = getspellpower(lf, f->val[0]); if (power <= 0) { @@ -9412,7 +9696,6 @@ int validateraces(void) { } goterror = B_TRUE; } - killlf(lf); } else { objecttype_t *sp; sp = findot(f->val[0]); @@ -9437,6 +9720,14 @@ int validateraces(void) { } } } + + + // xp check... + calcxp(lf); + + // remove a fake lf + killlf(lf); + } @@ -9533,11 +9824,12 @@ int rest(lifeform_t *lf, int onpurpose) { if (rf->val[2] == 0) { // ask about gaining skills if (isplayer(lf)) msg("You finish training."); + killflag(rf); // kill resting/training flag. + if (lf->skillpoints || getattpoints(player)) { if (isplayer(lf)) more(); enhanceskills(lf); } - killflag(rf); if (hasjob(lf, J_WIZARD)) { objecttype_t *ot; char ch = 'a'; @@ -9577,6 +9869,7 @@ int rest(lifeform_t *lf, int onpurpose) { if (isplayer(lf)) msg("Not learning anything."); } } + } } else { // resting @@ -9591,7 +9884,7 @@ int rest(lifeform_t *lf, int onpurpose) { if (hf) killflag(hf); } if (!lfhasflag(lf, F_RESTUNTILHP) && !lfhasflag(lf, F_RESTUNTILMP)) { - msg("You finish resting."); + if (isplayer(lf)) msg("You finish resting."); killflag(rf); wantclearmsg = B_FALSE; } @@ -9627,7 +9920,7 @@ int wear(lifeform_t *lf, object_t *o) { // check for already equipped first! f = hasflag(o->flags, F_EQUIPPED); if (f) { - if (lf->controller == C_PLAYER) { + if (isplayer(lf)) { if (f->val[0] == BP_WEAPON) { msg("You're weilding that!"); } else { @@ -9655,7 +9948,7 @@ int wear(lifeform_t *lf, object_t *o) { } if (nparts == 0) { - if (lf->controller == C_PLAYER) { + if (isplayer(lf)) { msg("You can't wear that!"); } return B_TRUE; @@ -9696,7 +9989,7 @@ int wear(lifeform_t *lf, object_t *o) { // find what else is there inway = getequippedob(lf->pack, f->val[0]); getobname(inway,buf, 1); - if (lf->controller == C_PLAYER) { + if (isplayer(lf)) { int ch; char buf2[BUFLEN]; // take offending item off first - this takes extra time. @@ -9750,6 +10043,8 @@ int wear(lifeform_t *lf, object_t *o) { addflag(o->flags, F_EQUIPPED, bp, -1, -1, NULL); taketime(lf, getactspeed(lf)); + + maketried(o->type->id); /* if (isplayer(lf)) { @@ -9776,7 +10071,7 @@ int wear(lifeform_t *lf, object_t *o) { } if ((gamemode == GM_GAMESTARTED) && lf->created) { - if (lf->controller == C_PLAYER) { + if (isplayer(lf)) { msg("You are now wearing %s.", obname); } else if (cansee(player, lf)) { getlfname(lf, buf); @@ -9786,7 +10081,7 @@ int wear(lifeform_t *lf, object_t *o) { } if (o->blessed == B_CURSED) { - if (lf->controller == C_PLAYER) { + if (isplayer(lf)) { msg("Oh no! The %s releases a pulse of evil!", noprefix(obname)); o->blessknown = B_TRUE; } else if (cansee(player, lf)) { @@ -9831,7 +10126,7 @@ int weild(lifeform_t *lf, object_t *o) { if (!canweild(lf, o)) { if ((gamemode == GM_GAMESTARTED) && lf->created) { - if (lf->controller == C_PLAYER) { + if (isplayer(lf)) { switch (reason) { case E_ALREADYUSING: msg("You are already weilding that!"); @@ -10006,7 +10301,11 @@ int weild(lifeform_t *lf, object_t *o) { if (hasflag(o->flags, F_TWOHANDED)) { addflag(o->flags, F_EQUIPPED, otherloc, -1, -1, NULL); } + taketime(lf, getactspeed(lf)); + + maketried(o->type->id); + if ((gamemode == GM_GAMESTARTED) && lf->created && (lf->race->id != R_DANCINGWEAPON)) { if (isplayer(lf)) { char buf2[BUFLEN]; @@ -10039,7 +10338,7 @@ int weild(lifeform_t *lf, object_t *o) { touch(lf, o); if (o->blessed == B_CURSED) { - if (lf->controller == C_PLAYER) { + if (isplayer(lf)) { msg("Oh no! The %s releases a pulse of evil!", strchr(buf, ' ')+1); o->blessknown = B_TRUE; } else if (cansee(player, lf)) { diff --git a/lf.h b/lf.h index a18d142..c31054c 100644 --- a/lf.h +++ b/lf.h @@ -47,6 +47,7 @@ skill_t *findskill(enum SKILL id); skill_t *findskillbyname(char *name); enum SKILLLEVEL findskilllevbyname(char *name); int flee(lifeform_t *lf); +void fleefrom(lifeform_t *lf, lifeform_t *enemy, int howlong); int freezelf(lifeform_t *freezee, lifeform_t *freezer, int howlong); void gainhp(lifeform_t *lf, int amt); void gainlevel(lifeform_t *lf); @@ -77,7 +78,7 @@ enum HUNGER gethungerlevel(int hunger); char * gethungername(enum HUNGER hunger, char *buf); int gethungerval(lifeform_t *lf); job_t *getjob(lifeform_t *lf); -int getlfaccuracy(lifeform_t *lf); +int getlfaccuracy(lifeform_t *lf, object_t *wep); enum LFCONDITION getlfcondition(lifeform_t *lf); int getnightvisrange(lifeform_t *lf); char *getlfconditionname(enum LFCONDITION cond); diff --git a/log.txt b/log.txt index ea04015..f4c126e 100644 --- a/log.txt +++ b/log.txt @@ -8,9 +8,11 @@ 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 @@ -20,10 +22,11 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 -got 10 possibilities. +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 @@ -33,10 +36,11 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 -got 10 possibilities. +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 @@ -46,10 +50,11 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 -got 10 possibilities. +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 @@ -59,10 +64,11 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 -got 10 possibilities. +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 @@ -72,10 +78,11 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 -got 10 possibilities. +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 @@ -85,10 +92,11 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 -got 10 possibilities. +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 @@ -98,10 +106,11 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 -got 10 possibilities. +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 @@ -111,10 +120,11 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 -got 10 possibilities. +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 @@ -124,10 +134,11 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 -got 10 possibilities. +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 @@ -137,10 +148,11 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 -got 10 possibilities. +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 @@ -150,10 +162,11 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 -got 10 possibilities. +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 @@ -163,10 +176,11 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 -got 10 possibilities. +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 @@ -176,10 +190,11 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 -got 10 possibilities. +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 @@ -189,10 +204,11 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 -got 10 possibilities. +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 @@ -202,24 +218,61 @@ finding random lf with rarity val 85-100 -> possibility: brown snake, rarity=85 -> possibility: giant fly, rarity=85 -> possibility: glowbug, rarity=85 -got 10 possibilities. +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. rollhitdice() - rolling 2d4 + 2 -rollhitdice() - mod is +32% -rollhitdice() ---- die 1/2 == 4 -rollhitdice() ---- die 2/2 == 4 -TOTAL: 8 - -> modified to: 10 +rollhitdice() - mod is +44% +rollhitdice() ---- die 1/2 == 6 +rollhitdice() ---- die 2/2 == 3 +TOTAL: 9 + -> modified to: 12 givejob() starting. -processing normal flag: 200 -processing normal flag: 157 -processing normal flag: 157 -processing normal flag: 157 -processing normal flag: 157 -processing normal flag: 157 -processing normal flag: 157 -processing normal flag: 157 -processing normal flag: 157 +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 @@ -230,92 +283,437 @@ 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: 229 -processing normal flag: 229 -processing normal flag: 229 -processing normal flag: 229 -processing normal flag: 229 -processing normal flag: 229 -processing normal flag: 229 -processing normal flag: 229 -processing normal flag: 229 -processing normal flag: 229 -processing normal flag: 229 -processing normal flag: 229 -processing normal flag: 229 -processing normal flag: 229 -processing normal flag: 229 -processing normal flag: 229 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 -processing normal flag: 227 +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: 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 +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 ------ + +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 +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 diff --git a/map.c b/map.c index 7bf04a9..aa5c228 100644 --- a/map.c +++ b/map.c @@ -117,9 +117,11 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt) { if (lf->cell->map->beingcreated) { // sometimes start off asleep in new maps - // TODO: base this on the time, and whether monster is nocturnal - if (rnd(1,2) == 1) { - addflag(lf->flags, F_ASLEEP, B_TRUE, NA, NA, NULL); + if (!lfhasflag(lf, F_DEAF)) { + // TODO: base this on the time, and whether monster is nocturnal + if (rnd(1,2) == 1) { + addflag(lf->flags, F_ASLEEP, B_TRUE, NA, NA, NULL); + } } } @@ -131,45 +133,59 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt) { } if (amt > 1) { cell_t *adjcell; - cell_t **moncell; - int nmoncells = 1; - - moncell = malloc( amt * sizeof(cell_t *)); - moncell[0] = c; - nmoncells = 1; amt--; // we've already added one //adjcell = c; for ( ; amt > 0; amt--) { - int n; lifeform_t *newlf; // find an adjacent cell to one of the newly added monsters, // starting with the first one - adjcell = NULL; - for (n = 0; n < nmoncells; n++) { - adjcell = getrandomadjcell(moncell[n], WE_WALKABLE, B_ALLOWEXPAND); - if (adjcell) break; - } + adjcell = getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND); // did we find one? if (!adjcell) break; - //lf = addlf(adjcell, r->id, getrandommonlevel(adjcell->map->depth)); newlf = addlf(adjcell, r->id, 1); if (!newlf) { break; } newlf->born = B_FALSE; - if (lfhasflag(lf, F_ASLEEP)) addflag(newlf->flags, F_ASLEEP, B_TRUE, NA, NA, NULL); - newlf->born = B_TRUE; - moncell[nmoncells] = adjcell; - nmoncells++; } - free(moncell); } + // minons? + f = hasflag(lf->flags, F_MINIONS); + if (f) { + if (rnd(1,100) <= f->val[0]) { + int n; + cell_t *adjcell; + int nminions; + // override amount + nminions = rnd(f->val[1], f->val[2]); + + for (n = 0; n < nminions; n++) { + lifeform_t *newlf; + race_t *newr; + + adjcell = getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND); + if (!adjcell) break; + + newr = findracebyname(f->text); + if (!newr) break; + + newlf = addlf(adjcell, newr->id, 1); + if (!newlf) break; + + newlf->born = B_FALSE; + if (lfhasflag(lf, F_ASLEEP)) addflag(newlf->flags, F_ASLEEP, B_TRUE, NA, NA, NULL); + newlf->born = B_TRUE; + } + } + } + + // sometimes give the lf random objects (extra monsters through // 'numappears' don't get them. if (lfhasflag(lf, F_HUMANOID) && !lfhasflag(lf, F_NOPACK)) { @@ -252,7 +268,6 @@ int cellhaslos(cell_t *c1, cell_t *dest) { // can always see your own cell if ((deltax == 0) && (deltay == 0)) { - //if (viewer->controller == C_HUMAN) wreck->mazelev[z].maze[y2*MAZEW+x2].known = B_PERM; return B_TRUE; } @@ -644,7 +659,7 @@ int countcellexits(cell_t *cell) { looppct = percentage change of turning dead-end into loop maxrooms = max # of rooms */ -void createmap(map_t *map, int depth, int habitat, map_t *parentmap, objecttype_t *returnstairtype) { +void createmap(map_t *map, int depth, int habitat) { char buf[BUFLEN]; int wantrooms = B_TRUE; int x,y; @@ -662,7 +677,6 @@ void createmap(map_t *map, int depth, int habitat, map_t *parentmap, objecttype_ int maxroomh = MAX_ROOMH; int bestx,besty; int w,h; - objecttype_t *ot; //int startdir,forcex,forcey,ntries; cell_t *cell, *c; object_t *o; @@ -920,37 +934,23 @@ void createmap(map_t *map, int depth, int habitat, map_t *parentmap, objecttype_ } - // add return staircase to previous map - c = NULL; - while (!c || !isempty(c) || countobs(c->obpile)) { - c = getrandomroomcell(map, ANYROOM); - } - - o = addob(c->obpile, returnstairtype->name); - if (parentmap) { - cell_t *parentstairs; - objecttype_t *ot; - ot = getoppositestairs(returnstairtype); - // find stairs in parent map - parentstairs = findobinmap(parentmap, ot->id); - assert(parentstairs); - // link stairs on new map to stairs on parent map - addflag_real(o->flags, F_MAPLINK, parentmap->id, parentstairs->x, parentstairs->y, NULL, PERMENANT, B_UNKNOWN, -1); - } - - // add staircase continuing on (normally this will be down) - if ((map->depth >= MAXDEPTH) && (returnstairtype->id == OT_STAIRSUP)) { - // no need for a down staircase on the last level! - } else { + // add staircases + for (i = 0; i < 3; i++) { + // add up stairs c = NULL; while (!c || !isempty(c) || countobs(c->obpile)) { c = getrandomroomcell(map, ANYROOM); } - ot = getoppositestairs(returnstairtype); - addob(c->obpile, ot->name); - // don't add F_MAPLINK yet - this will cocur when we use the stairs + o = addob(c->obpile, "staircase going up"); + linkstairs(o); + + c = NULL; + while (!c || !isempty(c) || countobs(c->obpile)) { + c = getrandomroomcell(map, ANYROOM); + } + o = addob(c->obpile, "staircase going down"); + linkstairs(o); } - /* void around map // N @@ -1670,6 +1670,22 @@ map_t *findmapofdepth(int depth) { return NULL; } +// find the object with id 'id' in map 'm' +object_t *findobidinmap(map_t *m, long id) { + cell_t *c; + int x,y; + for (y = 0; y < m->h; y++) { + for (x = 0; x < m->w; x++) { + object_t *o; + c = getcellat(m, x, y); + o = findobbyid(c->obpile, id); + if (o) return o; + } + } + return NULL; +} + + // find the cell in 'map' which contains object oid cell_t *findobinmap(map_t *m, enum OBCLASS oid) { cell_t *c; @@ -2017,6 +2033,40 @@ int getslipperyness(cell_t *c, object_t **slipob) { return totalslip; } +cell_t *getstairdestination(object_t *o) { + flag_t *f; + cell_t *newcell = NULL; + + f = hasflag(o->flags, F_MAPLINK); + if (f) { + map_t *newmap; + int newx,newy; + newmap = findmap(f->val[0]); + assert(newmap); + // prefer an object id if we have it + if (strlen(f->text)) { + object_t *o2; + long obid; + obid = atol(f->text); + o2 = findobidinmap(newmap, obid); + if (o2) { + newcell = getoblocation(o2); + } else { + dblog("stairs link to object %ld which no longer exists!",obid); + msg("stairs link to object %ld which no longer exists!",obid); + return NULL; + } + } else { + // otherwise look for x/y coors + newx = f->val[1]; + newy = f->val[2]; + // find dst x/y + newcell = getcellat(newmap, newx, newy); + } + } + return newcell; +} + object_t *hasenterableobject(cell_t *c) { return hasobwithflag(c->obpile, F_CLIMBABLE); } @@ -2247,6 +2297,68 @@ int iswallindir(cell_t *cell, int dir) { return B_FALSE; } +// link the staircase 'o' to a free one in map 'othermap' +// returns TRUE if it failed because othermap doesn't exist. +int linkstairs(object_t *o) { + map_t *othermap; + object_t *o2; + map_t *stairmap; + cell_t *staircell; + cell_t *c2; + objecttype_t *otherstairtype; + int n,found = B_FALSE; + int dir; + flag_t *f; + + staircell = getoblocation(o); + stairmap = staircell->map; + + otherstairtype = getoppositestairs(o->type); + + f = hasflag(o->flags, F_CLIMBABLE); + if (f) { + if (f->val[0] == D_UP) { + dir = -1; + } else { + dir = 1; + } + } else { + dblog("ERROR: stair object has no f_climbable!"); + msg("ERROR: stair object has no f_climbable!"); + exit(1); + } + + + othermap = findmapofdepth(stairmap->depth + dir); + if (othermap) { + // find an empty staircase in other map + for (n = 0; n < othermap->w*othermap->h; n++) { + c2 = othermap->cell[n]; + o2 = hasob(c2->obpile, otherstairtype->id); + // does it go nowhere? + if (o2 && !hasflag(o2->flags, F_MAPLINK)) { + char obid[BUFLEN]; + // link it to here! + sprintf(obid, "%ld", o->id); + addflag(o2->flags, F_MAPLINK, stairmap->id, NA, NA, obid); + // link me to there + sprintf(obid, "%ld", o2->id); + addflag(o->flags, F_MAPLINK, othermap->id, NA, NA, obid); + found = B_TRUE; + break; + } + } + if (!found) { + dblog("ERROR - stairs link to existing map #%d, but it has no free stairs.",othermap->id); + msg("ERROR - stairs link to existing map #%d, but it has no free stairs.",othermap->id); + exit(1); + } + } else { + return B_TRUE; + } + return B_FALSE; +} + void makedoor(cell_t *cell) { object_t *o; map_t *m; diff --git a/map.h b/map.h index ef3ca6f..242252b 100644 --- a/map.h +++ b/map.h @@ -17,7 +17,7 @@ int calcroompos(map_t *map, int w, int h, int *bx, int *by); int countadjcellsoftype(cell_t *cell, int id); int countadjcellswithflag(cell_t *cell, enum FLAG fid); int countcellexits(cell_t *cell); -void createmap(map_t *map, int depth, int habitat, map_t *parentmap, objecttype_t *returnstairtype); +void createmap(map_t *map, int depth, int habitat); void createroom(map_t *map, int minx, int miny, int w, int h, int roomid); int dirtox(int dt, int dir); int dirtoy(int dt, int dir); @@ -26,6 +26,7 @@ void explodesinglecell(cell_t *c, int dam, int killwalls, object_t *o, cell_t *c void explodecells(cell_t *c, int dam, int killwalls, object_t *o, int range, int wantannounce); map_t *findmap(int mid); map_t *findmapofdepth(int depth); +object_t *findobidinmap(map_t *m, long id); cell_t *findobinmap(map_t *m, enum OBCLASS oid); void forgetcells(map_t *map, int amt); cell_t *getcellindir(cell_t *cell, int dir); @@ -37,6 +38,7 @@ cell_t *getrandomcelloftype(map_t *map, int id); int getrandomdir(int dirtype); cell_t *getrandomroomcell(map_t *map, int roomid); int getslipperyness(cell_t *c, object_t **slipob); +cell_t *getstairdestination(object_t *o); object_t *hasenterableobject(cell_t *c); lifeform_t *haslf(cell_t *c); int hasobject(cell_t *c); @@ -50,6 +52,7 @@ int isloopdirok(cell_t *cell, int dir); int isnewcellok(cell_t *cell, char *err); int isonmap(map_t *map, int x, int y); int iswallindir(cell_t *cell, int dir); +int linkstairs(object_t *o); void makedoor(cell_t *cell); void makelit(cell_t *c, enum LIGHTLEV how, int howlong); void makelitradius(cell_t *c, int radius, enum LIGHTLEV how, int howlong); diff --git a/move.c b/move.c index 260f378..b7839ad 100644 --- a/move.c +++ b/move.c @@ -627,7 +627,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) { if (!boots) { // take damage getobname(o, obname, 1); - if (lf->controller == C_PLAYER) { + if (isplayer(lf)) { msg("Ow - you step on %s!",obname); didmsg = B_TRUE; } else if (haslos(player, newcell)) { @@ -935,7 +935,7 @@ int opendoor(lifeform_t *lf, object_t *o) { if (f) killflag(f); if (lf) { - if (lf->controller == C_PLAYER) { + if (isplayer(lf)) { msg("You open %s.",obname); } else { if (cansee(player, lf) && isadjacent(lf->cell, doorcell)) { @@ -1031,7 +1031,7 @@ int closedoor(lifeform_t *lf, object_t *o) { f = hasflag(o->flags, F_OPEN); if (!f) { - if (lf && (lf->controller == C_PLAYER)) { + if (lf && (isplayer(lf))) { msg("It is already closed!"); } return B_TRUE; @@ -1042,7 +1042,7 @@ int closedoor(lifeform_t *lf, object_t *o) { addflag(o->flags, F_BLOCKSVIEW, B_TRUE, NA, NA, NULL); if (lf) { - if (lf->controller == C_PLAYER) { + if (isplayer(lf)) { msg("You close %s.", obname); } else { if (cansee(player, lf) && isadjacent(lf->cell, cell)) { @@ -1307,7 +1307,7 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) { // push it! push(lf, inway, dir); } else { - if (lf->controller == C_PLAYER) { + if (isplayer(lf)) { char obname[BUFLEN]; getobname(inway, obname, 1); switch (reason) { @@ -1360,7 +1360,7 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) { } } else { // attack! - return attacklf(lf, cell->lf); + return attackcell(lf, cell); } break; case E_CANTMOVE: diff --git a/nexus.c b/nexus.c index 28b5f28..0209188 100644 --- a/nexus.c +++ b/nexus.c @@ -109,7 +109,7 @@ int main(int argc, char **argv) { if (!firstmap) { newworld = B_TRUE; addmap(); - createmap(firstmap, 1, H_DUNGEON, NULL, findot(OT_STAIRSUP)); + createmap(firstmap, 1, H_DUNGEON); } if (!knowledge) { @@ -329,14 +329,14 @@ void checkdeath(void) { for (lf = player->cell->map->lf; lf ; lf = nextlf) { nextlf = lf->next; + // check for object death + removedeadobs(lf->pack); // check for death if (lf->hp <= 0) { // die! die(lf); continue; } - // check for object death - removedeadobs(lf->pack); } // check for object death on map @@ -392,6 +392,7 @@ void donextturn(map_t *map) { who = map->lf; if (db) dblog("**** donextturn for: id %d %s", who->id, who->race->name); + assert(who->timespent == 0); turneffectslf(who); @@ -409,7 +410,6 @@ void donextturn(map_t *map) { autotarget(who); - assert(who->timespent == 0); // keep looping until they actually do something or are dead! while (who->timespent == 0) { if (isdead(who)) { @@ -703,7 +703,7 @@ void initcommands(void) { int isplayerturn(void) { if (!player) return B_FALSE; - if (player->cell->map->lf->controller == C_PLAYER) { + if (isplayer(player->cell->map->lf)) { return B_TRUE; } return B_FALSE; diff --git a/objects.c b/objects.c index e752b48..0e95a34 100644 --- a/objects.c +++ b/objects.c @@ -861,9 +861,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack) { f = hasflag(o->flags, F_DAM); if (f) { int ndice,dsides,bonus; - ndice = f->val[0]; - dsides = f->val[1]; - bonus = f->val[2]; if (bonus < 0) bonus = 0; + texttodice(f->text, &ndice,&dsides,&bonus); // half the number of sides on the dice (dsides). dsides /= 2; if (dsides < 1) dsides = 1; // increase modifier by (ndice * dsides) @@ -871,9 +869,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack) { if (bonus <= 0) { bonus = NA; } - f->val[0] = ndice; - f->val[1] = dsides; - f->val[2] = bonus; + dicetotext(ndice,dsides,bonus,NULL,NULL,f->text, NULL); } } break; @@ -892,17 +888,15 @@ object_t *addobject(obpile_t *where, char *name, int canstack) { // half the damage f = hasflag(o->flags, F_DAM); if (f) { - int dsides,bonus; - dsides = f->val[1]; - bonus = f->val[2]; if (bonus < 0) bonus = 0; + int ndice, dsides,bonus; + texttodice(f->text, &ndice, &dsides, &bonus); // half the number of sides on the dice (dsides). dsides /= 2; // half modifier if (bonus > 0) { bonus /= 2; if (bonus <= 0) bonus = NA; } - f->val[1] = dsides; - f->val[2] = bonus; + dicetotext(ndice,dsides,bonus,NULL,NULL,f->text, NULL); } } break; @@ -1333,7 +1327,7 @@ void adjustdamob(object_t *o, unsigned int *dam, enum DAMTYPE damtype) { lifeform_t *owner; (*dam) *= 2; owner = o->pile->owner; - if (owner && (owner->controller == C_PLAYER)) { + if (owner && isplayer(owner)) { // become known if a player's if (!isblessknown(o)) { char obname[BUFLEN]; @@ -1360,8 +1354,52 @@ void adjustprice(objecttype_t *ot, float *price) { } */ +// adjusts armour's evasion penalty based on skill +int adjustarmourpenalty(lifeform_t *lf, float amt) { + enum SKILLLEVEL slev; + + // no penalties for monsters + if (!isplayer(lf)) { + return 0; + } + // only adjust if it is a NEGATIVE penalty! + if (amt < 0) { + slev = getskill(lf, SK_ARMOUR); + switch (slev) { + case PR_INEPT: + amt *= 2; // double penalty! + break; + case PR_NOVICE: + break; + case PR_BEGINNER: + amt *= 0.8; + break; + case PR_ADEPT: + amt *= 0.6; + break; + case PR_SKILLED: + amt *= 0.4; + break; + case PR_EXPERT: + amt *= 0.2; + break; + case PR_MASTER: // no penalty! + amt = 0; + break; + } + } + return amt; +} + +// adjusts shield's accuracy penalty based on skill int adjustshieldpenalty(lifeform_t *lf, float amt) { enum SKILLLEVEL slev; + + // monsters suffer no penalties + if (!isplayer(lf)) { + return 0; + } + slev = getskill(lf, SK_SHIELDS); switch (slev) { case PR_INEPT: @@ -1414,16 +1452,33 @@ void applyobmod(object_t *o, obmod_t *om) { } if (om->id == OM_FROZEN) { - // frozen things don't decay + // frozen things don't decay... f = hasflagval(o->flags, F_OBHPDRAIN, NA, DT_DECAY, NA, NULL); if (f) { killflag(f); } - // but they do melt! + + // ...but they do melt! addflag(o->flags, F_OBHPDRAIN, 1, DT_MELT, NA, NULL); + + // it needs HP to melt + if (!hasflag(o->flags, F_OBHP)) { + int myhp; + // give hp + myhp = getobweight(o) * 20; + if (myhp <= 0) myhp = 2; + + // TODO: not sure about using FROMMAT here... + // but i wnat restoration to still work. + addtempflag(o->flags, F_OBHP, myhp, myhp, NA, NULL, FROMMAT); + } + if (!hasflag(o->flags, F_DAMAGABLE)) { + // TODO: not sure about using FROMMAT here... + // but i wnat restoration to still work. + addtempflag(o->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL, FROMMAT); + } } copyflags(o->flags, om->flags, FROMOBMOD); - } int blessob(object_t *o) { @@ -1474,7 +1529,7 @@ void brightflash(cell_t *centre, int range, lifeform_t *immunelf) { int x,y; cell_t *c; - animradial(centre, range, '}', C_GREY); + animradial(centre, range, '}', C_WHITE); // announce if (haslos(player, centre) && !isblind(player)) { @@ -1542,7 +1597,7 @@ int canbepoisoned(enum OBTYPE oid) { if (!ot) return B_FALSE; if (ot->obclass->id != OC_WEAPON) return B_FALSE; - f = hasflag(ot->flags, F_DAMTYPE); + f = hasflag(ot->flags, F_DAM); if (f) { switch (f->val[0]) { case DT_SLASH: @@ -1637,17 +1692,6 @@ int changemat(object_t *o, enum MATERIAL mat) { extinguish(o); // it will melt... - if (!hasflag(o->flags, F_OBHP)) { - int myhp; - // give hp - myhp = getobweight(o) * 20; - if (myhp <= 0) myhp = 2; - - addtempflag(o->flags, F_OBHP, myhp, myhp, NA, NULL, FROMMAT); - } - if (!hasflag(o->flags, F_DAMAGABLE)) { - addtempflag(o->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL, FROMMAT); - } // note that it is frozen om = findobmod(OM_FROZEN); applyobmod(o, om); @@ -2165,6 +2209,7 @@ void genhiddennames(void) { f = hasflag(ot->flags, F_HASHIDDENNAME); if (f) { int n; + int gotcolour = B_FALSE; char *thisname; if (strlen(f->text)) { thisname = strdup(f->text); @@ -2194,21 +2239,28 @@ void genhiddennames(void) { buf[0] = ot->obclass->glyph.ch; buf[1] = '\0'; addflag(ot->flags, F_GLYPH, colour[n].col, NA, NA, buf); + gotcolour = B_TRUE; + //dblog("assigning colour %s to %s (%s)",colour[n].name, thisname, ot->name); + break; } } } - for (n = 0; strlen(gemtype[n].name); n++) { - if (strstr(thisname, gemtype[n].name)) { - flag_t *gf; - gf = hasflag(ot->flags, F_GLYPH); - if (gf) { - gf->val[0] = gemtype[n].col; - } else { - char buf[2]; - - buf[0] = ot->obclass->glyph.ch; - buf[1] = '\0'; - addflag(ot->flags, F_GLYPH, gemtype[n].col, NA, NA, buf); + + if (!gotcolour) { + for (n = 0; strlen(gemtype[n].name); n++) { + if (strstr(thisname, gemtype[n].name)) { + flag_t *gf; + gf = hasflag(ot->flags, F_GLYPH); + if (gf) { + gf->val[0] = gemtype[n].col; + } else { + char buf[2]; + + buf[0] = ot->obclass->glyph.ch; + buf[1] = '\0'; + addflag(ot->flags, F_GLYPH, gemtype[n].col, NA, NA, buf); + break; + } } } } @@ -2271,7 +2323,7 @@ int getobaccuracy(object_t *wep, lifeform_t *weilder) { if (sk) { switch (getskill(weilder, sk->id)) { case PR_INEPT: - acc -= 75; + acc -= 45; break; case PR_NOVICE: acc -= 25; @@ -2347,7 +2399,7 @@ int getobvalue(object_t *o) { // damage if (f->id == F_DAM) { int min,max; - getdamrange(o->flags, &min, &max); + getdamrange(f, &min, &max); price += (max*5); } // armour rating @@ -2603,7 +2655,7 @@ char *gethiddenname(object_t *o) { if (k->id == o->type->id) { // it DOES have a hidden name. // does the player know about it? - if (k->known) { + if (k->known == B_KNOWN) { // if so, return real name return o->type->name; } else { @@ -2935,6 +2987,7 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan char prefix[BUFLEN]; char basename[BUFLEN]; char buf2[BUFLEN]; + char triedbuf[BUFLEN]; int shopitem = B_FALSE; flag_t *f; brand_t *br; @@ -3211,63 +3264,83 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan strcat(buf, o->inscription); strcat(buf, "}"); } - - // TODO: detect magic - append [magic] - if ((gamemode == GM_GAMESTARTED) && 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 + + // show if we've tried this + if (gamemode == GM_GAMESTARTED) { + strcpy(triedbuf, ""); + if (istried(o)) { + if (strlen(triedbuf)) strcat(triedbuf, ", "); + else strcpy(triedbuf, " ["); + strcat(triedbuf, "tried"); + } + if (lfhasflagval(player, F_FAILEDINSPECT, o->type->id, NA, NA, NULL)) { + if (strlen(triedbuf)) strcat(triedbuf, ", "); + else strcpy(triedbuf, " ["); + strcat(triedbuf, "inspected"); + } + if (strlen(triedbuf)) { + strcat(triedbuf, "]"); + strcat(buf, triedbuf); + } + + // detect magic - append [magic] + if (lfhasflag(player, F_DETECTMAGIC)) { + int ismagic = B_FALSE; + if (hasunknownmod) { 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 + } + 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; - default: - break; - } - if (hasflag(o->flags, F_ENCHANTABLE) && hasflag(o->flags, F_BONUS)) { - 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) { - strcat(buf, " [magic]"); + if (ismagic) { + strcat(buf, " [magic]"); + } } } + return buf; } @@ -3475,7 +3548,7 @@ char *real_getrandomob(map_t *map, char *buf, int cond, int cval, int forcedepth if (cond == RO_NONE) { condok = B_TRUE; } else if (cond == RO_DAMTYPE) { - if (hasflagval(ot->flags, F_DAMTYPE, cval, NA, NA, NULL)) { + if (hasflagval(ot->flags, F_DAM, cval, NA, NA, NULL)) { condok = B_TRUE; } } else if (cond == RO_OBCLASS) { @@ -5069,7 +5142,7 @@ void initobjects(void) { addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); - // divine powers + // divine powers (spells/abilities) addot(OT_A_DEBUG, "debug", "You can toggle debugging for a lifeform.", MT_NOTHING, 0, OC_ABILITY); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addot(OT_A_ENHANCE, "enhance", "Enhance a lifeform's stats.", MT_NOTHING, 0, OC_ABILITY); @@ -5084,39 +5157,50 @@ void initobjects(void) { addot(OT_S_GIFT, "gift", "Grants the target any item of their choice (with some limitations).", MT_NOTHING, 0, OC_SPELL); addflag(lastot->flags, F_SPELLLEVEL, 9, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINE, NA, NA, NULL); + addot(OT_A_EMPLOY, "employ", "Assigns a job to the target lifeform.", MT_NOTHING, 0, OC_ABILITY); + addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); + // abilities - addot(OT_A_SWOOP, "swoop", "You can attack an enemy while flying past them.", MT_NOTHING, 0, OC_ABILITY); - addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); - addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); - addot(OT_A_GRAB, "grab", "You can grab hold of nearby enemies to prevent their escape.", MT_NOTHING, 0, OC_ABILITY); - addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); - addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL); addot(OT_A_CRUSH, "crush", "You can crush enemies after grabbing them.", 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); addflag(lastot->flags, F_NEEDSGRAB, B_TRUE, NA, NA, NULL); - addot(OT_A_JUMP, "jump", "You can leap large distances.", MT_NOTHING, 0, OC_ABILITY); - addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); - addot(OT_A_SPRINT, "sprint", "You can run at high speed over short distances.", MT_NOTHING, 0, OC_ABILITY); - addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); - addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL); - addot(OT_A_EMPLOY, "employ", "Assigns a job to the target lifeform.", MT_NOTHING, 0, OC_ABILITY); + 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); + addflag(lastot->flags, F_XPVAL, 10, NA, NA, NULL); addot(OT_A_HEAVYBLOW, "heavy blow", "Mighty blow which knocks enemies backwards.", MT_NOTHING, 0, OC_ABILITY); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL); + addot(OT_A_JUMP, "jump", "You can leap large distances.", MT_NOTHING, 0, OC_ABILITY); + addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); + addot(OT_A_HURRICANESTRIKE, "hurricane strike", "A sweeping attack aginst everything nearby.", MT_NOTHING, 0, OC_ABILITY); + addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJSELF, NA, NA, NULL); addot(OT_A_INSPECT, "inspect", "Try to identify an unknown object from your pack.", MT_NOTHING, 0, OC_ABILITY); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addot(OT_A_POLYREVERT, "revertform", "Revert to your original form.", MT_NOTHING, 0, OC_ABILITY); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addflag(lastot->flags, F_NOANNOUNCE, B_TRUE, NA, NA, NULL); + addot(OT_A_SPRINT, "sprint", "You can run at high speed over short distances.", MT_NOTHING, 0, OC_ABILITY); + addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL); addot(OT_A_STINGACID, "sting (acid)", "You can sting your enemies.", 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); addflag(lastot->flags, F_RANGE, 1, NA, NA, NULL); + addot(OT_A_SWOOP, "swoop", "You can attack an enemy while flying past them.", MT_NOTHING, 0, OC_ABILITY); + addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); + addot(OT_A_WARCRY, "warcry", "Inspire fear in your enemies with a mighty war cry.", MT_NOTHING, 0, OC_ABILITY); + addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL); // manuals + addot(OT_MAN_ARMOUR, "manual of armour", "Teaches you the skill 'armour'.", MT_PAPER, 3, OC_BOOK); + addflag(lastot->flags, F_MANUALOF, SK_ARMOUR, NA, NA, NULL); addot(OT_MAN_ATHLETICS, "manual of athletics", "Teaches you the skill 'athletics'.", MT_PAPER, 3, OC_BOOK); addflag(lastot->flags, F_MANUALOF, SK_ATHLETICS, NA, NA, NULL); addot(OT_MAN_BACKSTAB, "manual of stabbing", "Teaches you the skill 'backstab'.", MT_PAPER, 3, OC_BOOK); @@ -5494,19 +5578,17 @@ void initobjects(void) { addflag(lastot->flags, F_PICKLOCKS, 4, B_DIEONFAIL, NA, NULL); addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL); // can use as a (very bad) weapon too... - addflag(lastot->flags, F_DAMTYPE, DT_PIERCE, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 1, NA, NULL); + addflag(lastot->flags, F_DAM, DT_PIERCE, NA, NA, "1d1"); addflag(lastot->flags, F_ACCURACY, 50, NA, NA, NULL); - // tech - l1 addot(OT_POCKETWATCH, "pocket watch", "A portable timekeeping device made to be carried in a pocket.", MT_METAL, 0.1, OC_TECH); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_TECHLEVEL, PR_NOVICE, NA, NA, NULL); addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL); addot(OT_DIGITALWATCH, "digital watch", "An electronic timekeeping device which shows the time as a number.", MT_METAL, 0.1, OC_TECH); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_TECHLEVEL, PR_NOVICE, NA, NA, NULL); addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL); @@ -5520,7 +5602,7 @@ void initobjects(void) { addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL); addot(OT_LANTERNLED, "LED lantern", "A low-powered but efficient lantern which will last almost forever.", MT_METAL, 0.5, OC_TECH); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 20, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OPERONOFF, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_ACTIVATECONFER, F_PRODUCESLIGHT, 2, NA, NULL); @@ -5531,7 +5613,7 @@ void initobjects(void) { // tech - l2 addot(OT_FLASHBANG, "flashbang", "A stun grenade which temporarily blinds all within sight.", MT_METAL, 1, OC_TECH); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 40, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL); addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OPERONOFF, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); @@ -5547,7 +5629,7 @@ void initobjects(void) { addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL); addot(OT_GRENADE, "grenade", "An explosive weapon which explodes a short time after activation.", MT_METAL, 1, OC_TECH); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 30, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL); addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OPERONOFF, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); @@ -5563,7 +5645,7 @@ void initobjects(void) { addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL); addot(OT_C4, "block of c4", "A highly explosive plastic which explodes a medium time after activation.", MT_PLASTIC, 1, OC_TECH); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 25, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL); addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OPERONOFF, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); @@ -5576,10 +5658,15 @@ void initobjects(void) { addflag(lastot->flags, F_GRENADE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_TECHLEVEL, PR_BEGINNER, NA, NA, NULL); addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL); + addot(OT_MOTIONSCANNER, "motion scanner", "Small scanning device which detects nearby lifeforms.", MT_METAL, 1.5, OC_TECH); + addflag(lastot->flags, F_RARITY, H_ALL, 60, NA, NULL); + addflag(lastot->flags, F_HOLDCONFER, F_DETECTLIFE, 10, NA, NULL); + addflag(lastot->flags, F_TECHLEVEL, PR_BEGINNER, NA, NA, NULL); + addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL); // tech - l3 addot(OT_JETPACK, "jet pack", "A portable ion-thruster which allows the wearer to fly.", MT_METAL, 10, OC_TECH); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 30, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OPERONOFF, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_RNDCHARGES, 10, 30, NA, NULL); @@ -5593,26 +5680,26 @@ void initobjects(void) { addot(OT_INFOVISOR, "infovisor", "Sleek looking metal visor which displays info directly into the retina.", MT_METAL, 0.2, OC_TECH); addflag(lastot->flags, F_GOESON, BP_EYES, NA, NA, NULL); addflag(lastot->flags, F_EQUIPCONFER, F_EXTRAINFO, B_TRUE, NA, NULL); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 30, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); addflag(lastot->flags, F_TECHLEVEL, PR_SKILLED, NA, NA, NULL); addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL); addot(OT_LOCKHACKER, "lock hacker", "A sophisticated machine to manipulate physical locks.", MT_METAL, 3, OC_TECH); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 20, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_TECHLEVEL, PR_SKILLED, NA, NA, NULL); addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL); // tech - l5 addot(OT_TELEPAD, "teleport beacon", "A metal cone which will teleport the user to the nearest similar cone.", MT_METAL, 3, OC_TECH); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 40, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_TECHLEVEL, PR_EXPERT, NA, NA, NULL); addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL); addot(OT_XRAYGOGGLES, "pair of xray goggles", "Bulky looking goggles which allow you to see through walls.", MT_METAL, 0.3, OC_TECH); addflag(lastot->flags, F_GOESON, BP_EYES, NA, NA, NULL); addflag(lastot->flags, F_EQUIPCONFER, F_XRAYVIS, 2, NA, NULL); - addflag(lastot->flags, F_RARITY, H_DUNGEON, 25, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); addflag(lastot->flags, F_TECHLEVEL, PR_EXPERT, NA, NA, NULL); addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL); @@ -5925,7 +6012,7 @@ void initobjects(void) { addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addot(OT_POISONCLOUD, "cloud of gas", "A thick cloud of poisonous gas.", MT_GAS, 0, OC_EFFECT); - addflag(lastot->flags, F_GLYPH, NA, NA, NA, "{"); + addflag(lastot->flags, F_GLYPH, C_GREEN, NA, NA, "{"); addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DIECONVERTTEXT, NA, NA, NA, "thins out a little"); addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "puff of gas"); @@ -5936,7 +6023,7 @@ void initobjects(void) { addflag(lastot->flags, F_WALKDAM, DT_POISONGAS, NA, NA, "1d4"); addot(OT_POISONPUFF, "puff of gas", "A small puff of poisonous gas.", MT_GAS, 0, OC_EFFECT); - addflag(lastot->flags, F_GLYPH, NA, NA, NA, "{"); + addflag(lastot->flags, F_GLYPH, C_GREEN, NA, NA, "{"); addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DIETEXT, B_TRUE, NA, NA, "disperses"); addflag(lastot->flags, F_OBHP, 2, 2, NA, NULL); @@ -6021,20 +6108,17 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_ALL, 80, NA, NULL); addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL); addflag(lastot->flags, F_ARMOURRATING, 1, NA, NA, NULL); - addflag(lastot->flags, F_EVASION, -10, NA, NA, NULL); addflag(lastot->flags, F_OBHP, 4, 4, NA, NULL); addot(OT_VELVETROBE, "velvet robe", "A luxurious velvet robe.", MT_CLOTH, 4, OC_ARMOUR); addflag(lastot->flags, F_RARITY, H_ALL, 65, NA, NULL); addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL); addflag(lastot->flags, F_ARMOURRATING, 1, NA, NA, NULL); - addflag(lastot->flags, F_EVASION, -10, NA, NA, NULL); addflag(lastot->flags, F_OBHP, 4, 4, NA, NULL); // armour - shoulders addot(OT_CLOAK, "cloak", "A standard leather cloak.", MT_LEATHER, 4, OC_ARMOUR); addflag(lastot->flags, F_RARITY, H_ALL, 80, NA, NULL); addflag(lastot->flags, F_GOESON, BP_SHOULDERS, NA, NA, NULL); addflag(lastot->flags, F_ARMOURRATING, 1, NA, NA, NULL); - addflag(lastot->flags, F_EVASION, -5, NA, NA, NULL); addflag(lastot->flags, F_OBHP, 6, 6, NA, NULL); // armour - waist addot(OT_BELTLEATHER, "leather belt", "A plain leather belt.", MT_LEATHER, 0.2, OC_ARMOUR); @@ -6046,19 +6130,16 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_ALL, 80, NA, NULL); addflag(lastot->flags, F_GOESON, BP_LEGS, NA, NA, NULL); addflag(lastot->flags, F_ARMOURRATING, 1, NA, NA, NULL); - addflag(lastot->flags, F_EVASION, 0, NA, NA, NULL); addflag(lastot->flags, F_OBHP, 2, 2, NA, NULL); addot(OT_RIDINGTROUSERS, "pair of riding trousers", "A fitted pair of leather trousers.", MT_LEATHER, 2, OC_ARMOUR); addflag(lastot->flags, F_RARITY, H_ALL, 70, NA, NULL); addflag(lastot->flags, F_GOESON, BP_LEGS, NA, NA, NULL); addflag(lastot->flags, F_ARMOURRATING, 2, NA, NA, NULL); - addflag(lastot->flags, F_EVASION, 0, NA, NA, NULL); addflag(lastot->flags, F_OBHP, 5, 5, NA, NULL); addot(OT_COMBATPANTS, "pair of combat pants", "An armoured pair of camoflauged trousers.", MT_CLOTH, 2, OC_ARMOUR); addflag(lastot->flags, F_RARITY, H_ALL, 65, NA, NULL); addflag(lastot->flags, F_GOESON, BP_LEGS, NA, NA, NULL); addflag(lastot->flags, F_ARMOURRATING, 3, NA, NA, NULL); - addflag(lastot->flags, F_EVASION, 0, NA, NA, NULL); addflag(lastot->flags, F_OBHP, 8, 8, NA, NULL); // armour - feet addot(OT_SANDALS, "pair of sandals", "Comfortable pair of open leather sandals.", MT_LEATHER, 1, OC_ARMOUR); @@ -6169,15 +6250,16 @@ void initobjects(void) { addflag(lastot->flags, F_OBHP, 2, 2, NA, NULL); addflag(lastot->flags, F_EQUIPCONFER, F_VISRANGEMOD, -4, NA, NULL); addflag(lastot->flags, F_TINTED, B_TRUE, NA, NA, NULL); - addot(OT_MOTIONSCANNER, "motion scanner", "Small scanning device which detects nearby lifeforms.", MT_METAL, 1.5, OC_ARMOUR); - addflag(lastot->flags, F_RARITY, H_ALL, 30, NA, NULL); - addflag(lastot->flags, F_HOLDCONFER, F_DETECTLIFE, 10, 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); addflag(lastot->flags, F_ARMOURRATING, 1, NA, NA, NULL); addflag(lastot->flags, F_OBHP, 2, 2, NA, NULL); addflag(lastot->flags, F_EQUIPCONFER, F_SEEINDARK, 5, NA, NULL); + addflag(lastot->flags, F_NOQUALITY, B_TRUE, NA, NA, NULL); + + // armour - shields addot(OT_BUCKLER, "buckler", "A small, unobtrusive wooden shield.", MT_WOOD, 3.00, OC_ARMOUR); addflag(lastot->flags, F_RARITY, H_ALL, 80, NA, NULL); @@ -6214,9 +6296,18 @@ void initobjects(void) { addflag(lastot->flags, F_EQUIPCONFER, F_SEEINVIS, NA, NA, NULL); addflag(lastot->flags, F_EQUIPCONFER, F_SEEINDARK, 5, NA, NULL); addflag(lastot->flags, F_EQUIPCONFER, F_VISRANGEMOD, 1, NA, NULL); + addot(OT_RING_MANA, "ring of mana", "Increases the wearer's MP pool.", MT_METAL, 0.1, OC_RING); + addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, ""); + addflag(lastot->flags, F_EQUIPCONFER, F_EXTRAMP, 10, NA, NULL); addot(OT_RING_LUCK, "ring of luck", "Makes the wearer more lucky.", MT_METAL, 0.1, OC_RING); - addflag(lastot->flags, F_RARITY, H_ALL, 70, NA, ""); + addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, ""); addflag(lastot->flags, F_EQUIPCONFER, F_EXTRALUCK, 5, NA, NULL); + addot(OT_RING_PROTFIRE, "ring of fire immunity", "Grants the caster complete immunity to fire.", MT_METAL, 0.1, OC_RING); + addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, ""); + addflag(lastot->flags, F_EQUIPCONFER, F_DTIMMUNE, DT_FIRE, NA, NULL); + addot(OT_RING_PROTCOLD, "ring of cold immunity", "Grants the caster complete immunity to cold.", MT_METAL, 0.1, OC_RING); + addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, ""); + addflag(lastot->flags, F_EQUIPCONFER, F_DTIMMUNE, DT_COLD, NA, NULL); addot(OT_RING_STR, "ring of strength", "Increases the wearer's strength.", MT_METAL, 0.1, OC_RING); addflag(lastot->flags, F_RARITY, H_ALL, 70, NA, ""); @@ -6234,9 +6325,7 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_ALL, 70, NA, ""); addflag(lastot->flags, F_EQUIPCONFER, F_ATTRMOD, A_DEX, 1, NULL); // '1' is randomized during generation addflag(lastot->flags, F_IDWHENUSED, B_TRUE, NA, NA, NULL); - addot(OT_RING_MANA, "ring of mana", "Increases the wearer's MP pool.", MT_METAL, 0.1, OC_RING); - addflag(lastot->flags, F_RARITY, H_ALL, 70, NA, ""); - addflag(lastot->flags, F_EQUIPCONFER, F_EXTRAMP, 10, NA, NULL); + addot(OT_RING_WOUNDING, "ring of wounding", "Increases the damage output of the wearer.", MT_METAL, 0.1, OC_RING); addflag(lastot->flags, F_RARITY, H_ALL, 65, NA, ""); addflag(lastot->flags, F_EQUIPCONFER, F_EXTRADAM, NA, NA, "0d0+4"); @@ -6250,9 +6339,6 @@ void initobjects(void) { addot(OT_RING_MPREGEN, "ring of recharging", "Slowly regenerates the wearer's mana.", MT_METAL, 0.1, OC_RING); addflag(lastot->flags, F_RARITY, H_ALL, 50, NA, ""); addflag(lastot->flags, F_EQUIPCONFER, F_MPREGEN, 1, NA, NULL); - addot(OT_RING_PROTFIRE, "ring of fire immunity", "Grants the caster complete immunity to fire.", MT_METAL, 0.1, OC_RING); - addflag(lastot->flags, F_RARITY, H_ALL, 60, NA, ""); - addflag(lastot->flags, F_EQUIPCONFER, F_DTIMMUNE, DT_FIRE, NA, NULL); addot(OT_RING_CONTROL, "ring of control", "Allows the wearer control over teleportation and polymorphic effects.", MT_METAL, 0.1, OC_RING); addflag(lastot->flags, F_RARITY, H_ALL, 50, NA, ""); addflag(lastot->flags, F_EQUIPCONFER, F_CONTROL, NA, NA, NULL); @@ -6262,7 +6348,7 @@ void initobjects(void) { addot(OT_RING_RESISTMAG, "ring of magic resistance", "Renders the wearer immune to most magical effects.", MT_METAL, 0.1, OC_RING); addflag(lastot->flags, F_RARITY, H_ALL, 50, NA, ""); addflag(lastot->flags, F_EQUIPCONFER, F_RESISTMAG, 5, NA, NULL); - addot(OT_RING_MIRACLES, "ring of miracles", "For a limited time, grants miracles to the wearer.", MT_METAL, 0.1, OC_RING); + addot(OT_RING_MIRACLES, "ring of miracles", "Grants a limited number of miracles to the wearer.", MT_METAL, 0.1, OC_RING); addflag(lastot->flags, F_RARITY, H_ALL, 40, NA, ""); addflag(lastot->flags, F_CHARGES, 3, 3, NA, NULL); @@ -6271,72 +6357,72 @@ void initobjects(void) { // // DAMTYPE _cannot_ be overridden (yet)! addot(OT_FISTS, "fists", "human fists", MT_FLESH, 0, OC_WEAPON); - addflag(lastot->flags, F_DAMTYPE, DT_UNARMED, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 2, NA, NULL); + addflag(lastot->flags, F_DAM, DT_UNARMED, NA, NA, "1d2"); 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); addot(OT_TEETH, "teeth", "teeth object", MT_BONE, 0, OC_WEAPON); - addflag(lastot->flags, F_DAMTYPE, DT_BITE, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 2, NA, NULL); + addflag(lastot->flags, F_DAM, DT_BITE, NA, NA, "1d2"); addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL); addflag(lastot->flags, F_NOSTRDAMMOD, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_NONE, NA, NA, NULL); + addflag(lastot->flags, F_UNARMEDWEP, B_TRUE, NA, NA, NULL); addot(OT_CLAWS, "claws", "claws object", MT_BONE, 0, OC_WEAPON); - addflag(lastot->flags, F_DAMTYPE, DT_CLAW, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 2, NA, NULL); + addflag(lastot->flags, F_DAM, DT_CLAW, NA, NA, "1d2"); 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); addot(OT_STING, "sting", "sting object", MT_BONE, 0, OC_WEAPON); - addflag(lastot->flags, F_DAMTYPE, DT_ACID, NA, NA, NULL); addflag(lastot->flags, F_ATTACKVERB, NA, NA, NA, "sting"); - addflag(lastot->flags, F_DAM, 1, 2, NA, NULL); + addflag(lastot->flags, F_DAM, DT_ACID, NA, NA, "1d2"); addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL); addflag(lastot->flags, F_NOSTRDAMMOD, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_NONE, NA, NA, NULL); + addflag(lastot->flags, F_UNARMEDWEP, B_TRUE, NA, NA, NULL); addot(OT_TAIL, "tail", "tail object", MT_FLESH, 0, OC_WEAPON); - addflag(lastot->flags, F_DAMTYPE, DT_BASH, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 4, NA, NULL); + 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); + addflag(lastot->flags, F_UNARMEDWEP, B_TRUE, NA, NA, NULL); addot(OT_TENTACLE, "tentacle", "tentacle object", MT_FLESH, 0, OC_WEAPON); - addflag(lastot->flags, F_DAMTYPE, DT_BASH, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 2, 6, NA, NULL); + addflag(lastot->flags, F_DAM, DT_BASH, NA, NA, "2d6"); 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); addot(OT_ZAPPER, "zapper", "zapper object", MT_NOTHING, 0, OC_WEAPON); - addflag(lastot->flags, F_DAMTYPE, DT_ELECTRIC, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 2, NA, NULL); + addflag(lastot->flags, F_DAM, DT_ELECTRIC, NA, NA, "1d2"); addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL); addflag(lastot->flags, F_NOSTRDAMMOD, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_NONE, NA, NA, NULL); + addflag(lastot->flags, F_UNARMEDWEP, B_TRUE, NA, NA, NULL); // monster weapons addot(OT_ACIDATTACK, "acidattack", "acid attack object", MT_WATER, 0, OC_WEAPON); - addflag(lastot->flags, F_DAMTYPE, DT_ACID, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 2, NA, NULL); + addflag(lastot->flags, F_DAM, DT_ACID, NA, NA, "1d2"); addflag(lastot->flags, F_ACCURACY, 60, NA, NA, NULL); addflag(lastot->flags, F_NOSTRDAMMOD, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_NONE, NA, NA, NULL); + addflag(lastot->flags, F_UNARMEDWEP, B_TRUE, NA, NA, NULL); addot(OT_TOUCHPARALYZE, "paralyzing touch", "paralyzing touch object", MT_BONE, 0, OC_WEAPON); - addflag(lastot->flags, F_DAMTYPE, DT_TOUCH, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 0, 1, NA, NULL); + addflag(lastot->flags, F_DAM, DT_TOUCH, NA, NA, "0d1"); addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL); addflag(lastot->flags, F_HITCONFER, F_PARALYZED, SC_CON, 22, "2-4"); addflag(lastot->flags, F_NOSTRDAMMOD, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_NONE, NA, NA, NULL); + addflag(lastot->flags, F_UNARMEDWEP, B_TRUE, NA, NA, NULL); addot(OT_TOUCHPARALYZE2, "strong paralyzing touch", "strong paralyzing touch object", MT_BONE, 0, OC_WEAPON); - addflag(lastot->flags, F_DAMTYPE, DT_TOUCH, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 0, 1, NA, NULL); + addflag(lastot->flags, F_DAM, DT_TOUCH, NA, NA, "0d1"); addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL); addflag(lastot->flags, F_HITCONFER, F_PARALYZED, SC_CON, 30, "5-10"); addflag(lastot->flags, F_NOSTRDAMMOD, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_NONE, NA, NA, NULL); + addflag(lastot->flags, F_UNARMEDWEP, B_TRUE, NA, NA, NULL); // missiles addot(OT_DART, "dart", "A small, sharp projectile weapon.", MT_WOOD, 0.5, OC_MISSILE); @@ -6405,16 +6491,14 @@ void initobjects(void) { addot(OT_AXE, "axe", "A short pole with a heavy, wedge-shaped blade for chopping.", MT_METAL, 4, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 150, NA, NA, NULL); - addflag(lastot->flags, F_DAMTYPE, DT_CHOP, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 6, 1, NULL); + addflag(lastot->flags, F_DAM, DT_CHOP, NA, NA, "1d6"); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_AXES, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, ST_AVERAGE, NA, NULL); addot(OT_BATTLEAXE, "battleaxe", "An axe specifically designed for combat.", MT_METAL, 5, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 140, NA, NA, NULL); - addflag(lastot->flags, F_DAMTYPE, DT_CHOP, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 9, 1, NULL); + addflag(lastot->flags, F_DAM, DT_CHOP, NA, NA, "1d9"); addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_AXES, NA, NA, NULL); @@ -6422,8 +6506,7 @@ void initobjects(void) { addot(OT_GREATAXE, "greataxe", "An enormous axe made designed for combat.", MT_METAL, 8, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 180, NA, NA, NULL); - addflag(lastot->flags, F_DAMTYPE, DT_CHOP, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 10, 2, NULL); + addflag(lastot->flags, F_DAM, DT_CHOP, NA, NA, "1d10"); addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_ACCURACY, 70, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_AXES, NA, NA, NULL); @@ -6431,8 +6514,7 @@ void initobjects(void) { addot(OT_HANDAXE, "hand axe", "A fast one-handed axe made for combat.", MT_METAL, 2, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 120, NA, NA, NULL); - addflag(lastot->flags, F_DAMTYPE, DT_CHOP, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 6, 1, NULL); + addflag(lastot->flags, F_DAM, DT_CHOP, NA, NA, "1d6+1"); addflag(lastot->flags, F_ACCURACY, 85, NA, NA, NULL); addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_AXES, NA, NA, NULL); @@ -6441,8 +6523,7 @@ void initobjects(void) { // short blades addot(OT_COMBATKNIFE, "combat knife", "A sharp knife designed for military use.", MT_METAL, 1, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 65, NA, NULL); - addflag(lastot->flags, F_DAMTYPE, DT_PIERCE, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 4, 1, NULL); + addflag(lastot->flags, F_DAM, DT_PIERCE, NA, NA, "1d4+1"); addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL); addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OBHP, 5, 5, NA, NULL); @@ -6451,8 +6532,7 @@ void initobjects(void) { addflag(lastot->flags, F_USESSKILL, SK_SHORTBLADES, NA, NA, NULL); addot(OT_DAGGER, "dagger", "A short stabbing weapon with a pointed blade.", MT_METAL, 1, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL); - addflag(lastot->flags, F_DAMTYPE, DT_PIERCE, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 4, NA, NULL); + addflag(lastot->flags, F_DAM, DT_PIERCE, NA, NA, "1d4"); addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL); addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); @@ -6461,8 +6541,7 @@ void initobjects(void) { addflag(lastot->flags, F_USESSKILL, SK_SHORTBLADES, NA, NA, NULL); addot(OT_KNIFE, "knife", "A moderately sharp stabbing tool.", MT_METAL, 1, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, NULL); - addflag(lastot->flags, F_DAMTYPE, DT_SLASH, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 3, NA, NULL); + addflag(lastot->flags, F_DAM, DT_SLASH, NA, NA, "1d3"); addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL); addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_PICKLOCKS, 7, B_BLUNTONFAIL, NA, NULL); @@ -6472,8 +6551,7 @@ void initobjects(void) { addot(OT_ORNDAGGER, "ornamental dagger", "This dagger is pretty, but not particularly effective.", MT_METAL, 1, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); addflag(lastot->flags, F_SHINY, B_TRUE, NA, NA, NULL); - addflag(lastot->flags, F_DAMTYPE, DT_PIERCE, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 3, NA, NULL); + addflag(lastot->flags, F_DAM, DT_PIERCE, NA, NA, "1d3"); addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL); addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_PICKLOCKS, 7, B_BLUNTONFAIL, NA, NULL); @@ -6481,42 +6559,36 @@ void initobjects(void) { addot(OT_QUICKBLADE, "quickblade", "A short blade of exceptional quality, which somehow allows its bearer to attack faster.", MT_METAL, 1, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 35, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 90, NA, NA, NULL); - addflag(lastot->flags, F_DAMTYPE, DT_PIERCE, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 4, NA, NULL); + addflag(lastot->flags, F_DAM, DT_PIERCE, NA, NA, "1d4"); addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_SHORTBLADES, NA, NA, NULL); addot(OT_RAPIER, "rapier", "A long, narrow French sword lacking a cutting edge. Made for stabbing.", MT_METAL, 2.5, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); - addflag(lastot->flags, F_DAMTYPE, DT_PIERCE, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 8, NA, NULL); + addflag(lastot->flags, F_DAM, DT_PIERCE, NA, NA, "1d8"); addflag(lastot->flags, F_ACCURACY, 90, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_SHORTBLADES, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, ST_VWEAK, NA, NULL); addot(OT_SAI, "sai", "A dagger with two long prongs on either side, made to trap opponents' weapons.", MT_METAL, 1, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL); - addflag(lastot->flags, F_DAMTYPE, DT_PIERCE, NA, NA, NULL); + addflag(lastot->flags, F_DAM, DT_PIERCE, NA, NA, "1d4"); addflag(lastot->flags, F_DISARMATTACK, B_TRUE, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 4, NA, NULL); addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_SHORTBLADES, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_DEX, DX_DEXTROUS, NA, NULL); addot(OT_SHORTSWORD, "short sword", "A short blade for fighting. Better for stabbing.", MT_METAL, 2.5, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL); - addflag(lastot->flags, F_DAMTYPE, DT_PIERCE, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 6, NA, NULL); + addflag(lastot->flags, F_DAM, DT_PIERCE, NA, NA, "1d6"); addflag(lastot->flags, F_ACCURACY, 90, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_SHORTBLADES, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, ST_VWEAK, NA, NULL); addot(OT_SICKLE, "sickle", "A hand-held agricultural tool with a curved blade.", MT_METAL, 0.5, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL); - addflag(lastot->flags, F_DAMTYPE, DT_SLASH, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 6, NA, NULL); + addflag(lastot->flags, F_DAM, DT_SLASH, NA, NA, "1d6"); addflag(lastot->flags, F_ACCURACY, 60, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_SHORTBLADES, NA, NA, NULL); addot(OT_STEAKKNIFE, "steak knife", "A common kitchen knife.", MT_METAL, 0.2, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, NULL); - addflag(lastot->flags, F_DAMTYPE, DT_SLASH, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 2, NA, NULL); + addflag(lastot->flags, F_DAM, DT_SLASH, NA, NA, "1d2"); addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL); addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); @@ -6527,16 +6599,14 @@ void initobjects(void) { addot(OT_FALCHION, "falchion", "A single-edged heavy sword made for chopping.", MT_METAL, 4.5, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 135, NA, NA, NULL); - addflag(lastot->flags, F_DAMTYPE, DT_CHOP, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 8, 3, NULL); + addflag(lastot->flags, F_DAM, DT_CHOP, NA, NA, "1d8+3"); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_LONGBLADES, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, ST_STRONG, NA, NULL); addot(OT_GREATSWORD, "greatsword", "A massive two-handed sword.", MT_METAL, 10, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 180, NA, NA, NULL); - addflag(lastot->flags, F_DAMTYPE, DT_SLASH, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 12, 6, NULL); + addflag(lastot->flags, F_DAM, DT_SLASH, NA, NA, "1d12+6"); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_LONGBLADES, NA, NA, NULL); @@ -6544,8 +6614,7 @@ void initobjects(void) { addot(OT_LONGSWORD, "longsword", "Standard issue long slashing weapon.", MT_METAL, 3, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 130, NA, NA, NULL); - addflag(lastot->flags, F_DAMTYPE, DT_SLASH, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 8, 2, NULL); + addflag(lastot->flags, F_DAM, DT_SLASH, NA, NA, "1d8+4"); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_LONGBLADES, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, ST_AVERAGE, NA, NULL); @@ -6553,15 +6622,13 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); addflag(lastot->flags, F_SHINY, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 130, NA, NA, NULL); - addflag(lastot->flags, F_DAMTYPE, DT_SLASH, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 6, NA, NULL); + addflag(lastot->flags, F_DAM, DT_SLASH, NA, NA, "1d6"); addflag(lastot->flags, F_ACCURACY, 70, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_LONGBLADES, NA, NA, NULL); addot(OT_SCIMITAR, "scimitar", "A fast, sharp, curved blade.", MT_METAL, 2, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 120, NA, NA, NULL); - addflag(lastot->flags, F_DAMTYPE, DT_SLASH, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 8, 2, NULL); + addflag(lastot->flags, F_DAM, DT_SLASH, NA, NA, "1d8+2"); 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); @@ -6570,8 +6637,7 @@ void initobjects(void) { addot(OT_GLAIVE, "glaive", "A long pole with a sharpened head.", MT_METAL, 4, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 73, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 150, NA, NA, NULL); - addflag(lastot->flags, F_DAMTYPE, DT_SLASH, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 7, 3, NULL); + addflag(lastot->flags, F_DAM, DT_SLASH, NA, NA, "1d7+3"); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_POLEARMS, NA, NA, NULL); @@ -6581,8 +6647,7 @@ void initobjects(void) { addflag(lastot->flags, F_TRIPATTACK, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 130, NA, NA, NULL); - addflag(lastot->flags, F_DAMTYPE, DT_SLASH, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 2, 4, 0, NULL); + addflag(lastot->flags, F_DAM, DT_SLASH, NA, NA, "2d4"); addflag(lastot->flags, F_ACCURACY, 70, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_POLEARMS, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, ST_STRONG, NA, NULL); @@ -6590,9 +6655,8 @@ void initobjects(void) { addot(OT_HALBERD, "halberd", "A spiked axe blade mounted on a long shaft, with a hook on the back.", MT_METAL, 4, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 71, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 130, NA, NA, NULL); - addflag(lastot->flags, F_DAMTYPE, DT_CHOP, NA, NA, NULL); addflag(lastot->flags, F_TRIPATTACK, B_TRUE, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 9, 2, NULL); + addflag(lastot->flags, F_DAM, DT_CHOP, NA, NA, "1d9+2"); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_POLEARMS, NA, NA, NULL); @@ -6602,8 +6666,7 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 140, NA, NA, NULL); - addflag(lastot->flags, F_DAMTYPE, DT_PIERCE, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 8, 2, NULL); + addflag(lastot->flags, F_DAM, DT_PIERCE, NA, NA, "1d8+2"); addflag(lastot->flags, F_ACCURACY, 70, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_POLEARMS, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, ST_STRONG, NA, NULL); @@ -6612,8 +6675,7 @@ void initobjects(void) { addflag(lastot->flags, F_DISARMATTACK, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 120, NA, NA, NULL); - addflag(lastot->flags, F_DAMTYPE, DT_PIERCE, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 2, 4, 0, NULL); + addflag(lastot->flags, F_DAM, DT_PIERCE, NA, NA, "2d4"); addflag(lastot->flags, F_ACCURACY, 70, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_POLEARMS, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, ST_STRONG, NA, NULL); @@ -6621,8 +6683,7 @@ void initobjects(void) { addot(OT_SCYTHE, "scythe", "An agricultural hand tool for mowing grass, or reaping crops.", MT_METAL, 3, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 150, NA, NA, NULL); - addflag(lastot->flags, F_DAMTYPE, DT_SLASH, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 2, 4, NA, NULL); + addflag(lastot->flags, F_DAM, DT_SLASH, NA, NA, "2d4"); addflag(lastot->flags, F_ACCURACY, 65, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_POLEARMS, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, ST_AVERAGE, NA, NULL); @@ -6630,8 +6691,7 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 140, NA, NA, NULL); - addflag(lastot->flags, F_DAMTYPE, DT_PIERCE, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 8, NA, NULL); + addflag(lastot->flags, F_DAM, DT_PIERCE, NA, NA, "1d8"); addflag(lastot->flags, F_ACCURACY, 75, NA, NA, NULL); addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); @@ -6641,8 +6701,7 @@ void initobjects(void) { addot(OT_TRIDENT, "trident", "A three-pronged stabbing weapon.", MT_METAL, 3, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 110, NA, NA, NULL); - addflag(lastot->flags, F_DAMTYPE, DT_PIERCE, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 10, NA, NULL); + addflag(lastot->flags, F_DAM, DT_PIERCE, NA, NA, "1d10"); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_POLEARMS, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, ST_WEAK, NA, NULL); @@ -6651,8 +6710,7 @@ void initobjects(void) { addot(OT_QUARTERSTAFF, "quarterstaff", "A long, stout pole.", MT_WOOD, 2, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 130, NA, NA, NULL); - addflag(lastot->flags, F_DAMTYPE, DT_BASH, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 8, NA, NULL); + addflag(lastot->flags, F_DAM, DT_BASH, NA, NA, "1d8"); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_STAVES, NA, NA, NULL); @@ -6662,32 +6720,28 @@ void initobjects(void) { addot(OT_CLUB, "club", "A heavy, blunt wooden instrument to hit things with.", MT_STONE, 1.5, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 140, NA, NA, NULL); - addflag(lastot->flags, F_DAMTYPE, DT_BASH, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 6, NA, NULL); + addflag(lastot->flags, F_DAM, DT_BASH, NA, NA, "1d6"); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_CLUBS, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, ST_WEAK, NA, NULL); addot(OT_FLAIL, "flail", "A flexible chain attached to a heavy weight.", MT_METAL, 6, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 140, NA, NA, NULL); - addflag(lastot->flags, F_DAMTYPE, DT_BASH, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 2, 4, NA, NULL); + addflag(lastot->flags, F_DAM, DT_BASH, NA, NA, "2d4"); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_CLUBS, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, ST_AVERAGE, NA, NULL); addot(OT_FLAILHEAVY, "heavy flail", "A flexible chain attached to a very heavy weight.", MT_METAL, 12, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 155, NA, NA, NULL); - addflag(lastot->flags, F_DAMTYPE, DT_BASH, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 2, 6, NA, NULL); + addflag(lastot->flags, F_DAM, DT_BASH, NA, NA, "2d6"); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_CLUBS, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, ST_STRONG, NA, NULL); addot(OT_GREATCLUB, "great club", "An enormous, very heavy, blunt instrument to hit things with.", MT_STONE, 5, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 180, NA, NA, NULL); - addflag(lastot->flags, F_DAMTYPE, DT_BASH, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 10, 5, NULL); + addflag(lastot->flags, F_DAM, DT_BASH, NA, NA, "1d10+5"); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_CLUBS, NA, NA, NULL); @@ -6695,16 +6749,14 @@ void initobjects(void) { addot(OT_MACE, "mace", "A weapon with a heavy head on a solid shaft used to bludgeon opponents.", MT_METAL, 3, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 140, NA, NA, NULL); - addflag(lastot->flags, F_DAMTYPE, DT_BASH, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 8, NA, NULL); + addflag(lastot->flags, F_DAM, DT_BASH, NA, NA, "1d7+1"); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_CLUBS, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, ST_AVERAGE, NA, NULL); addot(OT_MORNINGSTAR, "morningstar", "A heavy, spiked mace.", MT_METAL, 3.5, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 150, NA, NA, NULL); - addflag(lastot->flags, F_DAMTYPE, DT_BASH, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 10, NA, NULL); + addflag(lastot->flags, F_DAM, DT_BASH, NA, NA, "1d9+1"); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_CLUBS, NA, NA, NULL); @@ -6713,24 +6765,21 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 100, NA, NA, NULL); addflag(lastot->flags, F_DISARMATTACK, B_TRUE, NA, NA, NULL); - addflag(lastot->flags, F_DAMTYPE, DT_BASH, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 6, 1, NULL); + addflag(lastot->flags, F_DAM, DT_BASH, NA, NA, "1d6+1"); addflag(lastot->flags, F_ACCURACY, 75, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_CLUBS, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_DEX, DX_DEXTROUS, NA, NULL); addot(OT_SPANNER, "spanner", "A long, heavy metal wrench.", MT_METAL, 1, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 120, NA, NA, NULL); - addflag(lastot->flags, F_DAMTYPE, DT_BASH, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 4, NA, NULL); + addflag(lastot->flags, F_DAM, DT_BASH, NA, NA, "1d4"); addflag(lastot->flags, F_ACCURACY, 65, NA, NA, NULL); addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OPERNEEDDIR, B_TRUE, NA, NA, "Use your spanner in which direction"); addflag(lastot->flags, F_USESSKILL, SK_CLUBS, NA, NA, NULL); addot(OT_STICK, "stick", "A sturdy wooden stick.", MT_WOOD, 0.5, OC_WEAPON); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, NULL); - addflag(lastot->flags, F_DAMTYPE, DT_BASH, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 2, NA, NULL); + addflag(lastot->flags, F_DAM, DT_BASH, NA, NA, "1d2"); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_CLUBS, NA, NA, NULL); @@ -6802,8 +6851,7 @@ void initobjects(void) { addot(OT_HANDOFGOD, "hand of god", "The ultimate power.", MT_FLESH, 0.1, OC_WEAPON); //addflag(lastot->flags, F_RARITY, H_DUNGEON, RR_UNIQUE, NA, NULL); //addflag(lastot->flags, F_DAMTYPE, DT_HOLY, NA, NA, NULL); - addflag(lastot->flags, F_DAMTYPE, DT_SLASH, NA, NA, NULL); - addflag(lastot->flags, F_DAM, 1, 6, 100, NULL); + addflag(lastot->flags, F_DAM, DT_SLASH, NA, NA, "1d6+100"); addflag(lastot->flags, F_ACCURACY, 500, NA, NA, NULL); addflag(lastot->flags, F_UNIQUE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_NONE, NA, NA, NULL); @@ -6885,8 +6933,8 @@ int isbetterwepthan(object_t *a, object_t *b) { getobname(b, nameb, b->amt); } - getdamrange(a->flags, NULL, &dama); - getdamrange(b->flags, NULL, &damb); + getdamrange(hasflag(a->flags, F_DAM), NULL, &dama); + getdamrange(hasflag(b->flags, F_DAM), NULL, &damb); // modify based on extra props if (hasflag(a->flags, F_HASBRAND)) { @@ -7046,7 +7094,7 @@ int isknownot(objecttype_t *ot) { if (k->id == ot->id) { // it DOES have a hidden name. // does the player know about it? - if (k->known) { + if (k->known == B_KNOWN) { return B_TRUE; } else { return B_FALSE; @@ -7127,6 +7175,35 @@ int isthrowmissile(object_t *o) { return B_FALSE; } +// shoudl we append {tried} to this object? +int istried(object_t *o) { + if (hasflag(o->flags, F_IDENTIFIED)) { + return B_FALSE; + } + + return istriedot(o->type); +} + +int istriedot(objecttype_t *ot) { + knowledge_t *k; + + for (k = knowledge; k ; k = k->next) { + if (k->id == ot->id) { + // it DOES have a hidden name. + // has the player tried it? + if (k->known == B_TRIED) { + return B_TRUE; + } else { + return B_FALSE; + } + + } + } + + // no hidden name, so can't be "tried" + return B_FALSE; +} + int isoperable(object_t *o) { if (hasflag(o->flags, F_OPERABLE)) return B_TRUE; //if (o->type->obclass->id == OC_TECH) return B_TRUE; @@ -7197,6 +7274,11 @@ int isrotting(object_t *o) { return B_FALSE; } +// returns the 'shield' flag +flag_t *isshield(object_t *o) { + return hasflag(o->flags, F_SHIELD); +} + int isthrownmissile(object_t *o) { if (hasflag(o->flags, F_THROWMISSILE)) { return B_TRUE; @@ -7205,7 +7287,6 @@ int isthrownmissile(object_t *o) { } int isweapon(object_t *o) { - //if ((o->type->obclass->id == OC_WEAPON) && hasflag(o->flags, F_DAM)) { if (o->type->obclass->id == OC_WEAPON) { return B_TRUE; } @@ -7490,7 +7571,7 @@ void makeknown(enum OBTYPE otid) { for (k = knowledge; k ; k = k->next) { if (k->id == otid) { - k->known = B_TRUE; + k->known = B_KNOWN; } } @@ -7499,6 +7580,18 @@ void makeknown(enum OBTYPE otid) { } } +void maketried(enum OBTYPE otid) { + knowledge_t *k; + + for (k = knowledge; k ; k = k->next) { + if (k->id == otid) { + if (k->known == B_UNKNOWN) { + k->known = B_TRIED; + } + } + } +} + void makewet(object_t *o, int amt) { cell_t *loc; lifeform_t *owner; @@ -7759,7 +7852,7 @@ void obdie(object_t *o) { } if (o->pile->owner) { - if (o->pile->owner->controller == C_PLAYER) { + if (isplayer(o->pile->owner)) { msg("Your %s %s!",noprefix(obname), desc); } else if (cansee(player, o->pile->owner)) { // don't announce decay death unless we are holding it @@ -7800,7 +7893,7 @@ void obdie(object_t *o) { } if (o->pile->owner) { - if (o->pile->owner->controller == C_PLAYER) { + if (isplayer(o->pile->owner)) { msg("Your %s %s!",noprefix(obname), desc); } else if (cansee(player, o->pile->owner)) { char monname[BUFLEN]; @@ -7984,7 +8077,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { getobname(o, obname, 1); - if ((lf->controller == C_PLAYER) || cansee(player, lf)) { + if ((isplayer(lf)) || cansee(player, lf)) { playercansee = B_TRUE; } else { playercansee = B_FALSE; @@ -8090,6 +8183,9 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { // TODO: move this to the end in case 'operate' fails taketime(lf, getactspeed(lf)); + // mark obejct as tried + maketried(o->type->id); + /* if (lf->controller != C_PLAYER) { @@ -8165,16 +8261,16 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { // special wands } else if (o->type->id == OT_WAND_WONDER) { int power; + // random power power = rnd(1,10); + // 1 in 3 chance of targetting yourself + if (rnd(1,3) == 1) { + where = lf->cell; + } + // random effect - switch (rnd(0,7)) { - case 0: // slow - dospelleffects(lf, OT_S_SLOW, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid); - break; - case 1: // gas - dospelleffects(lf, OT_S_CLOUDKILL, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid); - break; - case 2: // butterflies around user + switch (rnd(0,21)) { + case 0: // butterflies around user willid = B_TRUE; where = getrandomadjcell(lf->cell, WE_WALKABLE, B_ALLOWEXPAND); addmonster(where, R_BUTTERFLY, B_FALSE, rnd(10,20)); @@ -8182,20 +8278,68 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { msg("A swarm of butterflies appears!"); } break; - case 3: // light + case 1: // summon monster + dospelleffects(lf, OT_S_CREATEMONSTER, rnd(1,4), NULL, NULL, NULL, B_UNCURSED, &willid); + break; + case 2: // animate dead + dospelleffects(lf, OT_S_ANIMATEDEAD, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid); + break; + case 3: // blindness + dospelleffects(lf, OT_S_BLINDNESS, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid); + break; + case 4: // levitate + dospelleffects(lf, OT_S_LEVITATION, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid); + break; + case 5: // dispersal + dospelleffects(lf, OT_S_DISPERSAL, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid); + break; + case 6: // flash + dospelleffects(lf, OT_S_FLASH, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid); + break; + case 7: // light dospelleffects(lf, OT_S_LIGHT, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid); break; - case 4: // dark + case 8: // heal + dospelleffects(lf, OT_S_HEALING, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid); + break; + case 9: // minor heal + dospelleffects(lf, OT_S_HEALINGMIN, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid); + break; + case 10: // invis + dospelleffects(lf, OT_S_INVISIBILITY, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid); + break; + case 11: // haste + dospelleffects(lf, OT_S_HASTE, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid); + break; + case 12: // pull + dospelleffects(lf, OT_S_PULL, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid); + break; + case 13: // blast + dospelleffects(lf, OT_S_AIRBLAST, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid); + break; + case 14: // slow + dospelleffects(lf, OT_S_SLOW, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid); + break; + case 15: // sleep + dospelleffects(lf, OT_S_SLEEP, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid); + break; + case 16: // gas + dospelleffects(lf, OT_S_CLOUDKILL, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid); + break; + case 17: // dark dospelleffects(lf, OT_S_DARKNESS, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid); break; - case 5: // stone + case 18: // stone dospelleffects(lf, OT_S_PETRIFY, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid); break; - case 6: // fireball + case 19: // fireball dospelleffects(lf, OT_S_FIREBALL, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid); break; - case 7: // summon monster - dospelleffects(lf, OT_S_CREATEMONSTER, rnd(1,4), NULL, NULL, NULL, B_UNCURSED, &willid); + case 20: // poly + dospelleffects(lf, OT_S_POLYMORPH, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid); + break; + case 21: // teleport + dospelleffects(lf, OT_S_TELEPORT, power, lf , NULL, lf->cell, o->blessed, &willid); break; //oooooooooo } @@ -8341,7 +8485,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { msg("%s looks at %s.",buf, obname); } } else if (o->type->id == OT_DIGITALWATCH) { - if (lf->controller == C_PLAYER) { + if (isplayer(lf)) { gettimetext(buf); msg("It is currently %s.",buf); } else if (cansee(player, lf)) { @@ -8821,7 +8965,7 @@ void quaff(lifeform_t *lf, object_t *o) { getobname(o, obname, 1); - if ((lf->controller == C_PLAYER) || cansee(player, lf)) { + if ((isplayer(lf)) || cansee(player, lf)) { playercansee = B_TRUE; } else { playercansee = B_FALSE; @@ -8829,11 +8973,13 @@ void quaff(lifeform_t *lf, object_t *o) { taketime(lf, getactspeed(lf)); + maketried(o->type->id); + touch(lf, o); if (hasflag(o->flags, F_DEAD)) return; if (o->material->id == MT_ICE) { - if (lf->controller == C_PLAYER) { + if (isplayer(lf)) { msg("You can't drink this, it's frozen!"); } return; @@ -8940,7 +9086,7 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE potblessed, i case OT_POT_ACID: dam = rnd(5,10); losehp(lf, dam, DT_ACID, NULL, "drinking acid"); - if (lf->controller == C_PLAYER) { + if (isplayer(lf)) { msg("Your suffer massive internal burning!"); } else if (cansee(player, lf)) { getlfname(lf, buf); @@ -8976,7 +9122,7 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE potblessed, i // fix hp if (lf->hp < lf->maxhp) { gainhp(lf, lf->maxhp); // ie. full hp - if (lf->controller == C_PLAYER) { + if (isplayer(lf)) { msg("You feel completely healed!"); } else if (cansee(player, lf)) { getlfname(lf, buf); @@ -9298,7 +9444,7 @@ int readsomething(lifeform_t *lf, object_t *o) { getobname(o, obname, 1); - if ((lf->controller == C_PLAYER) || cansee(player, lf)) { + if ((isplayer(lf)) || cansee(player, lf)) { playercansee = B_TRUE; } else { playercansee = B_FALSE; @@ -9312,6 +9458,8 @@ int readsomething(lifeform_t *lf, object_t *o) { } taketime(lf, readtime); + maketried(o->type->id); + // some checks first... touch(lf, o); if (hasflag(o->flags, F_DEAD)) { @@ -9377,7 +9525,7 @@ int readsomething(lifeform_t *lf, object_t *o) { // id the scroll makeknown(o->type->id); real_getobname(o, obname, 1, B_FALSE, B_TRUE, B_FALSE, B_FALSE); // don't adjust for blindness - if (lf->controller == C_PLAYER) { + if (isplayer(lf)) { // tell the player msg("This is %s!",obname); more(); @@ -9421,7 +9569,7 @@ int readsomething(lifeform_t *lf, object_t *o) { if (isplayer(lf)) msg("The scroll crumbles to dust."); removeob(o, 1); } else if (o->type->id == OT_MAP) { - if (lf->controller == C_PLAYER) { + if (isplayer(lf)) { msg("You study your map for a while."); } } else if (o->type->id == OT_SCR_NOTHING) { @@ -9538,7 +9686,7 @@ object_t *relinkob(object_t *src, obpile_t *dst) { } // adjust letter if going to player? - if (dst->owner && (dst->owner->controller == C_PLAYER)) { + if (dst->owner && isplayer(dst->owner)) { src->letter = getnextletter(dst, &src->letter); } @@ -9658,7 +9806,7 @@ void shufflehiddennames(void) { int i,n; int total; hiddenname_t *a, *temp; - int shuffleamt = 20; + int shuffleamt = 500; total = 0; @@ -9878,7 +10026,7 @@ int takedamage(object_t *o, unsigned int howmuch, int damtype) { } if (o->pile->owner) { - if (o->pile->owner->controller == C_PLAYER) { + if (isplayer(o->pile->owner)) { msg("Your %s %s!",noprefix(obname), getobhurtname(o, damtype)); } else if (cansee(player, o->pile->owner)) { // don't announce decay damage for object you aren't holding @@ -10164,9 +10312,9 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed, if (!lfhasflag(target, F_NOPACK) && hasbp(target, BP_HANDS) && lfhasflag(target, F_HUMANOID) && !isimmobile(target) && - skillcheck(target, SC_DEX, 10*speed, isblind(target) ? -15 : 0)) { + skillcheck(target, SC_DEX, 15*speed, isblind(target) ? -15 : 0)) { willcatch = B_TRUE; - } else if (skillcheck(target, SC_DODGE, 20, 0)) { + } else if (skillcheck(target, SC_DODGE, 10*speed, isblind(target) ? -15 : 0)) { // then check if we dodge it... youhit = B_FALSE; } @@ -10188,7 +10336,7 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed, if (youhit) { if (willcatch) { if (seen) { - msg("%s catches %s.", targetname, obname); + msg("%s catch%s %s.", targetname, isplayer(target) ? "" : "es", obname); } moveob(o, target->pack, amt); return B_FALSE; @@ -10258,6 +10406,8 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed, sprintf(damstring, "%s (%s by %s)",obname,throwverbpast, realthrowernamea); losehp(target, shatterdam, DT_SLASH, thrower, damstring); } + + wepeffects(o->flags, target->cell, hasflag(o->flags, F_DAM), dam); } } else { if (!announcedmiss) { @@ -10984,6 +11134,17 @@ int validateobs(void) { printf("ERROR in object '%s' - teachs a skill which doesn't exist.\n", ot->name); goterror = B_TRUE; } + f = hasflag(ot->flags, F_DAM); + if (f) { + if (f->val[0] < 0) { + printf("ERROR in object '%s' - F_DAM does not specify damage type.\n", ot->name); + goterror = B_TRUE; + } + if (!strlen(f->text)) { + printf("ERROR in object '%s' - F_DAM does not have dice string.\n", ot->name); + goterror = B_TRUE; + } + } } for (sk = firstskill ; sk ; sk = sk->next) { diff --git a/objects.h b/objects.h index d33c2d3..afe5cf3 100644 --- a/objects.h +++ b/objects.h @@ -16,6 +16,7 @@ obpile_t *addobpile(lifeform_t *owner, cell_t *where); objecttype_t *addot(int id, char *name, char *description, int material, float weight, int obclassid); void adjustdammaterial(unsigned int *dam, enum DAMTYPE damtype, enum MATERIAL mat); void adjustdamob(object_t *o, unsigned int *dam, enum DAMTYPE damtype); +int adjustarmourpenalty(lifeform_t *lf, float amt); int adjustshieldpenalty(lifeform_t *lf, float amt); //void adjustprice(objecttype_t *ot, float *price ); void appendinscription(object_t *o, char *text); @@ -139,7 +140,10 @@ int ispourable(object_t *o); int ispushable(object_t *o); int isreadable(object_t *o); int isrotting(object_t *o); +flag_t *isshield(object_t *o); int isthrownmissile(object_t *o); +int istried(object_t *o); +int istriedot(objecttype_t *ot); int isweapon(object_t *o); int iswearable(object_t *o); void killmaterial(material_t *m); @@ -151,6 +155,7 @@ int knockbackob(object_t *o, int dir, int howfar, int power, lifeform_t *pusher) lifeform_t *makeanimated(lifeform_t *lf, object_t *o, int level); void makeduller(object_t *o, int howmuch); void makeknown(enum OBTYPE otid); +void maketried(enum OBTYPE otid); void makewet(object_t *o, int amt); object_t *moveob(object_t *src, obpile_t *dst, int howmany); void modbonus(object_t *o, int amt); diff --git a/spell.c b/spell.c index 22b53c3..346487f 100644 --- a/spell.c +++ b/spell.c @@ -617,6 +617,46 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef f = addflag(wep->flags, F_HEAVYBLOW, B_TRUE, NA, NA, NULL); attackcell(user, targcell); killflag(f); + } else if (abilid == OT_A_WARCRY) { + // announce + if (isplayer(user)) { + msg("You shout a blood-curdling war cry!"); + } + makenoise(user, N_WARCRY); + + // take a lot of time + taketime(user, getactspeed(user)*4); + + // all in range must pass a morale check or flee + for (target = user->cell->map->lf ; target ; target = target->next) { + if ((target != user) && cansee(target, user) && areenemies(target, user)) { + if (canhear(target, user->cell)) { + scare(target, user, rnd(5,10)); + } + } + } + } else if (abilid == OT_A_HURRICANESTRIKE) { + int dir; + cell_t *c; + flag_t *f,*f2; + // take time + // - NOTE: purposely using action speed, not weapon speed. + taketime(user, getactspeed(user)); + + // now don't take any more time for the actual attacks. + f = addflag(user->flags, F_NOTIME, B_TRUE, NA, NA, NULL); + // lower accuracy + f2 = addflag(user->flags, F_ACCURACYMOD, -20, NA, NA, NULL); + // attack all adjacent enemies + for (dir = DC_N; dir <= DC_NW; dir++) { + c = getcellindir(user->cell, dir); + if (c) { + attackcell(user, c); + } + } + // remove temporary flags + killflag(f); + killflag(f2); } else if (abilid == OT_A_INSPECT) { object_t *o; int difficulty; @@ -1229,7 +1269,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ rv = B_FALSE; } else { // didn't work for some reason - if (caster->controller == C_PLAYER) { + if (isplayer(caster)) { nothinghappens(); } return B_TRUE; @@ -1641,7 +1681,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ failed = B_TRUE; } } else { - if (caster->controller == C_PLAYER) { + if (isplayer(caster)) { msg("You have no line of fire to there!"); } failed = B_TRUE; @@ -1816,7 +1856,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } else { // next thing touched addflag(caster->flags, F_FREEZINGTOUCH, 1, NA, NA, NULL); - if (caster->controller == C_PLAYER) { + if (isplayer(caster)) { msg("Your hands begin to glow blue!"); if (seenbyplayer) *seenbyplayer = B_TRUE; } else if (cansee(player, caster)) { @@ -1839,7 +1879,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } if (o->material->id == MT_ICE) { // already made of ice? - if (caster->controller == C_PLAYER) { + if (isplayer(caster)) { nothinghappens(); } return B_TRUE; @@ -1850,7 +1890,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (rv) { if (rv == E_NOEFFECT) { if (o->pile->owner) { - if (o->pile->owner->controller == C_PLAYER) { + if (isplayer(o->pile->owner)) { msg("Your %s glows blue for a moment.",noprefix(buf)); if (seenbyplayer) *seenbyplayer = B_TRUE; } else if (haslos(player, o->pile->owner->cell)) { @@ -1864,14 +1904,14 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (seenbyplayer) *seenbyplayer = B_TRUE; } } else { - if (caster->controller == C_PLAYER) { + if (isplayer(caster)) { nothinghappens(); } } return B_TRUE; } else { if (o->pile->owner) { - if (o->pile->owner->controller == C_PLAYER) { + if (isplayer(o->pile->owner)) { msg("Your %s turn%s to ice!",noprefix(buf), (o->amt == 1) ? "s" : ""); if (seenbyplayer) *seenbyplayer = B_TRUE; } else if (haslos(player, o->pile->owner->cell)) { @@ -1925,8 +1965,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } else { howlong = getspellduration(5,25,blessed) + power; - addtempflag(target->flags, F_FASTACT, 5, NA, NA, NULL, howlong); - addtempflag(target->flags, F_FASTMOVE, 5, NA, NA, NULL, howlong); + addtempflag(target->flags, F_FASTACT, 10, NA, NA, NULL, howlong); + addtempflag(target->flags, F_FASTMOVE, 10, NA, NA, NULL, howlong); } } else if (spellid == OT_S_HEALING) { int donesomething = B_FALSE; @@ -2035,7 +2075,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ return B_TRUE; } - if (caster->controller == C_PLAYER) { + if (isplayer(caster)) { if (isidentified(o)) { // already identified? nothinghappens(); return B_TRUE; @@ -2058,7 +2098,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } else if (spellid == OT_S_INFINITEDEATH) { lifeform_t *l; - if (caster->controller == C_PLAYER) { + if (isplayer(caster)) { msg("A wave of incalculable evil blasts outwards from you!"); if (seenbyplayer) *seenbyplayer = B_TRUE; } else if (cansee(player, caster)) { @@ -2189,7 +2229,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } - if (caster->controller == C_PLAYER) { + if (isplayer(caster)) { msg("An image of your surroundings appears in your mind!"); if (seenbyplayer) *seenbyplayer = B_TRUE; } @@ -2273,7 +2313,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } else if (spellid == OT_S_MINDSCAN) { cell_t *where; int failed = B_FALSE; - if (caster->controller == C_PLAYER) { + if (isplayer(caster)) { // ask for a target cell sprintf(buf, "Whose mind will you scan?"); where = askcoords(buf, TT_MONSTER); @@ -2716,7 +2756,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (!newmap) { // create new map newmap = addmap(); - createmap(newmap, newdepth, caster->cell->map->habitat, NULL, findot(OT_STAIRSUP)); + createmap(newmap, newdepth, caster->cell->map->habitat); } @@ -2809,12 +2849,12 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ getlfname(target, targname); howlong = getspellduration(20,40,blessed) + (power*2); - if (!isplayer(target) && cansee(player, target) && !lfhasflag(player, F_SEEINVIS)) { + if (!isplayer(target) && cansee(player, target) ) { willannounce = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE; } addtempflag(target->flags, F_INVISIBLE, B_TRUE, NA, NA, NULL, howlong); - if (willannounce) { + if (willannounce && !lfhasflag(player, F_SEEINVIS)) { msg("%s flicker%s then vanishes!",targname, isplayer(target) ? "" : "s"); } } else if (spellid == OT_S_KNOCK) { @@ -3013,7 +3053,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ howlong = getspellduration(5,10,blessed) + (power/2); addtempflag(target->flags, F_NONCORPOREAL, B_TRUE, NA, NA, NULL, howlong); } else if (spellid == OT_S_POLYMORPH) { - race_t *r; + race_t *r = NULL; // ask for target if required if (!target && isplayer(caster)) { @@ -3050,7 +3090,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } if (isplayer(caster) && (power >= 5)) { - if (isplayer(target)) { + if (isplayer(target)) { // ie. polymorphing yourself askstring("What will you become", '?', buf, BUFLEN, NULL); } else { char buf2[BUFLEN]; @@ -3067,11 +3107,25 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (r && !appearsrandomly(r->id)) { r = NULL; } - } else { - // random race, but not the same! - r = target->race; - while (r == target->race) { - r = getrandomrace(NULL, 0); + } else { + 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) { + // random race, but not the same! + r = target->race; + while (r == target->race) { + r = getrandomrace(NULL, 0); + } } } @@ -3158,8 +3212,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } howlong = rnd(5,25) + power; - addtempflag(target->flags, F_SLOWACT, 5, NA, NA, NULL, howlong); - addtempflag(target->flags, F_SLOWMOVE, 5, NA, NA, NULL, howlong); + addtempflag(target->flags, F_SLOWACT, 10, NA, NA, NULL, howlong); + addtempflag(target->flags, F_SLOWMOVE, 10, NA, NA, NULL, howlong); if (isplayer(target) || haslos(player, target->cell)) { if (seenbyplayer) *seenbyplayer = B_TRUE; } diff --git a/text.c b/text.c index 8298521..0872a38 100644 --- a/text.c +++ b/text.c @@ -572,6 +572,10 @@ void texttospellopts(char *text, int *power, char *damstr, int *needgrab) { if (damstr) strcpy(damstr, ""); if (needgrab) *needgrab = B_FALSE; + if (!strlen(text)) { + return; + } + // for each arg for (n = 0; argname[n]; n++) { // search for it in text...