diff --git a/ai.c b/ai.c index c4f2b77..cf7e4e2 100644 --- a/ai.c +++ b/ai.c @@ -18,9 +18,6 @@ extern lifeform_t *player; extern enum ERROR reason; -extern flag_t *retflag[]; -extern int nretflags; - int wantdb = B_TRUE; void addignorecell(lifeform_t *lf, cell_t *c) { @@ -112,6 +109,8 @@ int aiattack(lifeform_t *lf, lifeform_t *victim, int timelimit) { } enum OBTYPE aigetattackspell(lifeform_t *lf, lifeform_t *victim) { + flag_t *retflag[MAXCANDIDATES]; + int nretflags; flag_t *f; enum OBTYPE poss[MAXPILEOBS]; int nposs = 0; @@ -129,7 +128,8 @@ enum OBTYPE aigetattackspell(lifeform_t *lf, lifeform_t *victim) { if (castok) { int i; - getflags(lf->flags, F_CANCAST, F_CANWILL, F_NONE); + + getflags(lf->flags, retflag, &nretflags, F_CANCAST, F_CANWILL, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if (aispellok(lf, f->val[0], victim, F_AICASTTOATTACK)) { @@ -160,6 +160,8 @@ enum OBTYPE aigetfleespell(lifeform_t *lf) { int nposs = 0,i; int db = B_FALSE; lifeform_t *fleefrom; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; if (lfhasflag(lf, F_DEBUG)) { db = B_TRUE; @@ -169,9 +171,8 @@ enum OBTYPE aigetfleespell(lifeform_t *lf) { if (f) { fleefrom = findlf(lf->cell->map, f->val[0]); } - - getflags(lf->flags, F_CANCAST, F_CANWILL, F_NONE); + getflags(lf->flags, retflag, &nretflags, F_CANCAST, F_CANWILL, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if (aispellok(lf, f->val[0], fleefrom, F_AICASTTOFLEE)) { @@ -921,6 +922,8 @@ void aiturn(lifeform_t *lf) { lifeform_t *master = NULL; enum ATTRBRACKET iqb; int n,i; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; /* @@ -981,7 +984,7 @@ void aiturn(lifeform_t *lf) { // use items, talk,etc /////////////////////////////////////////////// - if ((lf->race->id == R_PRISONER) && master && isplayer(master) && cansee(lf, master)) { + if (lfhasflag(lf, F_ISPRISONER) && master && isplayer(master) && cansee(lf, master)) { if (isoutdoors(lf->cell->map) && pctchance(20)) { object_t *o; say(lf, "Thanks for getting me out!", SV_TALK); @@ -992,7 +995,9 @@ void aiturn(lifeform_t *lf) { getobname(o, obname, o->amt); msgnocap("%c - %s", o->letter, obname); } + // no longer an ally killflagsofid(lf->flags, F_PETOF); + killflagsofid(lf->flags, F_ISPRISONER); } } @@ -1035,7 +1040,7 @@ void aiturn(lifeform_t *lf) { flag_t *poss[MAXCANDIDATES]; int nposs = 0,i; - getflags(lf->flags, F_RANDOMTALK, F_NONE); + getflags(lf->flags, retflag, &nretflags, F_RANDOMTALK, F_NONE); for (i = 0; i < nretflags; i++) { poss[nposs++] = retflag[i]; } @@ -1672,6 +1677,9 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG specificcheckok = B_FALSE; } } + if ((ot->id == OT_S_FREEZEOB) && lfhasflag(lf, F_FREEZINGTOUCH)) { + specificcheckok = B_FALSE; + } if ((ot->id == OT_S_HASTE) && (lfhasflag(victim, F_FASTACT) || lfhasflag(victim, F_FASTACTMOVE)) ) { specificcheckok = B_FALSE; } @@ -2036,10 +2044,12 @@ int lookforobs(lifeform_t *lf) { void makewantedoblist(lifeform_t *lf, int *noids, enum OBTYPE *oid, int *oidcovet,int *nwantflags, enum FLAG *wantflag, int *wantflagcovet) { int i; flag_t *f; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; // construct a list of objects which we want *noids = 0; - getflags(lf->flags, F_WANTS, F_WANTSOBFLAG, F_NONE); + getflags(lf->flags, retflag, &nretflags, F_WANTS, F_WANTSOBFLAG, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if (f->id == F_WANTS) { diff --git a/attack.c b/attack.c index 9e98e0b..788fd71 100644 --- a/attack.c +++ b/attack.c @@ -17,17 +17,12 @@ extern lifeform_t *player; -extern flag_t *retflag[]; -extern int nretflags; - int applyarmourdamage(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damtype) { object_t *armour = NULL; int damtaken = 0; // first of all, only apply some of the damage dam /= 2; - - // figure out what bit of armour was hit if (dam == 0) { return 0; } @@ -41,6 +36,7 @@ int applyarmourdamage(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damty } } + // figure out what bit of armour was hit if (!armour) { // pick a random piece of armour armour = getrandomarmour(lf); @@ -167,6 +163,8 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) { int lastweaponidx = -1; flag_t *sf; int saysorry = B_FALSE; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; // anyone there? if so just attack. if (c->lf) { @@ -282,7 +280,7 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) { } // then use all our innate attacks.. - getflags(lf->flags, F_HASATTACK, F_NONE); + getflags(lf->flags, retflag, &nretflags, F_HASATTACK, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if (f->id == F_HASATTACK) { @@ -421,6 +419,11 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) { sayphrase(lf, SP_SORRY, -1, NA, NULL); } + if (lfhasflagval(lf, F_INJURY, BP_HANDS, DT_SLASH, NA, NULL)) { + bleed(lf); + losehp(lf, 1, DT_DIRECT, NULL, "blood loss"); + } + return B_FALSE; } @@ -447,9 +450,11 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) int willheal = B_FALSE; int isunarmed = B_FALSE; skill_t *wepsk = NULL; - + flag_t *retflag[MAXCANDIDATES]; + int nretflags; int aidb = B_FALSE; flag_t *f; + enum BODYPART critpos = BP_NONE; if (wep) { wepsk = getobskill(wep); @@ -502,7 +507,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) } - getflags(lf->flags, F_NONCORPOREAL, F_NONE); + getflags(lf->flags, retflag, &nretflags, F_NONCORPOREAL, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; // ie. you have been made noncorporeal @@ -522,6 +527,27 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) hit = rolltohit(lf, victim, wep, &critical); + if (critical) { + critpos = getrandomcorebp(victim); + // replace victicname to include body part + if ((lf == victim) && !isplayer(lf)) { + sprintf(victimname, "it's %s", getbodypartname(critpos)); + } else { + getlfname(victim, buf); + sprintf(victimname, "%s%s %s", buf, getpossessive(buf), getbodypartname(critpos)); + } + } + + if (lf == victim) { + if (isplayer(lf)) { + strcpy(victimname, "yourself"); + } else { + strcpy(victimname, "itself"); + } + } else { + getlfname(victim, victimname); + } + // weapon passing through ghosts etc? if (hit) { if (lfhasflag(victim, F_NONCORPOREAL) && @@ -884,7 +910,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) losehp_real(victim, dam[i], damtype[i], lf, buf, B_FALSE, NULL); // victim's armour loses hp - if (reduceamt) { + if (reduceamt && !critical) { applyarmourdamage(victim, wep, dam[i], damtype[i]); // train armour practice(victim, SK_ARMOUR, 1); @@ -960,10 +986,9 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) } // critical hit effects - if (critical) { - if (lfhasflag(lf, F_CRITKNOCKDOWN)) { - fall(victim, lf, B_TRUE); - } + if (critical && damtypecausescriteffects(damtype[0])) { + criticalhit(lf, victim, critpos, damtype[0]); + } // confer flags from attacker? @@ -988,15 +1013,17 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) } } } else if ((lf->race->id == R_STIRGE) || (lf->race->id == R_LEECH)) { - // automatically latch on - if (!lfhasflag(victim, F_NONCORPOREAL) && !hasflag(lf->flags, F_ATTACHEDTO)) { - addflag(lf->flags, F_ATTACHEDTO, victim->id, NA, NA, NULL); + if (getexposedlimbs(victim)) { + // automatically latch on + if (!lfhasflag(victim, F_NONCORPOREAL) && !hasflag(lf->flags, F_ATTACHEDTO)) { + addflag(lf->flags, F_ATTACHEDTO, victim->id, NA, NA, NULL); + } } } } // retaliation happens even if victim died - getflags(victim->flags, F_RETALIATE, F_NONE); + getflags(victim->flags, retflag, &nretflags, F_RETALIATE, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if (f->id == F_RETALIATE) { @@ -1280,6 +1307,64 @@ int attackob(lifeform_t *lf, object_t *o, object_t *wep, flag_t *damflag) { return B_FALSE; } + +void criticalhit(lifeform_t *lf, lifeform_t *victim, enum BODYPART hitpos, enum DAMTYPE damtype) { + object_t *o; + // replace some dam types + if (damtype == DT_UNARMED) damtype = DT_BASH; + + if (damtype == DT_BITE) damtype = DT_SLASH; + if (damtype == DT_PIERCE) damtype = DT_SLASH; + if (damtype == DT_CHOP) damtype = DT_SLASH; + + if (damtype == DT_BASH) { + switch (hitpos) { + default: + case BP_BODY: + if (pctchance(40)) fall(victim, lf, B_TRUE); + if (!getarmour(victim, BP_BODY)) injure(victim, BP_BODY, damtype); + break; + case BP_HEAD: + if (pctchance(80)) fall(victim, lf, B_TRUE); + stun(victim, 2); + // chance of your helmet falling off + o = getarmour(victim, BP_HEAD); + if (o) { + if (isplayer(lf)) { + char buf[BUFLEN]; + getobname(o, buf, o->amt); + msg("Your %s falls off!", noprefix(buf)); + } else if (cansee(player, lf)) { + char buf[BUFLEN], lfname[BUFLEN]; + getobname(o, buf, o->amt); + getlfname(lf, lfname); + msg("%s%s %s falls off!", lfname, getpossessive(lfname), noprefix(buf)); + } + moveob(o, victim->cell->obpile, o->amt); + } else { + injure(victim, BP_HEAD, damtype); + } + break; + case BP_HANDS: + if (!getarmour(victim, BP_HANDS)) injure(victim, BP_HANDS, damtype); + // drop your weapon! + o = getweapon(victim); + if (o) drop(o, ALL); + break; + case BP_LEGS: + if (pctchance(70)) fall(victim, lf, B_TRUE); + if (!getarmour(victim, BP_LEGS)) injure(victim, BP_LEGS, damtype); + break; + } + } else if (damtype == DT_SLASH) { + if (!getarmour(victim, hitpos)) injure(victim, hitpos, damtype); + } + + if (lfhasflag(lf, F_CRITKNOCKDOWN) && !isprone(victim)) { + fall(victim, lf, B_TRUE); + } +} + int damtypecausesbleed(enum DAMTYPE dt) { switch (dt) { case DT_PIERCE: @@ -1298,6 +1383,21 @@ int damtypecausesbleed(enum DAMTYPE dt) { return B_FALSE; } +int damtypecausescriteffects(enum DAMTYPE dt) { + switch (dt) { + case DT_BASH: case DT_UNARMED: + case DT_SLASH: case DT_PIERCE: case DT_BITE: case DT_CHOP: + /* + case DT_EXPLOSIVE: + case DT_FALL: + */ + return B_TRUE; + default: + break; + } + return B_FALSE; +} + // returns the amount of damage the armour blocked... int getarmourdamreduction(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damtype) { int reduceamt = 0; @@ -1344,6 +1444,8 @@ void getarrange(int arating, int *min, int *max) { char *getattackverb(lifeform_t *lf, object_t *wep, enum DAMTYPE damtype, int dam, int maxhp) { float pct; enum LFSIZE ownersize = SZ_HUMAN; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; if (lf) { ownersize = getlfsize(lf); @@ -1354,7 +1456,7 @@ char *getattackverb(lifeform_t *lf, object_t *wep, enum DAMTYPE damtype, int dam if (wep) { int i; flag_t *f; - getflags(wep->flags, F_ATTACKVERB, F_NONE); + getflags(wep->flags, retflag, &nretflags, F_ATTACKVERB, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if ((f->val[0] == NA) && (f->val[1] == NA)) { @@ -1532,9 +1634,11 @@ enum DAMTYPE getdamtype(object_t *wep) { int getextradamlf(lifeform_t *lf, int *dam, enum DAMTYPE *damtype, int *ndam) { flag_t *f; int i; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; // special case - EXTRADAM goes onto INITIAL dam[] if the same type, rather than // adding a new one. - getflags(lf->flags, F_EXTRADAM, F_NONE); + getflags(lf->flags, retflag, &nretflags, F_EXTRADAM, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if (f->id == F_EXTRADAM) { @@ -1578,7 +1682,9 @@ int getextradamlf(lifeform_t *lf, int *dam, enum DAMTYPE *damtype, int *ndam) { int getextradamwep(object_t *wep, int *dam, enum DAMTYPE *damtype, int *ndam) { flag_t *f; int i; - getflags(wep->flags, F_FROZEN, F_ONFIRE, F_NONE); + flag_t *retflag[MAXCANDIDATES]; + int nretflags; + getflags(wep->flags, retflag, &nretflags, F_FROZEN, F_ONFIRE, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if (f->id == F_ONFIRE) { @@ -1613,7 +1719,9 @@ char *getkillverb(lifeform_t *victim, object_t *wep, enum DAMTYPE damtype, int d if (wep) { flag_t *f; int i; - getflags(wep->flags, F_KILLVERB, F_NONE); + flag_t *retflag[MAXCANDIDATES]; + int nretflags; + getflags(wep->flags, retflag, &nretflags, F_KILLVERB, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if (f->id == F_KILLVERB) { @@ -1740,6 +1848,11 @@ int getdamroll(object_t *o, lifeform_t *victim, flag_t *damflag) { } } + if (lfhasflagval(victim, F_INJURY, BP_BODY, DT_SLASH, NA, NULL)) { + // extra damage + dam += rnd(1,2); + } + return dam; } @@ -1902,12 +2015,15 @@ void modifyforsize(int *val, lifeform_t *lf, lifeform_t *victim, int howmuch, en int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical) { int acc,ev; int gothit = B_FALSE; - enum SKILLLEVEL slev; + enum SKILLLEVEL lorelev = PR_INEPT; int myroll; flag_t *f; + // remember lore about victim... + lorelev = getlorelevel(lf, victim->race->raceclass->id); - // base 5% critical chance - check this first. + + // critical chance - check this first. if (critical) { int critroll; critroll = rnd(1,100); @@ -1915,13 +2031,13 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical) // default *critical = 0; - // modify for lore - if (slev != PR_INEPT) { - myroll += (slev*5); // ie. up to 30% bonus - + // modify for lore level + if (lorelev != PR_INEPT) { + critroll -= (lorelev*5); // ie. up to 30% bonus } + limit(&critroll, 1, 100); - if (critroll >= 95) *critical = 1; + if (critroll <= getcritchance(lf, wep)) *critical = 1; } f = lfhasflag(lf, F_TRUESTRIKE); @@ -1946,9 +2062,6 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical) acc += 30; } - // remember lore about victim... - slev = getlorelevel(lf, victim->race->raceclass->id); - // modify for defender's evasion if (isprone(victim) || !cansee(victim, lf)) { ev = 0; @@ -1975,8 +2088,8 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical) } // modify for lore level - if (slev != PR_INEPT) { - acc += (slev*10); + if (lorelev != PR_INEPT) { + lorelev += (lorelev*10); } limit(&acc, 0, 100); @@ -2000,6 +2113,8 @@ void wepeffects(flagpile_t *fp, cell_t *where, flag_t *damflag, int dam) { lifeform_t *owner = NULL; object_t *wep; int i; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; if (!where) return; @@ -2015,7 +2130,7 @@ void wepeffects(flagpile_t *fp, cell_t *where, flag_t *damflag, int dam) { } victim = where->lf; - getflags(fp, F_DISARMATTACK, F_FLAMESTRIKE, F_HEAVYBLOW, F_HITCONFER, F_REVENGE, F_TRIPATTACK, F_NONE); + getflags(fp, retflag, &nretflags, F_DISARMATTACK, F_FLAMESTRIKE, F_HEAVYBLOW, F_HITCONFER, F_REVENGE, F_TRIPATTACK, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if (f->id == F_FLAMESTRIKE) { diff --git a/attack.h b/attack.h index 7505fed..22b2323 100644 --- a/attack.h +++ b/attack.h @@ -6,7 +6,9 @@ int attackcell(lifeform_t *lf, cell_t *c, int force); 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); +void criticalhit(lifeform_t *lf, lifeform_t *victim, enum BODYPART hitpos, enum DAMTYPE damtype); int damtypecausesbleed(enum DAMTYPE dt); +int damtypecausescriteffects(enum DAMTYPE dt); int getarmourdamreduction(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damtype); void getarrange(int arating, int *min, int *max); char *getattackverb(lifeform_t *lf, object_t *wep, enum DAMTYPE damtype, int dam, int maxhp); diff --git a/data/hiscores.db b/data/hiscores.db index d2e2052..792f6ab 100644 Binary files a/data/hiscores.db and b/data/hiscores.db differ diff --git a/defs.h b/defs.h index 795ab71..4f495df 100644 --- a/defs.h +++ b/defs.h @@ -334,7 +334,7 @@ enum MODTYPE { #define MAXPILEOBS 52 -#define MAXSPELLLEV 9 +#define MAXSPELLLEV 6 #define MAXRETCELLS 80 @@ -662,6 +662,7 @@ enum RACECLASS { RC_UNDEAD, }; +#define R_GODFIRST R_GODPURITY #define MAXGODS 4 enum RACE { @@ -678,7 +679,7 @@ enum RACE { R_PRISONER, R_TOWNGUARD, // gods - R_GODPURITY, // amberon + R_GODPURITY, // amberon - R_FIRSTGOD R_GODTHIEVES, // felix R_GODDEATH, // hecta R_GODMERCY, // yumi @@ -718,6 +719,7 @@ enum RACE { R_SATYR, R_SHADOWCAT, R_SPRITEFIRE, + R_SPRITEICE, R_TROGLODYTE, R_TROLL, R_VAMPIRE, @@ -1726,7 +1728,7 @@ enum FLAG { // v0 = up/down //F_STAIRDIR//, // val0 = direcion F_OPPOSITESTAIRS, // val0 = opposite kind of stairs - F_MAPLINK, // val0 = map to link to. + F_MAPLINK, // val0 = map id to link to. // v1/v2 = x/y // OR // text = obid to link to @@ -1777,6 +1779,7 @@ enum FLAG { F_ATTREQ, // requires attrib v0 to be at least v1 //F_DAMTYPE, // val0 = damage type //F_DAM, // val0 = ndice, val1 = nsidesondie, val2 = mod + F_CRITCHANCE, // v0 = %chance of critical hit with this weapon F_DAM, // v0 = damtype, text = 1d1+1 F_MISSILEDAM, // val0 = dam if it hits (without speed multiplier) F_ACCURACY, // 100 - val0 = modify to tohit% (ie. higher is better) @@ -2000,6 +2003,7 @@ enum FLAG { F_LASTDIR, // this is the last direction we moved. //F_OWNERLASTDIR, // for pets, this it the last dir our owner moved // when we could see them. + F_ISPRISONER, // this lf wants to escape to the surface F_PETOF, // this lf is a pet of lfid v0 // v1/2 = last known location of my owner. // optional text is last known movement dir. @@ -2173,6 +2177,7 @@ enum FLAG { F_GRABBING, // you are grabbing lf id v0 F_HURRICANESTRIKE, // lf is performing a hurricane strike F_HIDING, // lifeform is hiding. v0 is modifier to stealth checks. + F_INJURY, // v0 = where, v1 = damtype F_INVISIBLE, // lifeform is invisible F_INVULNERABLE,// immune to most damage // this can apply to objects too! @@ -2285,9 +2290,11 @@ enum FLAG { // doorway with no door). F_AUTOPOPULATE, // fill this vault with obs/mons/pillars like normal rooms F_NORANDOM, // this vault does not randomly appear - F_VAULTATOB, // v0/1=x/y, v1=pctchance, text=obname - F_VAULTATLF, // v0/1=x/y, v1=pctchance, text=lfname - F_VAULTATCELL, // v0/1=x/y, v1=pctchance, text=cellname + F_VAULTATOB, // v0/1=x/y, v2=pctchance, text=obname + F_VAULTATLF, // v0/1=x/y, v2=pctchance, text=lfname + F_VAULTATCELL, // v0/1=x/y, v2=pctchance, text=cellname + F_VAULTATONEOF, // v0=thingtype, v1 = pctchance + // text=(x,y)(x,y)(x,y)...(x,y) thingname F_VAULTBOX, // v0=thingtype, v1=pctchance, v2=fill?, text=x1,y1,x2,y2,thingname F_VAULTDLEVMIN, // v0 = mininum map depth/difficulty for this vault F_VAULTDLEVMAX, // v0 = maximum map depth/difficulty for this vault @@ -2636,10 +2643,17 @@ typedef struct habitat_s { struct habitat_s *next, *prev; } habitat_t; +typedef struct room_s { + int id; + int x1,y1,x2,y2; + struct vault_s *vault; +} room_t; + typedef struct map_s { int id; region_t *region; int depth; + struct room_s room[MAXROOMS]; int nrooms; // how many rooms on this map char *name; // name of this map habitat_t *habitat; @@ -2713,8 +2727,7 @@ typedef struct glyph_s { typedef struct cell_s { map_t *map; // pointer back to map int x,y; // map coords - int roomid; - vault_t *vault; + struct room_s *room; struct celltype_s *type; struct obpile_s *obpile; enum LIGHTLEV lit; diff --git a/doc/vaults.txt b/doc/vaults.txt index eaef231..f4810c6 100644 --- a/doc/vaults.txt +++ b/doc/vaults.txt @@ -31,6 +31,9 @@ Flags can be: 'type' can be: ob, mon, cell coords can be negative ("count back from right/bottom") + atoneof(x,y)(x,y)...(x,y) type:what[:pct] + // place 'what' at one of the given positions (picked randomly) + exitat(x,y) // vault exit is at position x,y box(x,y,x2,y2) type:what[:pct] // outline box with what diff --git a/flag.c b/flag.c index 352855d..874ef26 100644 --- a/flag.c +++ b/flag.c @@ -11,9 +11,6 @@ #include "spell.h" #include "text.h" -flag_t *retflag[MAXCANDIDATES]; -int nretflags; - extern enum GAMEMODE gamemode; extern int needredraw; extern int statdirty; @@ -261,6 +258,23 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, } } + if (flagcausesloscalc(f->id)) { + cell_t *where = NULL; + // everyone who can see this cell recalcs their los + where = getflagpilelocation(f->pile); + if (where) { + lifeform_t *l; + for (l = where->map->lf ; l ; l = l->next) { + if (haslos(l, where)) { + precalclos(l); + if (isplayer(l)) { + redrawscreenatend = B_TRUE; + } + } + } + } + } + // special effects if (f->pile->owner) { float pct; @@ -349,6 +363,15 @@ int countflags(flagpile_t *fp) { return count; } + +int flagcausesloscalc(enum FLAG fid) { + switch (fid) { + case F_BLOCKSVIEW: + return B_TRUE; + default: break; + } + return B_FALSE; +} int flagcausesredraw(lifeform_t *lf, enum FLAG fid) { if (!lf) return B_FALSE; @@ -366,6 +389,7 @@ int flagcausesredraw(lifeform_t *lf, enum FLAG fid) { case F_PRODUCESLIGHT: case F_PRONE: case F_RAGE: + case F_SECRET: case F_SEEINDARK: case F_SEEINVIS: case F_SPRINTING: @@ -687,6 +711,7 @@ void killflag(flag_t *f) { flag_t *nextone, *lastone; lifeform_t *lf; map_t *redolight = NULL; + cell_t *redolos = NULL; int redostat = B_FALSE; int redoscreen = B_FALSE; int i,dopleasegod[MAXGODS]; @@ -722,7 +747,9 @@ void killflag(flag_t *f) { // ie. this lf was fleeing from the player, and // got away. if (isplayer(fleefrom) && !cansee(lf, fleefrom)) { - dopleasegod[R_GODMERCY] += 5; + for (i = 0; i < ngodlfs; i++) { + if (godlf[i]->race->id == R_GODMERCY) dopleasegod[i] += 5; + } } } } @@ -732,8 +759,12 @@ void killflag(flag_t *f) { if (flagcausesredraw(f->pile->owner, f->id)) redoscreen = B_TRUE; if (flagcausesstatredraw(f->pile->owner, f->id)) redostat = B_TRUE; + if (flagcausesloscalc(f->id)) { + redolos = getflagpilelocation(f->pile); + } + // notify - if ((gamemode == GM_GAMESTARTED)) { + if (gamemode == GM_GAMESTARTED) { if (lf) { // special cases if (f->id == F_FLEEFROM) { @@ -817,17 +848,28 @@ void killflag(flag_t *f) { pleasegodmaybe(godlf[i]->race->id, dopleasegod[i]); } } + if (redolos) { + // everyone who can see this cell recalcs their los + lifeform_t *l; + for (l = redolos->map->lf ; l ; l = l->next) { + if (haslos(l, redolos)) { + precalclos(l); + if (isplayer(l)) redoscreen = B_TRUE; + } + } + } if (redolight) { calclight(redolight); precalclos(player); + needredraw = B_TRUE; } - if (redoscreen || redolight) { + if (redoscreen) { needredraw = B_TRUE; } if (redostat) { statdirty = B_TRUE; } - if (statdirty || needredraw || redolight) { + if (statdirty || needredraw ) { drawscreen(); } } @@ -1065,14 +1107,25 @@ void timeeffectsflag(flag_t *f, int howlong) { } } +cell_t *getflagpilelocation(flagpile_t *fp) { + cell_t *where = NULL; + // everyone who can see this cell recalcs their los + if (fp->owner) { + where = fp->owner->cell; + } else if (fp->ob) { + where = getoblocation(fp->ob); + } + return where; +} + // populates retflag & nretflags with matching flags -int getflags(flagpile_t *fp, ... ) { +int getflags(flagpile_t *fp, flag_t **retflag, int *nretflags, ... ) { va_list flags; enum FLAG wantflag[MAXCANDIDATES]; int nwantflags,i; flag_t *f; - va_start(flags, fp); + va_start(flags, nretflags); nwantflags = 0; wantflag[nwantflags] = va_arg(flags, enum FLAG); while (wantflag[nwantflags] != F_NONE) { @@ -1082,15 +1135,15 @@ int getflags(flagpile_t *fp, ... ) { va_end(flags); // now populate retflag[] with matches flags - nretflags = 0; + *nretflags = 0; for (i = 0; i < nwantflags; i++) { f = hasflag(fp, wantflag[i]); while (f && (f->id == wantflag[i])) { - retflag[nretflags++] = f; + retflag[(*nretflags)++] = f; f = f->next; } } - return nretflags; + return *nretflags; } int modcounter(flagpile_t *fp, int amt) { diff --git a/flag.h b/flag.h index 62b0e58..03abb88 100644 --- a/flag.h +++ b/flag.h @@ -12,10 +12,12 @@ void changeflagtext(flag_t *f, char *newtext); void copyflag(flagpile_t *dst, flagpile_t *src, enum FLAG id); void copyflags(flagpile_t *dst, flagpile_t *src, int lifetime); int countflags(flagpile_t *fp); +int flagcausesloscalc(enum FLAG fid); int flagcausesredraw(lifeform_t *lf, enum FLAG fid); int flagcausesstatredraw(lifeform_t *lf, enum FLAG fid); int flagstacks(enum FLAG fid); -int getflags(flagpile_t *fp, ... ); +cell_t *getflagpilelocation(flagpile_t *fp); +int getflags(flagpile_t *fp, flag_t **retflag, int *nretflags, ... ); int modcounter(flagpile_t *fp, int amt); flag_t *hasflag(flagpile_t *fp, int id); flag_t *hasflagknown(flagpile_t *fp, int id); diff --git a/io.c b/io.c index e597c22..1dbf2c4 100644 --- a/io.c +++ b/io.c @@ -45,9 +45,6 @@ extern int nmsghist; extern lifeform_t *godlf[]; extern int ngodlfs; -extern flag_t *retflag[]; -extern int nretflags; - extern prompt_t prompt; extern object_t *retobs[MAXPILEOBS+1]; @@ -528,6 +525,8 @@ cell_t *askcoords(char *prompt, char *subprompt, int targettype, lifeform_t *src int x,y; enum ATTRBRACKET iqb; iqb = getattrbracket(getattr(player, A_IQ), A_IQ, NULL); + flag_t *retflag[MAXCANDIDATES]; + int nretflags; // remember previously targetted lifeforms if (startlf > 0) { @@ -791,7 +790,7 @@ cell_t *askcoords(char *prompt, char *subprompt, int targettype, lifeform_t *src strcat(extrainfo, "enraged"); } - getflags(c->lf->flags, F_RETALIATE, F_NONE); + getflags(c->lf->flags, retflag, &nretflags, F_RETALIATE, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if (strlen(extrainfo)) strcat(extrainfo, ", "); @@ -1060,6 +1059,7 @@ int announceflaggain(lifeform_t *lf, flag_t *f) { lifeform_t *lf2; char lfname[BUFLEN]; char buf[BUFLEN]; + char buf3[BUFLEN]; char *buf2; if (isdead(player)) { @@ -1300,6 +1300,19 @@ int announceflaggain(lifeform_t *lf, flag_t *f) { donesomething = B_TRUE; } break; + case F_INJURY: + strcpy(buf, getinjuredbpname(f->val[0])); + strcpy(buf3, getinjuryname(f->val[1])); + if (isplayer(lf)) { + msg("^%cYour %s %s %s!", getlfcol(lf, CC_VBAD), buf, + (f->val[1] == DT_SLASH) ? "starts" : "is", buf3); + } else { + msg("^%c%s%s %s %s %s!", getlfcol(lf, CC_VBAD), + lfname, getpossessive(lfname), buf, + (f->val[1] == DT_SLASH) ? "starts" : "is", + buf3); + } + break; case F_INVISIBLE: if (isplayer(lf)) { if (lfhasflag(player, F_SEEINVIS)) { @@ -1625,6 +1638,7 @@ int announceflaggain(lifeform_t *lf, flag_t *f) { int announceflagloss(lifeform_t *lf, flag_t *f) { char lfname[BUFLEN]; + char buf[BUFLEN], buf3[BUFLEN]; lifeform_t *lf2; int donesomething = B_FALSE; @@ -1866,6 +1880,16 @@ int announceflagloss(lifeform_t *lf, flag_t *f) { donesomething = B_TRUE; } break; + case F_INJURY: + strcpy(buf, getinjuredbpname(f->val[0])); + strcpy(buf3, getinjuryname(f->val[1])); + if (isplayer(lf)) { + msg("^%cYour %s %s has healed.", getlfcol(lf, CC_VGOOD), buf3, buf); + } else { + msg("^%c%s%s %s %s has healed.", getlfcol(lf, CC_VGOOD), + lfname, getpossessive(lfname), buf3, buf); + } + break; case F_INVISIBLE: if (isplayer(lf)) { msg("Your are no longer invisible."); @@ -2968,6 +2992,8 @@ void describegod(lifeform_t *god) { char goddesc[BUFLEN]; int i; flag_t *f; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; cls(); f = hasflag(god->flags, F_GODOF); @@ -2982,7 +3008,7 @@ void describegod(lifeform_t *god) { wmove(mainwin, 2, 0); wprintw(mainwin, "%s likes ", godname); - getflags(god->flags, F_GODLIKES, F_NONE); + getflags(god->flags, retflag, &nretflags, F_GODLIKES, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if (i == 0) { @@ -2995,7 +3021,7 @@ void describegod(lifeform_t *god) { } wprintw(mainwin, ".\n\n"); wprintw(mainwin, "%s dislikes ", godname); - getflags(god->flags, F_GODDISLIKES, F_NONE); + getflags(god->flags, retflag, &nretflags, F_GODDISLIKES, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if (i == 0) { @@ -3024,6 +3050,8 @@ void describeob(object_t *o) { int obknown; int i; int throwrange; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; cls(); @@ -3141,8 +3169,7 @@ void describeob(object_t *o) { y++; strcpy(buf, ""); - - getflags(o->flags, F_AMMOOB, F_NONE); + getflags(o->flags, retflag, &nretflags, F_AMMOOB, F_NONE); for (i = 0; i < nretflags; i++) { objecttype_t *ot; ff = retflag[i]; @@ -3179,6 +3206,7 @@ void describeob(object_t *o) { } else if (o->type->obclass->id == OC_WEAPON) { flag_t *damflag; int delay; + int critchance; sprintf(buf, "It is a %s weapon", hasflag(o->flags, F_TWOHANDED) ? "two-handed" : "single handed"); damflag = hasflag(o->flags, F_DAM); if (damflag) { @@ -3239,6 +3267,12 @@ void describeob(object_t *o) { mvwprintw(mainwin, y, 0, " Its attack delay is %d%%.",delay - 100); y++; + critchance = getcritchance(player, o); + if (critchance > 0) { + mvwprintw(mainwin, y, 0, " You have a %d%% critical hit chance with it.", critchance); + y++; + } + f = hasflag(o->flags, F_ACCURACY); if (f) { int acc; @@ -4127,7 +4161,7 @@ void docomms(lifeform_t *lf) { addchoice(&prompt, '>', "Keep your distance.", NULL, NULL); } } else if (ishirable(lf) ) { - if (lf->race->id == R_PRISONER) { + if (lfhasflag(lf, F_ISPRISONER)) { addchoice(&prompt, 'j', "Join me, and I will help you escape.", NULL, NULL); } else { addchoice(&prompt, 'j', "Join me on my quest!", NULL, NULL); @@ -4285,7 +4319,7 @@ void docomms(lifeform_t *lf) { } } - // TODO: only get speech bonus if humanoid+intelligent + // TODO: only get speech bonus if humanoid (ie they can understand you) mod += getskill(player, SK_SPEECH); if (skillcheckvs(player, SC_MORALE, mod, lf, SC_MORALE, 0)) { @@ -5353,8 +5387,8 @@ void dohelp(char helpmode) { if (helpmode == '?') { initprompt(&prompt, "What would you like help with (ESC when done)?"); addchoice(&prompt, '?', "Keyboard Commands", NULL, NULL); - addchoice(&prompt, 'g', "Skill Descriptions", NULL, NULL); - addchoice(&prompt, 's', "God Descriptions", NULL, NULL); + addchoice(&prompt, 's', "Skill Descriptions", NULL, NULL); + addchoice(&prompt, 'g', "God Descriptions", NULL, NULL); addchoice(&prompt, '-', "(done)", NULL, NULL); prompt.maycancel = B_TRUE; ch = getchoice(&prompt); @@ -5363,6 +5397,7 @@ void dohelp(char helpmode) { case 'g': case 's': helpmode = ch; + break; default: done = B_TRUE; break; @@ -6697,7 +6732,7 @@ void handleinput(void) { stopnow = B_TRUE; } // stop if enter/exit a room - if (player->prevcell[0] && (player->cell->roomid != player->prevcell[0]->roomid)) { + if (player->prevcell[0] && (getroomid(player->cell) != getroomid(player->prevcell[0]))) { stopnow = B_TRUE; } @@ -7829,6 +7864,8 @@ void showlfstats(lifeform_t *lf, int showall) { enum SKILLLEVEL lorelev; enum COLOUR lorecol; int min,max; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; h = getmaxy(mainwin); @@ -8430,6 +8467,22 @@ void showlfstats(lifeform_t *lf, int showall) { mvwprintw(mainwin, y, 0, "%s %s hiding.", you(lf), is(lf)); y++; } + getflags(lf->flags, retflag, &nretflags, F_INJURY, F_NONE); + for (i = 0; i < nretflags; i++) { + char buf[BUFLEN], buf2[BUFLEN],buf3[BUFLEN]; + f = retflag[i]; + strcpy(buf, getinjuredbpname(f->val[0])); + strcpy(buf2, getinjuryname(f->val[1])); + strcpy(buf3, getinjurydesc(f->val[0], f->val[1])); + if (isplayer(lf)) { + msg("^%cYour %s is %s%s.", getlfcol(lf, CC_VBAD), buf, buf2, buf3); + } else { + char lfname[BUFLEN]; + getlfname(lf, lfname); + msg("^%c%s%s %s is %s%s.", getlfcol(lf, CC_VBAD), + lfname, getpossessive(lfname), buf, buf2, buf3); + } + } f = lfhasknownflag(lf, F_INVISIBLE); if (f && (f->known)) { mvwprintw(mainwin, y, 0, "%s %s invisible.", you(lf), is(lf)); @@ -9055,47 +9108,61 @@ void showlfstats(lifeform_t *lf, int showall) { y++; } - // extra dam - can have it multiple times - for (f = lf->flags->first ; f; f = f->next) { - if (f->id == F_EXTRADAM) { - int ndice,nsides,bonus; - char dicebuf[BUFLEN]; - char mmbuf[BUFLEN]; - char damtypebuf[BUFLEN]; - int min = 0,max = 0; - texttodice(f->text, &ndice,&nsides,&bonus); - - if ((f->lifetime == FROMOBEQUIP) || - (f->lifetime == FROMOBHOLD) || - (f->lifetime == FROMOBACTIVATE) ) { - object_t *obfrom; - obfrom = findobbyid(lf->pack, f->obfrom); - if (obfrom) { - int bonusdam; - sumflags(obfrom->flags, F_BONUS, &bonusdam, NULL, NULL); - bonus += bonusdam; - } - } - - if (f->val[0] == NA) { - strcpy(damtypebuf, "damage"); - } else { - sprintf(damtypebuf, "%s damage", getdamname(f->val[0])); - } - - dicetotext(ndice, nsides, bonus, &min, &max, dicebuf, mmbuf); - if (strcmp(dicebuf, mmbuf)) { - mvwprintw(mainwin, y, 0, "%s deal%s %s (%s) extra %s each hit.", you(lf), - isplayer(lf) ? "" : "s", dicebuf, mmbuf, damtypebuf); - } else { - mvwprintw(mainwin, y, 0, "%s deal%s %s extra %s each hit.", you(lf), - isplayer(lf) ? "" : "s", dicebuf, damtypebuf); - } - y++; - + getflags(lf->flags, retflag, &nretflags, F_INJURY, F_NONE); + for (i = 0; i < nretflags; i++) { + char buf[BUFLEN], buf2[BUFLEN]; + f = retflag[i]; + strcpy(buf, getinjuredbpname(f->val[0])); + strcpy(buf2, getinjuryname(f->val[1])); + if (isplayer(lf)) { + msg("^%cYour %s is %s.", getlfcol(lf, CC_VBAD), buf, buf2); + } else { + char lfname[BUFLEN]; + getlfname(lf, lfname); + msg("^%c%s%s %s is %s.", getlfcol(lf, CC_VBAD), + lfname, getpossessive(lfname), buf, buf2); } } + getflags(lf->flags, retflag, &nretflags, F_EXTRADAM, F_NONE); + for (i = 0; i < nretflags; i++) { + int ndice,nsides,bonus; + char dicebuf[BUFLEN]; + char mmbuf[BUFLEN]; + char damtypebuf[BUFLEN]; + int min = 0,max = 0; + f = retflag[i]; + texttodice(f->text, &ndice,&nsides,&bonus); + + if ((f->lifetime == FROMOBEQUIP) || + (f->lifetime == FROMOBHOLD) || + (f->lifetime == FROMOBACTIVATE) ) { + object_t *obfrom; + obfrom = findobbyid(lf->pack, f->obfrom); + if (obfrom) { + int bonusdam; + sumflags(obfrom->flags, F_BONUS, &bonusdam, NULL, NULL); + bonus += bonusdam; + } + } + + if (f->val[0] == NA) { + strcpy(damtypebuf, "damage"); + } else { + sprintf(damtypebuf, "%s damage", getdamname(f->val[0])); + } + + dicetotext(ndice, nsides, bonus, &min, &max, dicebuf, mmbuf); + if (strcmp(dicebuf, mmbuf)) { + mvwprintw(mainwin, y, 0, "%s deal%s %s (%s) extra %s each hit.", you(lf), + isplayer(lf) ? "" : "s", dicebuf, mmbuf, damtypebuf); + } else { + mvwprintw(mainwin, y, 0, "%s deal%s %s extra %s each hit.", you(lf), + isplayer(lf) ? "" : "s", dicebuf, damtypebuf); + } + y++; + } + f = lfhasknownflag(lf, F_EXTRALUCK); if (f) { mvwprintw(mainwin, y, 0, "Your luck is being boosted.", you(lf)); diff --git a/lf.c b/lf.c index 28de526..009900d 100644 --- a/lf.c +++ b/lf.c @@ -33,9 +33,6 @@ extern skill_t *firstskill, *lastskill; extern objecttype_t *objecttype; extern lifeform_t *player; -extern flag_t *retflag[]; -extern int nretflags; - extern glyph_t playerglyph; extern glyph_t tempglyph; @@ -264,6 +261,8 @@ int calcxp(lifeform_t *lf) { int maxhdroll; int i; float xpconstant = 1; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; if (lfhasflag(lf, F_DEBUG)) { db = B_TRUE; @@ -320,7 +319,7 @@ int calcxp(lifeform_t *lf) { // spells - getflags(lf->flags, F_CANCAST, F_CANWILL, F_NONE); + getflags(lf->flags, retflag, &nretflags, F_CANCAST, F_CANWILL, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if (f->id == F_CANCAST) { @@ -839,6 +838,12 @@ int canquaff(lifeform_t *lf, object_t *o) { } int cansee(lifeform_t *viewer, lifeform_t *viewee) { + return cansee_real(viewer, viewee, B_TRUE); +} + +// if uselos is false, then this function means "COULD viewer see +// viewee assuming they have los?" +int cansee_real(lifeform_t *viewer, lifeform_t *viewee, int uselos) { object_t *o; flag_t *f; int xray = 0; @@ -878,9 +883,11 @@ int cansee(lifeform_t *viewer, lifeform_t *viewee) { } } - // no line of sight? - if (!haslos(viewer, viewee->cell)) { - return B_FALSE; + if (uselos) { + // no line of sight? + if (!haslos(viewer, viewee->cell)) { + return B_FALSE; + } } // viewee is invisible? @@ -942,6 +949,8 @@ int canwear(lifeform_t *lf, object_t *o, enum BODYPART where) { int i; object_t *oo; flag_t *f; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; reason = E_OK; if ((where != BP_NONE) && !hasbp(lf, where)) { @@ -966,7 +975,7 @@ int canwear(lifeform_t *lf, object_t *o, enum BODYPART where) { } // other flags to check - getflags(o->flags, F_ATTREQ, F_NONE); + getflags(o->flags, retflag, &nretflags, F_ATTREQ, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if (f->id == F_ATTREQ) { @@ -983,7 +992,7 @@ int canwear(lifeform_t *lf, object_t *o, enum BODYPART where) { enum BODYPART possbp[MAXBODYPARTS]; int nparts = 0; int i; - getflags(o->flags, F_GOESON, F_NONE); + getflags(o->flags, retflag, &nretflags, F_GOESON, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if (f->id == F_GOESON) { @@ -1035,6 +1044,8 @@ int canwear(lifeform_t *lf, object_t *o, enum BODYPART where) { int canweild(lifeform_t *lf, object_t *o) { flag_t *f; enum BODYPART weildloc,otherloc; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; weildloc = getweildloc(o, &otherloc, NULL); @@ -1069,7 +1080,7 @@ int canweild(lifeform_t *lf, object_t *o) { if (o) { int i; - getflags(o->flags, F_ATTREQ, F_TWOHANDED, F_NONE); + getflags(o->flags, retflag, &nretflags, F_ATTREQ, F_TWOHANDED, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if (f->id == F_ATTREQ) { @@ -1361,8 +1372,22 @@ int celltransparentfor(lifeform_t *lf, cell_t *c, int *xray, int *rangemod) { // solid cells stop los if (!c->type->transparent) { - if (xray && *xray) (*xray)--; - else return B_FALSE; + if (xray && *xray) { + (*xray)--; + } else return B_FALSE; + } + + // check for lfs which block view + if (c->lf && (c->lf != lf) && cansee_real(lf, c->lf, B_FALSE)) { + int sizediff; + // high sizediff means that the lf in the cell is bigger than the viewer + sizediff = getlfsize(c->lf) - getlfsize(lf); + // lf greater than 2 sizes bigger than us? + if (sizediff >= 2) { + if (xray && *xray) { + (*xray) -= (sizediff-1); + } else return B_FALSE; + } } // check for objects which block view @@ -1553,7 +1578,9 @@ float comparelfs(lifeform_t *lf1, lifeform_t *lf2) { int countinnateattacks(lifeform_t *lf) { int count = 0,i; flag_t *f; - getflags(lf->flags, F_HASATTACK, F_NONE); + flag_t *retflag[MAXCANDIDATES]; + int nretflags; + getflags(lf->flags, retflag, &nretflags, F_HASATTACK, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if (f->id == F_HASATTACK) count++; @@ -1727,6 +1754,8 @@ void die(lifeform_t *lf) { int vaporised = B_FALSE, i; int willbecomeghost = B_FALSE; object_t *corpse = NULL; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; if (cansee(player, lf)) { needredraw = B_TRUE; @@ -1948,7 +1977,7 @@ void die(lifeform_t *lf) { } // add extra flags ? - getflags(lf->flags, F_CORPSEFLAG, F_NONE); + getflags(lf->flags, retflag, &nretflags, F_CORPSEFLAG, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if (f->id == F_CORPSEFLAG) { @@ -3352,6 +3381,8 @@ int flee(lifeform_t *lf) { int i; int db = B_FALSE; char lfname[BUFLEN]; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; if (lfhasflag(lf, F_DEBUG)) db = B_TRUE; @@ -3364,7 +3395,7 @@ int flee(lifeform_t *lf) { } // are we fleeing? - getflags(lf->flags, F_FLEEFROM, F_NONE); + getflags(lf->flags, retflag, &nretflags, F_FLEEFROM, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if (f->id == F_FLEEFROM) { @@ -3529,12 +3560,14 @@ int freezelf(lifeform_t *freezee, lifeform_t *freezer, int howlong) { } else { strcpy(buf, "being frozen"); } - losehp(freezee, rnd(10,20), DT_COLD, freezer, buf); + losehp(freezee, rnd(5,10), DT_COLD, freezer, buf); return B_TRUE; } - // turn to ice - addtempflag(freezee->flags, F_FROZEN, B_TRUE, NA, NA, NULL, howlong); + if (!lfhasflag(freezee, F_FROZEN)) { + // turn to ice + addtempflag(freezee->flags, F_FROZEN, B_TRUE, NA, NA, NULL, howlong); + } return B_FALSE; } @@ -3706,6 +3739,8 @@ int getactspeed(lifeform_t *lf) { int speed = 0; flag_t *f; int i; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; f = lfhasflag(lf, F_ACTIONSPEED); if (f) { @@ -3715,7 +3750,7 @@ int getactspeed(lifeform_t *lf) { } // modifier? - getflags(lf->flags, F_SLOWACT, F_SLOWACTMOVE, F_FASTACT, F_FASTACTMOVE, F_NONE); + getflags(lf->flags, retflag, &nretflags, F_SLOWACT, F_SLOWACTMOVE, F_FASTACT, F_FASTACTMOVE, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if ((f->id == F_SLOWACT) || (f->id == F_SLOWACTMOVE)) { @@ -3869,12 +3904,14 @@ int getarmourrating(lifeform_t *lf, object_t **hitob, int *hitchance, int *narms object_t *o; flag_t *f; int ar = 0, i; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; if (narms) { (*narms) = 0; } - getflags(lf->flags, F_ARMOURRATING, F_MAGICARMOUR, F_PHALANX, F_NONE); + getflags(lf->flags, retflag, &nretflags, F_ARMOURRATING, F_MAGICARMOUR, F_PHALANX, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if (f->id == F_ARMOURRATING) { @@ -4009,6 +4046,8 @@ int getattr(lifeform_t *lf, enum ATTRIB attr) { int real_getattr(lifeform_t *lf, enum ATTRIB attr, int ignoreattrset) { int val = 0, i; flag_t *f; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; // override? if (!ignoreattrset) { @@ -4021,7 +4060,7 @@ int real_getattr(lifeform_t *lf, enum ATTRIB attr, int ignoreattrset) { // base attribute val = lf->att[attr]; // modified? - getflags(lf->flags, F_ATTRMOD, F_DRUNK, F_NONE); + getflags(lf->flags, retflag, &nretflags, F_ATTRMOD, F_DRUNK, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if ((f->id == F_ATTRMOD) && (f->val[0] == attr)) { @@ -4051,13 +4090,15 @@ int getavgdam(lifeform_t *lf, int forxp) { int avgdam = 0,i; int db = B_FALSE; flag_t *f; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; if (lfhasflag(lf, F_DEBUG)) { db = B_TRUE; } op = addobpile(NULL, NULL, NULL); - getflags(lf->race->flags, F_HASATTACK, F_STARTOB, F_NONE); + getflags(lf->race->flags, retflag, &nretflags, F_HASATTACK, F_STARTOB, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if (f->id == F_HASATTACK) { @@ -4214,6 +4255,8 @@ float getequippedweight(lifeform_t *lf) { int getevasion(lifeform_t *lf) { flag_t *f; int ev = 0,i; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; // no evasion if you can't move! if (isimmobile(lf)) { @@ -4253,7 +4296,7 @@ int getevasion(lifeform_t *lf) { */ // adjust for bulky armour/shield - getflags(lf->flags, F_ARMOURPENALTY, F_SHIELDPENALTY, F_NONE); + getflags(lf->flags, retflag, &nretflags, F_ARMOURPENALTY, F_SHIELDPENALTY, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if (f->id == F_ARMOURPENALTY) { @@ -4338,12 +4381,14 @@ object_t *getbestweapon(lifeform_t *lf) { //int bestmaxdam = -999; object_t *o; obpile_t *op = NULL; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; bestwep = getweapon(lf); if (!bestwep) { int i; // get best innate attack - getflags(lf->flags, F_HASATTACK, F_NONE); + getflags(lf->flags, retflag, &nretflags, F_HASATTACK, F_NONE); for (i = 0; i < nretflags; i++) { objecttype_t *ot; @@ -4487,7 +4532,6 @@ object_t *getequippedob(obpile_t *op, enum BODYPART bp) { int getexposedlimbs(lifeform_t *lf) { int exposedlimbs = 0; if (!getouterequippedob(lf, BP_HEAD)) exposedlimbs += 1; - if (!getouterequippedob(lf, BP_SHOULDERS)) exposedlimbs += 1; if (!getouterequippedob(lf, BP_BODY)) exposedlimbs += 2; if (!getouterequippedob(lf, BP_HANDS)) exposedlimbs += 1; if (!getouterequippedob(lf, BP_LEGS)) exposedlimbs += 2; @@ -4716,6 +4760,8 @@ int getlfaccuracy(lifeform_t *lf, object_t *wep) { flag_t *f; object_t *o; int acc = 0,i; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; // get weapon if (wep) { @@ -4741,14 +4787,18 @@ int getlfaccuracy(lifeform_t *lf, object_t *wep) { } } - // adjust for bulky armour/shield - getflags(lf->flags, F_ARMOURPENALTY, F_SHIELDPENALTY, F_NONE); + // adjust for bulky armour/shield, or injuries + getflags(lf->flags, retflag, &nretflags, F_ARMOURPENALTY, F_INJURY, F_SHIELDPENALTY, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if (f->id == F_SHIELDPENALTY) { acc -= adjustshieldpenalty(lf, f->val[0]); } else if (f->id == F_ARMOURPENALTY) { acc -= adjustarmourpenalty(lf, f->val[0]); + } else if (f->id == F_INJURY) { + if (f->val[0] == BP_HANDS) { + acc -= 25; + } } } @@ -4882,8 +4932,10 @@ int getminions(lifeform_t *lf, lifeform_t **minion, int *nminions) { lifeform_t *min; *nminions = 0; int i; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; - getflags(lf->flags, F_MINION, F_NONE); + getflags(lf->flags, retflag, &nretflags, F_MINION, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if (f->id == F_MINION) { @@ -4900,6 +4952,8 @@ int getminions(lifeform_t *lf, lifeform_t **minion, int *nminions) { int getnightvisrange(lifeform_t *lf) { int range = 1,i; // default flag_t *f; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; f = lfhasflag(lf, F_SEEINDARK); if (f && !isblind(lf)) { @@ -4915,7 +4969,7 @@ int getnightvisrange(lifeform_t *lf) { } } // modifications? - getflags(lf->flags, F_NIGHTVISRANGEMOD, F_NONE); + getflags(lf->flags, retflag, &nretflags, F_NIGHTVISRANGEMOD, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if (f->id == F_NIGHTVISRANGEMOD) { @@ -5150,6 +5204,8 @@ int getmaxmp(lifeform_t *lf) { int activemp = 0; int maxmp,i; int extrapct = 0; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; // base maxmp = lf->maxmp; @@ -5160,7 +5216,7 @@ int getmaxmp(lifeform_t *lf) { // losses activemp = 0; - getflags(lf->flags, F_BOOSTSPELL, F_NONE); + getflags(lf->flags, retflag, &nretflags, F_BOOSTSPELL, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if (f->id == F_BOOSTSPELL) { @@ -5191,6 +5247,8 @@ int getmr(lifeform_t *lf) { int getvisrange(lifeform_t *lf) { int range,i; flag_t *f; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; if (isblind(lf)) { return 0; @@ -5223,7 +5281,7 @@ int getvisrange(lifeform_t *lf) { } // modifications? - getflags(lf->flags, F_VISRANGEMOD, F_NONE); + getflags(lf->flags, retflag, &nretflags, F_VISRANGEMOD, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if (f->id == F_VISRANGEMOD) { @@ -5239,6 +5297,8 @@ int getmovespeed(lifeform_t *lf) { int speed = 0,i; flag_t *f; object_t *o; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; f = lfhasflag(lf, F_MOVESPEED); if (f) { @@ -5248,13 +5308,18 @@ int getmovespeed(lifeform_t *lf) { } // modifier? - getflags(lf->flags, F_FASTMOVE, F_FASTACTMOVE, F_SLOWMOVE, F_SLOWACTMOVE, F_SPRINTING, F_TIRED, F_NONE); + getflags(lf->flags, retflag, &nretflags, F_FASTMOVE, F_FASTACTMOVE, F_INJURY, F_SLOWMOVE, + F_SLOWACTMOVE, F_SPRINTING, F_TIRED, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if ((f->id == F_SLOWMOVE) || (f->id == F_SLOWACTMOVE)) { speed += f->val[0]; } else if ((f->id == F_FASTMOVE) || (f->id == F_FASTACTMOVE)) { speed -= f->val[0]; + } else if (f->id == F_INJURY) { + if (f->val[0] == BP_LEGS) { + speed += 5; + } } else if (f->id == F_SPRINTING) { if (f->val[0]) { speed -= 10; @@ -5703,25 +5768,6 @@ object_t *getrandomarmour(lifeform_t *lf) { // make a list of all valid armour getarmourrating(lf, poss, hitchance, &nposs); if (!nposs) return NULL; - /* - for (o = lf->pack->first ; o ; o = o->next) { - if (hasflag(o->flags, F_ARMOURRATING)) { - f = hasflag(o->flags, F_EQUIPPED); - if (f) { - anyfound = B_TRUE; - poss[nposs] = o; - if (hasflag(o->flags, F_SHIELD)) { - hitchance[nposs] = getbodyparthitchance(BP_BODY); - } else { - hitchance[nposs] = getbodyparthitchance(f->val[0]); - } - maxroll += hitchance[nposs]; - nposs++; - } - } - } - */ - maxroll = 0; for (i = 0; i < nposs; i++) { @@ -5745,6 +5791,36 @@ object_t *getrandomarmour(lifeform_t *lf) { return o; } +// pick a random major body part +// ie. head, body, arms/hands, legs +enum BODYPART getrandomcorebp(lifeform_t *lf) { + int cutoff[4],nparts = 0,i,max = 0,num; + enum BODYPART bp[4],selbp = BP_NONE; + if (hasbp(lf, BP_BODY)) bp[nparts++] = BP_BODY; + if (hasbp(lf, BP_HANDS)) bp[nparts++] = BP_HANDS; + if (hasbp(lf, BP_LEGS)) bp[nparts++] = BP_LEGS; + if (hasbp(lf, BP_HEAD)) bp[nparts++] = BP_HEAD; + for (i = 0;i < nparts; i++) { + int n; + cutoff[i] = getbodyparthitchance(bp[i]); + for (n = 0; n < i; n++) { + cutoff[i] += cutoff[n]; + } + max += cutoff[i]; + } + num = rnd(1,max); + for (i = 0;i < nparts; i++) { + if (num <= cutoff[i]) { + selbp = bp[i]; + break; + } + } + if (selbp == BP_NONE) { + dblog("error in getrandomcorebodypart!"); + } + return selbp; +} + job_t *getrandomjob(int onlyplayerjobs) { job_t *j; int njobs = 0; @@ -6486,8 +6562,8 @@ void givejob(lifeform_t *lf, enum JOB jobid) { killflagsofid(lf->flags, F_HATESRACE); // mark its home shop if (isroom(lf->cell)) { - addflag(lf->flags, F_OWNSSHOP, lf->cell->roomid, NA, NA, NULL); - addflag(lf->flags, F_STAYINROOM, lf->cell->roomid, NA, NA, NULL); + addflag(lf->flags, F_OWNSSHOP, getroomid(lf->cell), NA, NA, NULL); + addflag(lf->flags, F_STAYINROOM, getroomid(lf->cell), NA, NA, NULL); } } } @@ -7029,8 +7105,10 @@ void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp) { void givestartskills(lifeform_t *lf, flagpile_t *fp) { flag_t *f; int i; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; - getflags(fp, F_STARTSKILL, F_NONE); + getflags(fp, retflag, &nretflags, F_STARTSKILL, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; @@ -7074,7 +7152,31 @@ job_t *hasjob(lifeform_t *lf, enum JOB job) { return j; } +int injure(lifeform_t *lf, enum BODYPART where, enum DAMTYPE damtype) { + char lfname[BUFLEN]; + if (where == BP_NONE) return B_TRUE; + if (!hasbp(lf, where)) return B_TRUE; + if (lfhasflagval(lf, F_INJURY, where, damtype, NA, NULL)) return B_TRUE; + // special cases for head... + if (where == BP_HEAD) { + if (damtype == DT_SLASH) { + if (isplayer(lf)) { + msg("^BYour brain is ruptured!"); + } else if (cansee(player, lf)) { + getlfname(lf, lfname); + msg("^%c%s%s brain ruptures!", getlfcol(lf, CC_VBAD), lfname, getpossessive(lfname)); + } + if (lf->hp > 0) lf->hp = 0; + return B_FALSE; + } + } + + addtempflag(lf->flags, F_INJURY, where, damtype, NA, NULL,rnd(5,30)); + + + return B_FALSE; +} int lfcanbestoned(lifeform_t *lf) { switch (getlfmaterial(lf)) { @@ -7592,172 +7694,6 @@ int getviscell(lifeform_t *lf, cell_t *cell) { return lf->viscell[idx]; } -// find los, remembering cells on the way -void calclos(lifeform_t *viewer, cell_t *dest) { - int numpixels; - int i,n; - int x1,y1; - int maxvisrange; - int nightvisrange; - int xray = 0; - flag_t *f; - int x2,y2; - map_t *map; - object_t *o; - int currange; - cell_t *retcell[MAXRETCELLS]; - int allbad = B_FALSE; - - if (!viewer) return ; - if (!dest) return ; - if (!viewer->cell) return ; - if (viewer->cell->map != dest->map) return ; - - map = dest->map; - - x1 = viewer->cell->x; - y1 = viewer->cell->y; - x2 = dest->x; - y2 = dest->y; - - // find the path of cells - calcbresnham(map, x1, y1, x2, y2, retcell, &numpixels); - - // can't see if you're blind - if (isblind(viewer)) { - allbad = 1; - } - - maxvisrange = getvisrange(viewer); - nightvisrange = getnightvisrange(viewer); - - //origheight = getheight(x1,y1,z); - - if (allbad) { - // mark all as bad - for (i = 0; i < numpixels; i++ ){ - setviscell(viewer, retcell[i], B_VIS); - } - return; - } - - - f = hasflag(viewer->flags, F_XRAYVIS); - if (f) { - xray = f->val[0]; - } else { - xray = 0; - } - - //shopwall = B_FALSE; - currange = 0; - - for (i = 0; i < numpixels ; i++) { - cell_t *cell; - int cellopaque = B_FALSE; - int celldark = B_FALSE; - - cell = retcell[i]; - - //already can't see this one? - if (getviscell(viewer, cell) == B_NOVIS) { - break; - } - - if ((cell->x == x2) && (cell->y == y2)) { - // made it to the last cell - setviscell(viewer, cell, B_VIS); - return; - } - - if (i == 0) { - // you can always see your own cell - setviscell(viewer, cell, B_VIS); - continue; - } - - - currange++; - if (currange > maxvisrange) { - break; - } - - // check cell type - if (!cell->type->transparent) { - cellopaque = -1; // fullblock - } - - // now check lighting - if (!cellopaque) { - // outside the range of our light, and not lit - if (getcelldist(viewer->cell, cell) > nightvisrange) { - if (!islit(cell)) { - celldark = B_TRUE; - } - } else { - // inside our nightvis range and magically dark - if (cell->lit == L_PERMDARK) { - celldark = B_TRUE; - } - } - } - - // check for objects which block view - if (!cellopaque && !celldark) { - for (o = cell->obpile->first ; o ; o = o->next) { - f = hasflag(o->flags, F_BLOCKSVIEW); - if (f) { - if (!lfhasflagval(viewer, F_CANSEETHROUGHMAT, o->material->id, NA, NA, NULL)) { - if (f->val[0] == B_TRUE) { - cellopaque = -1; // fullblock - break; - } else { - cellopaque += f->val[0]; - } - } - } - } - } - - if (cellopaque) { - if (xray) { - xray--; - } else { - if (cellopaque == -1) { - // can see this one but not the rest. - setviscell(viewer, cell, B_VIS); - i++; - break; - } else { - currange += cellopaque; - if (currange > maxvisrange) { - // can see this one but not the rest. - setviscell(viewer, cell, B_VIS); - i++; - break; - } - } - } - } - - // xray vision decreases by one - if (xray) xray--; - - // this cell is visible (unless it's dark) - if (celldark) { - setviscell(viewer, cell, B_NOVIS); - } else { - setviscell(viewer, cell, B_VIS); - } - } - - - // rest of cells are not visible. - for (n = i; n < numpixels; n++) { - setviscell(viewer, retcell[n], B_NOVIS); - } -} - int haslos(lifeform_t *viewer, cell_t *dest) { int numpixels; int i; @@ -7776,24 +7712,18 @@ int haslos(lifeform_t *viewer, cell_t *dest) { if (!viewer) return B_FALSE; if (!dest) return B_FALSE; if (!viewer->cell) return B_FALSE; + if (viewer->cell->map != dest->map) return B_FALSE; - // let the player see when dead, otherwise the screen wil - // go black when "You die" appears. + // can't see when you're dead UNLESS you are the player. this is + // to prevent the screen from going black when "You die" appears. if (isdead(viewer) && !isplayer(viewer)) return B_FALSE; - if (viewer->cell->map != dest->map) return B_FALSE; // can we use pre-calced los? // - //if ((viewer->cell->map->lf == viewer) && viewer->los) { if (viewer->los) { - for (i = 0;i < viewer->nlos; i++) { - if (viewer->los[i] == dest) { - return B_TRUE; - } - } - return B_FALSE; + return haslos_fast(viewer, dest); } map = dest->map; @@ -7803,7 +7733,6 @@ int haslos(lifeform_t *viewer, cell_t *dest) { x2 = dest->x; y2 = dest->y; - f = hasflag(viewer->flags, F_XRAYVIS); if (f) { xray = f->val[0]; @@ -7816,14 +7745,13 @@ int haslos(lifeform_t *viewer, cell_t *dest) { return B_FALSE; } - calcbresnham(map, x1, y1, x2, y2, retcell, &numpixels); - maxvisrange = getvisrange(viewer); if (!celllitfor(viewer, dest, maxvisrange, getnightvisrange(viewer))) { return B_FALSE; } + calcbresnham(map, x1, y1, x2, y2, retcell, &numpixels); currange = 0; @@ -7836,8 +7764,7 @@ int haslos(lifeform_t *viewer, cell_t *dest) { break; } - // you can always see your own cell - if (i != 0) { + if (i != 0) { // ie. if not blind, you can always see your own cell int rangemod; currange++; @@ -7872,13 +7799,23 @@ int haslos(lifeform_t *viewer, cell_t *dest) { return B_TRUE; } +int haslos_fast(lifeform_t *viewer, cell_t *dest) { + int i; + for (i = 0; i < viewer->nlos; i++) { + if (viewer->los[i] == dest) { + return B_TRUE; + } + } + return B_FALSE; +} + void initjobs(void) { int i; flag_t *f; // job definitions - // NOTE: try to always make the job's weapon be the first object defined. + // NOTE: try to always make the job's primary weapon be the first object defined. // this will make sure that they have the letter 'a'. addjob(J_GOD, "Diety"); //addflag(lastjob->flags, F_OMNIPOTENT, B_TRUE, NA, NA, NULL); @@ -7898,6 +7835,7 @@ void initjobs(void) { addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "10 blessed scrolls of create monster"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "10 blessed potions of experience"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "ring of miracles"); + addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "ring of control"); addflag(lastjob->flags, F_STARTSKILL, SK_SPELLCASTING, PR_MASTER, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_LORE_ARCANA, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_SS_DEATH, PR_MASTER, NA, NULL); @@ -8405,6 +8343,7 @@ void initjobs(void) { } void initrace(void) { + race_t *r; flag_t *f; objecttype_t *ot; // race classes @@ -8573,7 +8512,7 @@ void initrace(void) { addflag(lastrace->flags, F_WANTSBETTERARM, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_WANTS, OT_GOLD, NA, NA, NULL); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addflag(lastrace->flags, F_HIRABLE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_ISPRISONER, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HIREPRICE, 0, NA, NA, NULL); addrace(R_TOWNGUARD, "town guard", 100, '@', C_GREY, MT_FLESH, RC_HUMANOID); @@ -9338,7 +9277,7 @@ void initrace(void) { 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); - addflag(lastrace->flags, F_HITDICE, 1, NA, NA, NULL); + addflag(lastrace->flags, F_HITDICE, 2, NA, NA, NULL); addflag(lastrace->flags, F_EVASION, 5, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); @@ -9364,7 +9303,7 @@ void initrace(void) { 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, 78, NA, NULL); - addflag(lastrace->flags, F_HITDICE, 1, NA, NA, NULL); + addflag(lastrace->flags, F_HITDICE, 2, 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); @@ -9777,7 +9716,7 @@ void initrace(void) { addflag(lastrace->flags, F_STARTATT, A_STR, AT_LOW, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, AT_AVERAGE, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); - addflag(lastrace->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, 70, RR_UNCOMMON, NULL); addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL); addflag(lastrace->flags, F_HITDICE, 1, NA, NA, NULL); addflag(lastrace->flags, F_EVASION, 15, NA, NA, NULL); @@ -9797,6 +9736,31 @@ void initrace(void) { addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); + addrace(R_SPRITEICE, "ice sprite", 5, 'n', C_WHITE, MT_ICE, RC_MAGIC); + addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "sheet of ice"); + addflag(lastrace->flags, F_STARTATT, A_STR, AT_LOW, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_IQ, AT_AVERAGE, NA, NULL); + addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, 70, RR_UNCOMMON, NULL); + addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL); + addflag(lastrace->flags, F_HITDICE, 1, NA, NA, NULL); + addflag(lastrace->flags, F_EVASION, 15, NA, NA, NULL); + addflag(lastrace->flags, F_FLYING, B_TRUE, NA, NA, ""); + addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); + addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); + addflag(lastrace->flags, F_MPDICE, 4, 2, NA, NULL); + addflag(lastrace->flags, F_MPREGEN, 1, NA, NA, NULL); + addflag(lastrace->flags, F_CANCAST, OT_S_FROSTBITE, NA, NA, NULL); + addflag(lastrace->flags, F_CANCAST, OT_S_FREEZEOB, NA, NA, NULL); + addflag(lastrace->flags, F_CANCAST, OT_S_ICICLE, NA, NA, NULL); + addflag(lastrace->flags, F_SPELLCASTTEXT, NA, NA, NA, "gestures"); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d3"); + addflag(lastrace->flags, F_DTIMMUNE, DT_COLD, NA, NA, NULL); + addflag(lastrace->flags, F_HASSKILL, SK_SPELLCASTING, PR_NOVICE, NA, NULL); + addflag(lastrace->flags, F_HASSKILL, SK_SS_COLD, PR_ADEPT, 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, RC_HUMANOID); addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL); @@ -11126,6 +11090,57 @@ void initrace(void) { 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); + + // now do final steps in race initialisation: + // - add flags based on raceclass, etc + // - fill in missing alignments + for (r = firstrace ; r ; r = r->next) { + if (r->raceclass->id == RC_AQUATIC) { + addflag(r->flags, F_HASSKILL, SK_SWIMMING, PR_MASTER, NA, NULL); + addflag(r->flags, F_AQUATIC, B_TRUE, NA, NA, NULL); + addflag(r->flags, F_BREATHWATER, B_TRUE, NA, NA, NULL); + addflag(r->flags, F_DTIMMUNE, DT_WATER, NA, NA, NULL); + } else if (r->raceclass->id == RC_DEMON) { + addflag(r->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL); + } else if (r->raceclass->id == RC_GOD) { + addflag(r->flags, F_PIETY, 100, NA, NA, NULL); + addflag(r->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); + addflag(r->flags, F_MORALE, 10, NA, NA, NULL); + addflag(r->flags, F_BREATHWATER, B_TRUE, NA, NA, NULL); + addflag(r->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL); + addflag(r->flags, F_DTIMMUNE, DT_NECROTIC, NA, NA, NULL); + addflag(r->flags, F_DTIMMUNE, DT_POISON, NA, NA, NULL); + addflag(r->flags, F_DTIMMUNE, DT_POISONGAS, NA, NA, NULL); + addflag(r->flags, F_FLEEONHPPCT, 20, NA, NA, NULL); + addflag(r->flags, F_RESISTMAG, 15, NA, NA, NULL); + addflag(r->flags, F_MORALE, 40, NA, NA, NULL); + } else if (r->raceclass->id == RC_MAGIC) { + addflag(r->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL); + } else if (r->raceclass->id == RC_PLANT) { + addflag(r->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL); + addflag(r->flags, F_DTRESIST, DT_BASH, NA, NA, NULL); + addflag(r->flags, F_DTVULN, DT_FIRE, NA, NA, NULL); + addflag(r->flags, F_DTVULN, DT_COLD, NA, NA, NULL); + addflag(r->flags, F_DTVULN, DT_DECAY, NA, NA, NULL); + addflag(r->flags, F_FLAMMABLE, PERMENANT, NA, NA, NULL); + } else if (r->raceclass->id == RC_SLIME) { + addflag(lastrace->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL); + } else if (r->raceclass->id == RC_UNDEAD) { + addflag(r->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL); + addflag(r->flags, F_DTIMMUNE, DT_COLD, NA, NA, NULL); + addflag(r->flags, F_DTIMMUNE, DT_POISON, NA, NA, NULL); + addflag(r->flags, F_DTIMMUNE, DT_POISONGAS, NA, NA, NULL); + addflag(r->flags, F_DTIMMUNE, DT_DECAY, NA, NA, NULL); + addflag(r->flags, F_DTIMMUNE, DT_NECROTIC, NA, NA, NULL); + addflag(r->flags, F_DTVULN, DT_HOLY, NA, NA, NULL); + addflag(r->flags, F_SEEINDARK, B_TRUE, NA, NA, NULL); + } + + // fill in missins alignments + if (!hasflag(r->flags, F_ALIGNMENT)) { + addflag(r->flags, F_ALIGNMENT, AL_NEUTRAL, NA, NA, NULL); + } + } } int isairborne(lifeform_t *lf) { @@ -11152,6 +11167,10 @@ int isbleeding(lifeform_t *lf) { hppct = ((float)lf->hp / (float) lf->maxhp) * 100; if (hppct <= 40) return B_TRUE; + + if (lfhasflagval(lf, F_INJURY, NA, DT_SLASH, NA, NULL)) { + return B_TRUE; + } return B_FALSE; } @@ -11408,6 +11427,9 @@ int ishirable(lifeform_t *lf) { if (lfhasflag(lf, F_HIRABLE)) { return B_TRUE; } + if (lfhasflag(lf, F_ISPRISONER)) { + return B_TRUE; + } } return B_FALSE; } @@ -11489,8 +11511,10 @@ int isplayer(lifeform_t *lf) { flag_t *ispoisoned(lifeform_t *lf) { flag_t *f,*max = NULL; int i; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; - getflags(lf->flags, F_POISONED, F_NONE); + getflags(lf->flags, retflag, &nretflags, F_POISONED, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if (f->lifetime == PERMENANT) { @@ -12462,10 +12486,12 @@ void killrace(race_t *race) { flag_t *levelabilityready(lifeform_t *lf) { flag_t *f; int i; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; if (!lfhasflag(lf, F_HASNEWLEVEL)) return NULL; - getflags(lf->flags, F_LEVABIL, F_LEVFLAG, F_LEVSPELL, F_LEVSPELLSCHOOL, F_LEVSKILL, F_NONE); + getflags(lf->flags, retflag, &nretflags, F_LEVABIL, F_LEVFLAG, F_LEVSPELL, F_LEVSPELLSCHOOL, F_LEVSKILL, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; // we'll set lifetime to -1 while actually assigning these. @@ -12625,6 +12651,8 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml char lfname[BUFLEN]; int prebleed = B_FALSE,postbleed = B_FALSE; flag_t *f; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; getlfname(lf, lfname); @@ -12641,7 +12669,7 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml if (isphysicaldam(damtype)) { int i; - getflags(lf->flags, F_MAGICARMOUR, F_NONE); + getflags(lf->flags, retflag, &nretflags, F_MAGICARMOUR, F_NONE); for (i = 0; i < nretflags; i++) { int damtaken; @@ -12718,6 +12746,7 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml } else { // effects based on damage type if (damtype == DT_COLD) { + int i; if (lfhasflag(lf, F_COLDBLOOD)) { // slow them addtempflag(lf->flags, F_SLOWMOVE, 5, NA, NA, NULL, 10); @@ -12726,6 +12755,26 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml if (!skillcheck(lf, SC_CON, (amt/2) + getexposedlimbs(lf), 0)) { poison(lf, 20+(amt*3), P_COLD, 0, "the cold"); } + // cold will heal bruised limbs + getflags(lf->flags, retflag, &nretflags, F_INJURY, F_NONE); + for (i = 0; i < nretflags; i++) { + f = retflag[i]; + if ((f->val[1] == DT_BASH) && (f->lifetime > 0)) { + f->lifetime -= 5; + limit(&f->lifetime, 1, NA); + } + } + } else if (damtype == DT_FIRE) { + int i; + // fire will cauterise slash wounds + getflags(lf->flags, retflag, &nretflags, F_INJURY, F_NONE); + for (i = 0; i < nretflags; i++) { + f = retflag[i]; + if ((f->val[1] == DT_SLASH) && (f->lifetime > 0)) { + f->lifetime -= 20; + limit(&f->lifetime, 1, NA); + } + } } else if (damtype == DT_POISONGAS) { if (amt > 0) { if (!skillcheck(lf, SC_POISON, 25, 0)) { @@ -12764,8 +12813,6 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml spellcloud(lf->cell, 3, '\0', C_MAGENTA, OT_S_SLEEP, 8, B_TRUE); } - - // further effects if not dead... if (!isdead(lf)) { // fight back if required @@ -13587,6 +13634,8 @@ void poison(lifeform_t *lf, int howlong, enum POISONTYPE ptype, int power, char flag_t *f; int found = B_FALSE,i; enum POISONSEVERITY psev; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; // are you immune to disease? psev = getpoisonseverity(ptype); @@ -13601,7 +13650,7 @@ void poison(lifeform_t *lf, int howlong, enum POISONTYPE ptype, int power, char } - getflags(lf->flags, F_POISONED, F_NONE); + getflags(lf->flags, retflag, &nretflags, F_POISONED, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; @@ -14065,7 +14114,9 @@ int recruit(lifeform_t *lf) { void refreshlevelabilities(lifeform_t *lf) { flag_t *f; int i; - getflags(lf->flags, F_LEVABIL, F_LEVFLAG, F_LEVSPELL, F_LEVSPELLSCHOOL, F_LEVSKILL, F_NONE); + flag_t *retflag[MAXCANDIDATES]; + int nretflags; + getflags(lf->flags, retflag, &nretflags, F_LEVABIL, F_LEVFLAG, F_LEVSPELL, F_LEVSPELLSCHOOL, F_LEVSKILL, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; // we'll set timeleft to -1 while actually assigning these. @@ -14554,6 +14605,8 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) { int nkilled = 0; race_t *newrace; char buf[BUFLEN]; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; newrace = findrace(rid); @@ -14645,7 +14698,7 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) { killflagsofid(lf->flags, F_RARITY); // certain other flags are rnadom - getflags(lf->flags, F_RNDHOSTILE, F_NONE); + getflags(lf->flags, retflag, &nretflags, F_RNDHOSTILE, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if (f->id == F_RNDHOSTILE) { @@ -14955,112 +15008,111 @@ void initskills(void) { addskilldesc(SK_UNARMED, PR_SKILLED, "^gYou can now make melee attacks with your off-hand.", B_TRUE); // spell schools addskill(SK_SS_ALLOMANCY, "Allomancy", "Boosts casting of spells from this school.", 50); - addskilldesc(SK_SS_ALLOMANCY, PR_NOVICE, "You gain knowledge of all Allomancy spells.", B_FALSE); addskilldesc(SK_SS_ALLOMANCY, PR_NOVICE, "Allows you to cast Allomancy spells up to level 1.", B_FALSE); addskilldesc(SK_SS_ALLOMANCY, PR_BEGINNER, "Allows you to cast Allomancy spells up to level 2.", B_FALSE); - addskilldesc(SK_SS_ALLOMANCY, PR_ADEPT, "Allows you to cast Allomancy spells up to level 4.", B_FALSE); - addskilldesc(SK_SS_ALLOMANCY, PR_SKILLED, "Allows you to cast Allomancy spells up to level 6.", B_FALSE); - addskilldesc(SK_SS_ALLOMANCY, PR_EXPERT, "Allows you to cast Allomancy spells up to level 8.", B_FALSE); - addskilldesc(SK_SS_ALLOMANCY, PR_MASTER, "Allows you to cast Allomancy spells up to level 9.", B_FALSE); + addskilldesc(SK_SS_ALLOMANCY, PR_ADEPT, "Allows you to cast Allomancy spells up to level 3.", B_FALSE); + addskilldesc(SK_SS_ALLOMANCY, PR_SKILLED, "Allows you to cast Allomancy spells up to level 4.", B_FALSE); + addskilldesc(SK_SS_ALLOMANCY, PR_EXPERT, "Allows you to cast Allomancy spells up to level 5.", B_FALSE); + addskilldesc(SK_SS_ALLOMANCY, PR_MASTER, "Allows you to cast Allomancy spells up to level 6.", B_FALSE); addskill(SK_SS_AIR, "Air Magic", "Boosts casting of spells from this school.", 50); addskilldesc(SK_SS_AIR, PR_NOVICE, "Allows you to cast Air Magic spells up to level 1.", B_FALSE); addskilldesc(SK_SS_AIR, PR_BEGINNER, "Allows you to cast Air Magic spells up to level 2.", B_FALSE); - addskilldesc(SK_SS_AIR, PR_ADEPT, "Allows you to cast Air Magic spells up to level 4.", B_FALSE); - addskilldesc(SK_SS_AIR, PR_SKILLED, "Allows you to cast Air Magic spells up to level 6.", B_FALSE); - addskilldesc(SK_SS_AIR, PR_EXPERT, "Allows you to cast Air Magic spells up to level 8.", B_FALSE); - addskilldesc(SK_SS_AIR, PR_MASTER, "Allows you to cast Air Magic spells up to level 9.", B_FALSE); + addskilldesc(SK_SS_AIR, PR_ADEPT, "Allows you to cast Air Magic spells up to level 3.", B_FALSE); + addskilldesc(SK_SS_AIR, PR_SKILLED, "Allows you to cast Air Magic spells up to level 4.", B_FALSE); + addskilldesc(SK_SS_AIR, PR_EXPERT, "Allows you to cast Air Magic spells up to level 5.", B_FALSE); + addskilldesc(SK_SS_AIR, PR_MASTER, "Allows you to cast Air Magic spells up to level 6.", B_FALSE); addskill(SK_SS_DEATH, "Necromancy", "Boosts casting of spells from this school.", 50); addskilldesc(SK_SS_DEATH, PR_NOVICE, "Allows you to cast Necromancy spells up to level 1.", B_FALSE); addskilldesc(SK_SS_DEATH, PR_BEGINNER, "Allows you to cast Necromancy spells up to level 2.", B_FALSE); - addskilldesc(SK_SS_DEATH, PR_ADEPT, "Allows you to cast Necromancy spells up to level 4.", B_FALSE); - addskilldesc(SK_SS_DEATH, PR_SKILLED, "Allows you to cast Necromancy spells up to level 6.", B_FALSE); - addskilldesc(SK_SS_DEATH, PR_EXPERT, "Allows you to cast Necromancy spells up to level 8.", B_FALSE); - addskilldesc(SK_SS_DEATH, PR_MASTER, "Allows you to cast Necromancy spells up to level 9.", B_FALSE); + addskilldesc(SK_SS_DEATH, PR_ADEPT, "Allows you to cast Necromancy spells up to level 3.", B_FALSE); + addskilldesc(SK_SS_DEATH, PR_SKILLED, "Allows you to cast Necromancy spells up to level 4.", B_FALSE); + addskilldesc(SK_SS_DEATH, PR_EXPERT, "Allows you to cast Necromancy spells up to level 5.", B_FALSE); + addskilldesc(SK_SS_DEATH, PR_MASTER, "Allows you to cast Necromancy spells up to level 6.", B_FALSE); addskill(SK_SS_DIVINATION, "Divination", "Boosts casting of spells from this school.", 50); addskilldesc(SK_SS_DIVINATION, PR_NOVICE, "Allows you to cast Divination spells up to level 1.", B_FALSE); addskilldesc(SK_SS_DIVINATION, PR_BEGINNER, "Allows you to cast Divination spells up to level 2.", B_FALSE); - addskilldesc(SK_SS_DIVINATION, PR_ADEPT, "Allows you to cast Divination spells up to level 4.", B_FALSE); - addskilldesc(SK_SS_DIVINATION, PR_SKILLED, "Allows you to cast Divination spells up to level 6.", B_FALSE); - addskilldesc(SK_SS_DIVINATION, PR_EXPERT, "Allows you to cast Divination spells up to level 8.", B_FALSE); - addskilldesc(SK_SS_DIVINATION, PR_MASTER, "Allows you to cast Divination spells up to level 9.", B_FALSE); + addskilldesc(SK_SS_DIVINATION, PR_ADEPT, "Allows you to cast Divination spells up to level 3.", B_FALSE); + addskilldesc(SK_SS_DIVINATION, PR_SKILLED, "Allows you to cast Divination spells up to level 4.", B_FALSE); + addskilldesc(SK_SS_DIVINATION, PR_EXPERT, "Allows you to cast Divination spells up to level 5.", B_FALSE); + addskilldesc(SK_SS_DIVINATION, PR_MASTER, "Allows you to cast Divination spells up to level 6.", B_FALSE); addskill(SK_SS_ENCHANTMENT, "Enchantment", "Boosts casting of spells from this school.", 50); addskilldesc(SK_SS_ENCHANTMENT, PR_NOVICE, "Allows you to cast Enchantment spells up to level 1.", B_FALSE); addskilldesc(SK_SS_ENCHANTMENT, PR_BEGINNER, "Allows you to cast Enchantment spells up to level 2.", B_FALSE); - addskilldesc(SK_SS_ENCHANTMENT, PR_ADEPT, "Allows you to cast Enchantment spells up to level 4.", B_FALSE); - addskilldesc(SK_SS_ENCHANTMENT, PR_SKILLED, "Allows you to cast Enchantment spells up to level 6.", B_FALSE); - addskilldesc(SK_SS_ENCHANTMENT, PR_EXPERT, "Allows you to cast Enchantment spells up to level 8.", B_FALSE); - addskilldesc(SK_SS_ENCHANTMENT, PR_MASTER, "Allows you to cast Enchantment spells up to level 9.", B_FALSE); + addskilldesc(SK_SS_ENCHANTMENT, PR_ADEPT, "Allows you to cast Enchantment spells up to level 3.", B_FALSE); + addskilldesc(SK_SS_ENCHANTMENT, PR_SKILLED, "Allows you to cast Enchantment spells up to level 4.", B_FALSE); + addskilldesc(SK_SS_ENCHANTMENT, PR_EXPERT, "Allows you to cast Enchantment spells up to level 5.", B_FALSE); + addskilldesc(SK_SS_ENCHANTMENT, PR_MASTER, "Allows you to cast Enchantment spells up to level 6.", B_FALSE); addskill(SK_SS_FIRE, "Fire Magic", "Boosts casting of spells from this school.", 50); addskilldesc(SK_SS_FIRE, PR_NOVICE, "Allows you to cast Fire Magic spells up to level 1.", B_FALSE); addskilldesc(SK_SS_FIRE, PR_BEGINNER, "Allows you to cast Fire Magic spells up to level 2.", B_FALSE); - addskilldesc(SK_SS_FIRE, PR_ADEPT, "Allows you to cast Fire Magic spells up to level 4.", B_FALSE); - addskilldesc(SK_SS_FIRE, PR_SKILLED, "Allows you to cast Fire Magic spells up to level 6.", B_FALSE); - addskilldesc(SK_SS_FIRE, PR_EXPERT, "Allows you to cast Fire Magic spells up to level 8.", B_FALSE); - addskilldesc(SK_SS_FIRE, PR_MASTER, "Allows you to cast Fire Magic spells up to level 9.", B_FALSE); + addskilldesc(SK_SS_FIRE, PR_ADEPT, "Allows you to cast Fire Magic spells up to level 3.", B_FALSE); + addskilldesc(SK_SS_FIRE, PR_SKILLED, "Allows you to cast Fire Magic spells up to level 4.", B_FALSE); + addskilldesc(SK_SS_FIRE, PR_EXPERT, "Allows you to cast Fire Magic spells up to level 5.", B_FALSE); + addskilldesc(SK_SS_FIRE, PR_MASTER, "Allows you to cast Fire Magic spells up to level 6.", B_FALSE); addskill(SK_SS_COLD, "Cold Magic", "Boosts casting of spells from this school.", 50); addskilldesc(SK_SS_COLD, PR_NOVICE, "Allows you to cast Cold Magic spells up to level 1.", B_FALSE); addskilldesc(SK_SS_COLD, PR_BEGINNER, "Allows you to cast Cold Magic spells up to level 2.", B_FALSE); - addskilldesc(SK_SS_COLD, PR_ADEPT, "Allows you to cast Cold Magic spells up to level 4.", B_FALSE); - addskilldesc(SK_SS_COLD, PR_SKILLED, "Allows you to cast Cold Magic spells up to level 6.", B_FALSE); - addskilldesc(SK_SS_COLD, PR_EXPERT, "Allows you to cast Cold Magic spells up to level 8.", B_FALSE); - addskilldesc(SK_SS_COLD, PR_MASTER, "Allows you to cast Cold Magic spells up to level 9.", B_FALSE); + addskilldesc(SK_SS_COLD, PR_ADEPT, "Allows you to cast Cold Magic spells up to level 3.", B_FALSE); + addskilldesc(SK_SS_COLD, PR_SKILLED, "Allows you to cast Cold Magic spells up to level 4.", B_FALSE); + addskilldesc(SK_SS_COLD, PR_EXPERT, "Allows you to cast Cold Magic spells up to level 5.", B_FALSE); + addskilldesc(SK_SS_COLD, PR_MASTER, "Allows you to cast Cold Magic spells up to level 6.", B_FALSE); addskill(SK_SS_GRAVITY, "Gravitation Magic", "Boosts casting of spells from this school.", 50); addskilldesc(SK_SS_GRAVITY, PR_NOVICE, "Allows you to cast Gravitation Magic spells up to level 1.", B_FALSE); addskilldesc(SK_SS_GRAVITY, PR_BEGINNER, "Allows you to cast Gravitation Magic spells up to level 2.", B_FALSE); - addskilldesc(SK_SS_GRAVITY, PR_ADEPT, "Allows you to cast Gravitation Magic spells up to level 4.", B_FALSE); - addskilldesc(SK_SS_GRAVITY, PR_SKILLED, "Allows you to cast Gravitation Magic spells up to level 6.", B_FALSE); - addskilldesc(SK_SS_GRAVITY, PR_EXPERT, "Allows you to cast Gravitation Magic spells up to level 8.", B_FALSE); - addskilldesc(SK_SS_GRAVITY, PR_MASTER, "Allows you to cast Gravitation Magic spells up to level 9.", B_FALSE); + addskilldesc(SK_SS_GRAVITY, PR_ADEPT, "Allows you to cast Gravitation Magic spells up to level 3.", B_FALSE); + addskilldesc(SK_SS_GRAVITY, PR_SKILLED, "Allows you to cast Gravitation Magic spells up to level 4.", B_FALSE); + addskilldesc(SK_SS_GRAVITY, PR_EXPERT, "Allows you to cast Gravitation Magic spells up to level 5.", B_FALSE); + addskilldesc(SK_SS_GRAVITY, PR_MASTER, "Allows you to cast Gravitation Magic spells up to level 6.", B_FALSE); addskill(SK_SS_LIFE, "Life Magic", "Boosts casting of spells from this school.", 50); addskilldesc(SK_SS_LIFE, PR_NOVICE, "Allows you to cast Life Magic spells up to level 1.", B_FALSE); addskilldesc(SK_SS_LIFE, PR_BEGINNER, "Allows you to cast Life Magic spells up to level 2.", B_FALSE); - addskilldesc(SK_SS_LIFE, PR_ADEPT, "Allows you to cast Life Magic spells up to level 4.", B_FALSE); - addskilldesc(SK_SS_LIFE, PR_SKILLED, "Allows you to cast Life Magic spells up to level 6.", B_FALSE); - addskilldesc(SK_SS_LIFE, PR_EXPERT, "Allows you to cast Life Magic spells up to level 8.", B_FALSE); - addskilldesc(SK_SS_LIFE, PR_MASTER, "Allows you to cast Life Magic spells up to level 9.", B_FALSE); + addskilldesc(SK_SS_LIFE, PR_ADEPT, "Allows you to cast Life Magic spells up to level 3.", B_FALSE); + addskilldesc(SK_SS_LIFE, PR_SKILLED, "Allows you to cast Life Magic spells up to level 4.", B_FALSE); + addskilldesc(SK_SS_LIFE, PR_EXPERT, "Allows you to cast Life Magic spells up to level 5.", B_FALSE); + addskilldesc(SK_SS_LIFE, PR_MASTER, "Allows you to cast Life Magic spells up to level 6.", B_FALSE); addskill(SK_SS_MODIFICATION, "Modification", "Boosts casting of spells from this school.", 50); addskilldesc(SK_SS_MODIFICATION, PR_NOVICE, "Allows you to cast Modification spells up to level 1.", B_FALSE); addskilldesc(SK_SS_MODIFICATION, PR_BEGINNER, "Allows you to cast Modification spells up to level 2.", B_FALSE); - addskilldesc(SK_SS_MODIFICATION, PR_ADEPT, "Allows you to cast Modification spells up to level 4.", B_FALSE); - addskilldesc(SK_SS_MODIFICATION, PR_SKILLED, "Allows you to cast Modification spells up to level 6.", B_FALSE); - addskilldesc(SK_SS_MODIFICATION, PR_EXPERT, "Allows you to cast Modification spells up to level 8.", B_FALSE); - addskilldesc(SK_SS_MODIFICATION, PR_MASTER, "Allows you to cast Modification spells up to level 9.", B_FALSE); + addskilldesc(SK_SS_MODIFICATION, PR_ADEPT, "Allows you to cast Modification spells up to level 3.", B_FALSE); + addskilldesc(SK_SS_MODIFICATION, PR_SKILLED, "Allows you to cast Modification spells up to level 4.", B_FALSE); + addskilldesc(SK_SS_MODIFICATION, PR_EXPERT, "Allows you to cast Modification spells up to level 5.", B_FALSE); + addskilldesc(SK_SS_MODIFICATION, PR_MASTER, "Allows you to cast Modification spells up to level 6.", B_FALSE); addskill(SK_SS_MENTAL, "Psionics", "Boosts casting of spells from this school.", 50); addskilldesc(SK_SS_MENTAL, PR_NOVICE, "Allows you to cast Psionic spells up to level 1.", B_FALSE); addskilldesc(SK_SS_MENTAL, PR_BEGINNER, "Allows you to cast Psionic spells up to level 2.", B_FALSE); - addskilldesc(SK_SS_MENTAL, PR_ADEPT, "Allows you to cast Psionic spells up to level 4.", B_FALSE); - addskilldesc(SK_SS_MENTAL, PR_SKILLED, "Allows you to cast Psionic spells up to level 6.", B_FALSE); - addskilldesc(SK_SS_MENTAL, PR_EXPERT, "Allows you to cast Psionic spells up to level 8.", B_FALSE); - addskilldesc(SK_SS_MENTAL, PR_MASTER, "Allows you to cast Psionic spells up to level 9.", B_FALSE); + addskilldesc(SK_SS_MENTAL, PR_ADEPT, "Allows you to cast Psionic spells up to level 3.", B_FALSE); + addskilldesc(SK_SS_MENTAL, PR_SKILLED, "Allows you to cast Psionic spells up to level 4.", B_FALSE); + addskilldesc(SK_SS_MENTAL, PR_EXPERT, "Allows you to cast Psionic spells up to level 5.", B_FALSE); + addskilldesc(SK_SS_MENTAL, PR_MASTER, "Allows you to cast Psionic spells up to level 6.", B_FALSE); addskill(SK_SS_NATURE, "Nature Magic", "Boosts casting of spells from this school.", 50); addskilldesc(SK_SS_NATURE, PR_NOVICE, "Allows you to cast Nature spells up to level 1.", B_FALSE); addskilldesc(SK_SS_NATURE, PR_BEGINNER, "Allows you to cast Nature spells up to level 2.", B_FALSE); - addskilldesc(SK_SS_NATURE, PR_ADEPT, "Allows you to cast Nature spells up to level 4.", B_FALSE); - addskilldesc(SK_SS_NATURE, PR_SKILLED, "Allows you to cast Nature spells up to level 6.", B_FALSE); - addskilldesc(SK_SS_NATURE, PR_EXPERT, "Allows you to cast Nature spells up to level 8.", B_FALSE); - addskilldesc(SK_SS_NATURE, PR_MASTER, "Allows you to cast Nature spells up to level 9.", B_FALSE); + addskilldesc(SK_SS_NATURE, PR_ADEPT, "Allows you to cast Nature spells up to level 3.", B_FALSE); + addskilldesc(SK_SS_NATURE, PR_SKILLED, "Allows you to cast Nature spells up to level 4.", B_FALSE); + addskilldesc(SK_SS_NATURE, PR_EXPERT, "Allows you to cast Nature spells up to level 5.", B_FALSE); + addskilldesc(SK_SS_NATURE, PR_MASTER, "Allows you to cast Nature spells up to level 6.", B_FALSE); addskill(SK_SS_SUMMONING, "Summoning", "Boosts casting of spells from this school.", 50); addskilldesc(SK_SS_SUMMONING, PR_NOVICE, "Allows you to cast Summoning spells up to level 1.", B_FALSE); addskilldesc(SK_SS_SUMMONING, PR_BEGINNER, "Allows you to cast Summoning spells up to level 2.", B_FALSE); - addskilldesc(SK_SS_SUMMONING, PR_ADEPT, "Allows you to cast Summoning spells up to level 4.", B_FALSE); - addskilldesc(SK_SS_SUMMONING, PR_SKILLED, "Allows you to cast Summoning spells up to level 6.", B_FALSE); - addskilldesc(SK_SS_SUMMONING, PR_EXPERT, "Allows you to cast Summoning spells up to level 8.", B_FALSE); - addskilldesc(SK_SS_SUMMONING, PR_MASTER, "Allows you to cast Summoning spells up to level 9.", B_FALSE); + addskilldesc(SK_SS_SUMMONING, PR_ADEPT, "Allows you to cast Summoning spells up to level 3.", B_FALSE); + addskilldesc(SK_SS_SUMMONING, PR_SKILLED, "Allows you to cast Summoning spells up to level 4.", B_FALSE); + addskilldesc(SK_SS_SUMMONING, PR_EXPERT, "Allows you to cast Summoning spells up to level 5.", B_FALSE); + addskilldesc(SK_SS_SUMMONING, PR_MASTER, "Allows you to cast Summoning spells up to level 6.", B_FALSE); addskill(SK_SS_TRANSLOCATION, "Translocation", "Boosts casting of spells from this school.", 50); addskilldesc(SK_SS_TRANSLOCATION, PR_NOVICE, "Allows you to cast Translocation spells up to level 1.", B_FALSE); addskilldesc(SK_SS_TRANSLOCATION, PR_BEGINNER, "Allows you to cast Translocation spells up to level 2.", B_FALSE); - addskilldesc(SK_SS_TRANSLOCATION, PR_ADEPT, "Allows you to cast Translocation spells up to level 4.", B_FALSE); - addskilldesc(SK_SS_TRANSLOCATION, PR_SKILLED, "Allows you to cast Translocation spells up to level 6.", B_FALSE); - addskilldesc(SK_SS_TRANSLOCATION, PR_EXPERT, "Allows you to cast Translocation spells up to level 8.", B_FALSE); - addskilldesc(SK_SS_TRANSLOCATION, PR_MASTER, "Allows you to cast Translocation spells up to level 9.", B_FALSE); + addskilldesc(SK_SS_TRANSLOCATION, PR_ADEPT, "Allows you to cast Translocation spells up to level 3.", B_FALSE); + addskilldesc(SK_SS_TRANSLOCATION, PR_SKILLED, "Allows you to cast Translocation spells up to level 4.", B_FALSE); + addskilldesc(SK_SS_TRANSLOCATION, PR_EXPERT, "Allows you to cast Translocation spells up to level 5.", B_FALSE); + addskilldesc(SK_SS_TRANSLOCATION, PR_MASTER, "Allows you to cast Translocation spells up to level 6.", B_FALSE); addskill(SK_SS_WILD, "Wild Magic", "Boosts casting of spells from this school.", 50); addskilldesc(SK_SS_WILD, PR_NOVICE, "Allows you to cast Wild Magic spells up to level 1.", B_FALSE); addskilldesc(SK_SS_WILD, PR_BEGINNER, "Allows you to cast Wild Magic spells up to level 2.", B_FALSE); - addskilldesc(SK_SS_WILD, PR_ADEPT, "Allows you to cast Wild Magic spells up to level 4.", B_FALSE); - addskilldesc(SK_SS_WILD, PR_SKILLED, "Allows you to cast Wild Magic spells up to level 6.", B_FALSE); - addskilldesc(SK_SS_WILD, PR_EXPERT, "Allows you to cast Wild Magic spells up to level 8.", B_FALSE); - addskilldesc(SK_SS_WILD, PR_MASTER, "Allows you to cast Wild Magic spells up to level 9.", B_FALSE); + addskilldesc(SK_SS_WILD, PR_ADEPT, "Allows you to cast Wild Magic spells up to level 3.", B_FALSE); + addskilldesc(SK_SS_WILD, PR_SKILLED, "Allows you to cast Wild Magic spells up to level 4.", B_FALSE); + addskilldesc(SK_SS_WILD, PR_EXPERT, "Allows you to cast Wild Magic spells up to level 5.", B_FALSE); + addskilldesc(SK_SS_WILD, PR_MASTER, "Allows you to cast Wild Magic spells up to level 6.", B_FALSE); } void interrupt(lifeform_t *lf) { @@ -15290,8 +15342,7 @@ int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *r break; } } else if (ct == SC_MORALE) { - // ie. -5 to 5 - othermod += (getstatmod(lf, A_WIS) / 10); + othermod += (getstatmod(lf, A_WIS) / 10); // ie. -5 to 5 } else if (ct == SC_OPENLOCKS) { enum SKILLLEVEL slev; slev = getskill(lf, SK_LOCKPICKING); @@ -15733,6 +15784,21 @@ void stopsprinting(lifeform_t *lf) { } +int stun(lifeform_t *lf, int nturns) { + if (lfhasflag(lf, F_ASLEEP)) { + return B_TRUE; + } + if (isplayer(lf)) { + msg("You are stunned!"); + } else if (cansee(player, lf)) { + char buf[BUFLEN]; + getlfname(lf, buf); + msg("%s is stunned!", buf); + } + taketime(lf, getactspeed(lf)*nturns); + return B_FALSE; +} + // wrapper for addmonster(), but announce that it appears // and make it worth zero xp. // @@ -16054,6 +16120,8 @@ void turneffectslf(lifeform_t *lf) { int i; int willvanish = B_FALSE; int donefeetwet = B_FALSE; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; map = lf->cell->map; @@ -16164,7 +16232,7 @@ void turneffectslf(lifeform_t *lf) { } // MP regeneration - getflags(lf->flags, F_MPREGEN, F_NONE); + getflags(lf->flags, retflag, &nretflags, F_MPREGEN, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if (f->id == F_MPREGEN) { @@ -16573,7 +16641,7 @@ void turneffectslf(lifeform_t *lf) { // for flags which can occur multiple times - getflags(o->flags, F_DEEPWATER, F_WALKDAMBP, F_NONE); + getflags(o->flags, retflag, &nretflags, F_DEEPWATER, F_WALKDAMBP, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if ((f->id == F_DEEPWATER) && !isairborne(lf)) { @@ -16620,7 +16688,7 @@ void turneffectslf(lifeform_t *lf) { if (isdead(lf)) return; - getflags(lf->flags, F_ATTACHEDTO, F_CANWILL, F_CHARMEDBY, F_FLEEFROM, F_GRABBEDBY, F_GRABBING, F_BOOSTSPELL, F_FEIGNINGDEATH, + getflags(lf->flags, retflag, &nretflags, F_ATTACHEDTO, F_CANWILL, F_CHARMEDBY, F_FLEEFROM, F_GRABBEDBY, F_GRABBING, F_BOOSTSPELL, F_FEIGNINGDEATH, F_NOFLEEFROM, F_PETOF, F_SPOTTED, F_STABBEDBY, F_TARGETCELL, F_TARGETLF, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; @@ -17111,17 +17179,8 @@ int usestairs(lifeform_t *lf, object_t *o, int onpurpose) { newdepth = 1; } createmap(newmap, newdepth, newregion, curmap, dir, o); - // if we stayed within the same region, our stairs should - // now have a destination, since createmap() will automatically check - // previous/next levels in the same region. - - // if not, we need to call linkstairs() on the staircase first. - /* - if (newmap->region->id != curmap->region->id) { - linkstairs(o); - } -*/ - // at this point, stairs should have a destination + // at this point, stairs should have a destination (map creation will + // fill it in) newcell = getstairdestination(o); madenewmap = B_TRUE; } @@ -17321,54 +17380,6 @@ int validateraces(void) { cell_t fakecell; map_t fakemap; - // add flags based on raceclass, and fill in missing alignments - for (r = firstrace ; r ; r = r->next) { - if (r->raceclass->id == RC_AQUATIC) { - addflag(r->flags, F_HASSKILL, SK_SWIMMING, PR_MASTER, NA, NULL); - addflag(r->flags, F_AQUATIC, B_TRUE, NA, NA, NULL); - addflag(r->flags, F_BREATHWATER, B_TRUE, NA, NA, NULL); - addflag(r->flags, F_DTIMMUNE, DT_WATER, NA, NA, NULL); - } else if (r->raceclass->id == RC_DEMON) { - addflag(r->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL); - } else if (r->raceclass->id == RC_GOD) { - addflag(r->flags, F_PIETY, 100, NA, NA, NULL); - addflag(r->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addflag(r->flags, F_MORALE, 10, NA, NA, NULL); - addflag(r->flags, F_BREATHWATER, B_TRUE, NA, NA, NULL); - addflag(r->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL); - addflag(r->flags, F_DTIMMUNE, DT_NECROTIC, NA, NA, NULL); - addflag(r->flags, F_DTIMMUNE, DT_POISON, NA, NA, NULL); - addflag(r->flags, F_DTIMMUNE, DT_POISONGAS, NA, NA, NULL); - addflag(r->flags, F_FLEEONHPPCT, 20, NA, NA, NULL); - addflag(r->flags, F_RESISTMAG, 15, NA, NA, NULL); - addflag(r->flags, F_MORALE, 40, NA, NA, NULL); - } else if (r->raceclass->id == RC_MAGIC) { - addflag(r->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL); - } else if (r->raceclass->id == RC_PLANT) { - addflag(r->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL); - addflag(r->flags, F_DTRESIST, DT_BASH, NA, NA, NULL); - addflag(r->flags, F_DTVULN, DT_FIRE, NA, NA, NULL); - addflag(r->flags, F_DTVULN, DT_COLD, NA, NA, NULL); - addflag(r->flags, F_DTVULN, DT_DECAY, NA, NA, NULL); - addflag(r->flags, F_FLAMMABLE, PERMENANT, NA, NA, NULL); - } else if (r->raceclass->id == RC_SLIME) { - addflag(lastrace->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL); - } else if (r->raceclass->id == RC_UNDEAD) { - addflag(r->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL); - addflag(r->flags, F_DTIMMUNE, DT_COLD, NA, NA, NULL); - addflag(r->flags, F_DTIMMUNE, DT_POISON, NA, NA, NULL); - addflag(r->flags, F_DTIMMUNE, DT_POISONGAS, NA, NA, NULL); - addflag(r->flags, F_DTIMMUNE, DT_DECAY, NA, NA, NULL); - addflag(r->flags, F_DTIMMUNE, DT_NECROTIC, NA, NA, NULL); - addflag(r->flags, F_DTVULN, DT_HOLY, NA, NA, NULL); - addflag(r->flags, F_SEEINDARK, B_TRUE, NA, NA, NULL); - } - - if (!hasflag(r->flags, F_ALIGNMENT)) { - addflag(r->flags, F_ALIGNMENT, AL_NEUTRAL, NA, NA, NULL); - } - } - // generate xp list genxplist(); @@ -17735,6 +17746,8 @@ int wear(lifeform_t *lf, object_t *o) { enum BODYPART possbp[MAXBODYPARTS]; int nparts = 0; enum BODYPART bp; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; // this might impact your AR if (isplayer(lf)) { @@ -17768,7 +17781,7 @@ int wear(lifeform_t *lf, object_t *o) { nparts = 0; - getflags(o->flags, F_GOESON, F_NONE); + getflags(o->flags, retflag, &nretflags, F_GOESON, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if (f->id == F_GOESON) { diff --git a/lf.h b/lf.h index e59a18b..dd583a5 100644 --- a/lf.h +++ b/lf.h @@ -38,6 +38,7 @@ int canpolymorphto(enum RACE rid); int canpush(lifeform_t *lf, object_t *o, int dir); int canquaff(lifeform_t *lf, object_t *o); int cansee(lifeform_t *viewer, lifeform_t *viewee); +int cansee_real(lifeform_t *viewer, lifeform_t *viewee, int uselos); int cansleep(lifeform_t *lf); int canwear(lifeform_t *lf, object_t *o, enum BODYPART where); int canweild(lifeform_t *lf, object_t *o); @@ -175,6 +176,7 @@ enum POISONSEVERITY getpoisonseverity(enum POISONTYPE ptype); int getraceclass(lifeform_t *lf); int getracerarity(map_t *map, enum RACE rid); object_t *getrandomarmour(lifeform_t *lf); +enum BODYPART getrandomcorebp(lifeform_t *lf); job_t *getrandomjob(int onlyplayerjobs); int getrandommonlevel(race_t *r, map_t *m); race_t *getrandomrace(cell_t *c, int forcedepth); @@ -204,6 +206,7 @@ map_t *gotolev(lifeform_t *lf, int depth, object_t *fromstairs); int gotosleep(lifeform_t *lf, int onpurpose); int hasfreeaction(lifeform_t *lf); job_t *hasjob(lifeform_t *lf, enum JOB job); +int injure(lifeform_t *lf, enum BODYPART where, enum DAMTYPE damtype); int lfcanbestoned(lifeform_t *lf); flag_t *lfhasflag(lifeform_t *lf, enum FLAG fid); flag_t *lfhasflagval(lifeform_t *lf, enum FLAG fid, int val0, int val1, int val2, char *text); @@ -216,6 +219,7 @@ int hasbp(lifeform_t *lf, enum BODYPART bp); flag_t *hasactivespell(lifeform_t *lf, enum OBTYPE sid); int haslof(cell_t *src, cell_t *dest, enum LOFTYPE loftype, cell_t **newdest); int haslos(lifeform_t *viewer, cell_t *dest); +int haslos_fast(lifeform_t *viewer, cell_t *dest); void initjobs(void); void initrace(void); void initskills(void); @@ -320,6 +324,7 @@ void stopeating(lifeform_t *lf); void stopresting(lifeform_t *lf); void stoprunning(lifeform_t *lf); void stopsprinting(lifeform_t *lf); +int stun(lifeform_t *lf, int nturns); lifeform_t *summonmonster(lifeform_t *caster, cell_t *c, enum RACE rid, char *racename, int lifetime, int wantfriendly); //int testammo(lifeform_t *lf, object_t *o); int takeoff(lifeform_t *lf, object_t *o); diff --git a/map.c b/map.c index 9b1cae9..3af29e2 100644 --- a/map.c +++ b/map.c @@ -30,9 +30,6 @@ extern lifeform_t *player; extern lifeform_t *godlf[]; extern int ngodlfs; -extern flag_t *retflag[]; -extern int nretflags; - extern glyph_t tempglyph; extern enum OBCLASS sortorder[]; @@ -55,8 +52,7 @@ cell_t *addcell(map_t *m, int x, int y) { cell->visited = B_FALSE; cell->obpile = addobpile(NOOWNER, cell, NOOB); cell->lf = NULL; - cell->roomid = -1; - cell->vault = NULL; + cell->room = NULL; cell->lit = L_NOTLIT; cell->origlit = L_NOTLIT; cell->littimer = 0; @@ -499,6 +495,13 @@ void getradiuscells(cell_t *centre, int radius, int dirtype, enum LOFTYPE needlo } } +int getroomid(cell_t *c) { + if (c->room) { + return c->room->id; + } + return -1; +} + // whichside should be D_ORTH // for now, this function will NOT include room corners void getroomedge(map_t *map, int roomid, int minx, int miny, int maxx, int maxy, int whichside, cell_t **retcell, int *ncells, int onlywantsolid) { @@ -779,6 +782,7 @@ int autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy, in doorsadded++; } else { setcelltype(cell[sel], cell[sel]->habitat->emptycelltype); + addflag(map->flags, F_ROOMEXIT, roomid, cell[sel]->x, cell[sel]->y, NULL); doorsadded++; } } @@ -1172,6 +1176,7 @@ int getmapdifficulty(map_t *m) { return diff; } + // forglyph will be true if we are using this function for the purpose // of figuring out which glyph to draw object_t *gettopobject(cell_t *where, int forglyph) { @@ -1501,6 +1506,21 @@ int countlfs(map_t *map) { return count; } +int countmapobs(map_t *m, enum OBTYPE oid) { + cell_t *c; + int count = 0,x,y; + + for (y = 0; y < m->h; y++) { + for (x = 0; x < m->w; x++) { + c = getcellat(m, x, y); + if (c) { + count += countobsoftype(c->obpile, oid); + } + } + } + return count; +} + // void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_t *entryob) { int wantrooms = B_TRUE; @@ -1728,11 +1748,16 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_ // just do a normal room createroom(map, i, NA, NA, 0, 0, &rx, &ry, &roomw[i],&roomh[i], 50, B_FALSE); roomvault[i] = B_FALSE; - linkexits(map, i, rx, ry, rx+roomw[i]-1, ry+roomh[i]-1); } } } + // link up room exits + for (i = 0; i < map->nrooms; i++) { + linkexits(map, map->room[i].id); + } + + // add staircases. // first dungeon level has 1 up stairs, 3 down. // subsequent levels always have 3 up and down stairs @@ -1856,6 +1881,7 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_ } // end foreach room } // end if wantrooms & nrooms>0 + if (db) dblog("Finished adding objects."); // now do a border @@ -2453,7 +2479,7 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex cell_t *c; c = getcellat(map, x, y); // no random obs in vaults - if (c && isempty(c) && !c->vault) { + if (c && isempty(c) && !getcellvault(c)) { if (rnd(1,100) <= c->habitat->randthingpct) { addrandomthing(c, c->habitat->randobpct, NULL); } @@ -2507,6 +2533,7 @@ int createvault(map_t *map, int roomid, vault_t *v, int *retw, int *reth, int *r int minx,miny,maxx,maxy; int db = B_FALSE; int rotation = 0; + room_t *thisroom = NULL; flag_t *f; // default @@ -2556,6 +2583,16 @@ int createvault(map_t *map, int roomid, vault_t *v, int *retw, int *reth, int *r maxx = minx + (w-1); maxy = miny + (h-1); + map->room[map->nrooms].id = roomid; + map->room[map->nrooms].x1 = minx; + map->room[map->nrooms].y1 = miny; + map->room[map->nrooms].x2 = maxx; + map->room[map->nrooms].y2 = maxy; + map->room[map->nrooms].vault = v; + thisroom = &(map->room[map->nrooms]); + map->nrooms++; + + // now make it if (db) dblog("making vault %s at pos %d,%d on map %s", v->id, minx, miny, map->name); for (y = miny; y <= maxy; y++) { @@ -2570,7 +2607,7 @@ int createvault(map_t *map, int roomid, vault_t *v, int *retw, int *reth, int *r ct = getvaultcelltype(v, x-minx,y-miny, rotation); setcelltype(cell, ct ? ct->id : cell->habitat->emptycelltype); // set roomid - cell->roomid = roomid; + cell->room = thisroom; // add objects addvaultcellcontents(cell, v, x-minx,y-miny, rotation); } @@ -2593,22 +2630,41 @@ int createvault(map_t *map, int roomid, vault_t *v, int *retw, int *reth, int *r autodoors(map, roomid, minx, miny, maxx, maxy, f->val[0], B_NODOORS); } - linkexits(map, roomid, minx, miny, maxx,maxy); - - map->nrooms++; - return B_FALSE; } // make sure exits/doors in a given room link up to the rest of the map. -int linkexits(map_t *m, int roomid, int minx, int miny, int maxx, int maxy) { +int linkexits(map_t *m, int roomid) { int x,y,i; cell_t *poss[MAXCANDIDATES],*c; int nposs = 0; int db = B_FALSE; int nadded = 0; + int minx = -1, miny = -1, maxx = -1, maxy = -1; - if (db) dblog("linkexits for roomid %d", roomid); + // figure out room coords + for (i = 0; i < m->nrooms; i++) { + if (m->room[i].id == roomid) { + minx = m->room[i].x1; + miny = m->room[i].y1; + maxx = m->room[i].x2; + maxy = m->room[i].y2; + break; + } + } + assert(minx != -1); + + + if (db) { + char buf[BUFLEN]; + vault_t *v; + c = getrandomroomcell(m, roomid); + v = getcellvault(c); + sprintf(buf, "*** linkexits for roomid %d (%s) [%d,%d-%d,%d]", roomid, + v ? v->id : "novault", + minx,miny,maxx,maxy); + dblog("%s", buf); + } // find all doors or f_roomexits for (y = miny; y <= maxy; y++) { @@ -2616,8 +2672,11 @@ int linkexits(map_t *m, int roomid, int minx, int miny, int maxx, int maxy) { c = getcellat(m, x, y); if (!c) continue; - if (hasobwithflag(c->obpile, F_DOOR) || hasflagval(m->flags, F_ROOMEXIT, roomid, x, y, NULL)) { - if (db) dblog("found door/exit at %d,%d",x,y); + if (hasobwithflag(c->obpile, F_DOOR)) { + if (db) dblog("found door at %d,%d",x,y); + poss[nposs++] = c; + } else if (hasflagval(m->flags, F_ROOMEXIT, roomid, x, y, NULL)) { + if (db) dblog("found roomexit at %d,%d",x,y); poss[nposs++] = c; } } @@ -2630,9 +2689,9 @@ int linkexits(map_t *m, int roomid, int minx, int miny, int maxx, int maxy) { for (i = 0; i < nposs; i++) { int d; int ncorridors = 0; - for (d = DC_N; d <= DC_NW; d++) { + for (d = D_N; d <= D_W; d++) { c = getcellindir(poss[i], d); - if (c && cellwalkable(NULL, c, NULL) && (c->roomid != roomid)) { + if (c && cellwalkable(NULL, c, NULL) && (getroomid(c) != roomid)) { ncorridors++; } } @@ -2642,37 +2701,170 @@ int linkexits(map_t *m, int roomid, int minx, int miny, int maxx, int maxy) { if (ncorridors == 0) { int poss2[MAXCANDIDATES],nposs2; int dist[MAXDIR_ORTH]; - int bestdist = 999; + int hitsedge[MAXDIR_ORTH]; + int mindist = 999,maxdist = -1; if (db) dblog(" Need to link."); // link it. starting from the door, count the number of cells in // each direction until we hit an empty (walkable) cell which isn't a room. + // if we hit a cell of this roomid, mark this dir as invalid. for (d = D_N; d <= D_W; d++) { dist[d] = 0; + hitsedge[d] = B_TRUE; c = getcellindir(poss[i], d); while (c) { dist[d]++; - if (isroom(c)) { + if (getroomid(c) == roomid) { // mark dir as invalid dist[d] = 999; break; } else if (cellwalkable(NULL, c, NULL)) { // walkable and not in this vault. finished. + hitsedge[d] = B_FALSE; break; + } else { + int perpdir[2],n; + cell_t *pcell = NULL; + perpdir[0] = d - 1; if (perpdir[0] < D_N) perpdir[0] = D_W; + perpdir[1] = d + 1; if (perpdir[1] > D_W) perpdir[1] = D_N; + // is there an adjacent walkable cell in a perpendicular direction + // which isn't from the starting room? + for (n = 0; n <= 1; n++) { + pcell = getcellindir(c, perpdir[n]); + if (pcell) { + if ((getroomid(pcell) != roomid) && cellwalkable(NULL, pcell, NULL)) { + // finished. + hitsedge[d] = B_FALSE; + break; + } + } + } + } // check next cell c = getcellindir(c, d); // getting the same cell! } - if (dist[d] < bestdist) bestdist = dist[d]; + if (dist[d] != 999) { + if (!hitsedge[d]) { + if (dist[d] < mindist) mindist = dist[d]; + } + if (dist[d] > maxdist) maxdist = dist[d]; + } } - if (bestdist != 999) { + if (mindist == 999) { + cell_t *turncell = NULL,*endcell = NULL; + int perpdir[2]; + int startdir = D_NONE; + int turndir = D_NONE; + int startdist = 0; + // no good directions. + if (db) dblog(" No directions lead to rooms. Trying turns."); + // starting at the LONGEST distance, traverse up each dir, + // branching off looking for rooms. + + // find longest distance + for (d = D_N; d <= D_W; d++) { + if (dist[d] == maxdist) { + startdir = d; + break; + } + } + assert(startdir != D_NONE); + // figure out perpendicular dirs + perpdir[0] = startdir - 1; if (perpdir[0] < D_N) perpdir[0] = D_W; + perpdir[1] = startdir + 1; if (perpdir[1] > D_W) perpdir[1] = D_N; + + if (db) dblog(" Will walk %s (dist %d), checking %s and %s.", getdirname(startdir), maxdist, + getdirname(perpdir[0]), getdirname(perpdir[1])); + + // check in startdir + c = getcellindir(poss[i], startdir); + while (c && !turncell) { + int n; + cell_t *c2; + startdist++; + // check left/right from this door for rooms + for (n = 0; n <= 1; n++) { + int turndist = 0; + c2 = getcellindir(c, perpdir[n]); + while (c2) { + int gotsolution = B_FALSE; + turndist++; + if (getroomid(c2) == roomid) { + // hits same room, not ok. + break; + } else if (cellwalkable(NULL, c2, NULL)) { + if (db) dblog(" Got to an empty cell here."); + gotsolution = B_TRUE; + } else if (turndist > 1) { + // check l/r too + int perpdir2[2],nn; + cell_t *pcell = NULL; + perpdir2[0] = perpdir[n] - 1; if (perpdir2[0] < D_N) perpdir2[0] = D_W; + perpdir2[1] = perpdir[n] + 1; if (perpdir2[1] > D_W) perpdir2[1] = D_N; + for (nn = 0; nn <= 1; nn++) { + pcell = getcellindir(c2, perpdir2[nn]); + if (pcell) { + if ((getroomid(pcell) != roomid) && + cellwalkable(NULL, pcell, NULL)) { + // finished. + if (db) dblog(" Got to an empty cell next to us."); + gotsolution = B_TRUE; + break; + } + } + } + } + + if (gotsolution) { + if (db) dblog(" Solution found: Walk %d %s, then %d %s.", + startdist, getdirname(startdir), + turndist, getdirname(perpdir[n])); + // walkable and not in this roomid. ok! + turncell = c; + endcell = c2; + turndir = perpdir[n]; + break; + } + // check next cell + c2 = getcellindir(c2, perpdir[n]); + } + if (turncell) break; + } + // now keep going in main direction. + c = getcellindir(c, startdir); + } + + if (turncell) { + // make a path up to the turn point. + if (db) dblog(" Making path from vault to corner, initdir=%s", getdirname(startdir)); + nadded++; + c = getcellindir(poss[i], startdir); + while (c != turncell) { + setcelltype(c, c->habitat->emptycelltype); + c = getcellindir(c, startdir); + } + // clear the corner cell + setcelltype(c, c->habitat->emptycelltype); + if (db) dblog(" Making path from corner to rest of map, turndir=%s", getdirname(turndir)); + // now turn and clear up to the next room/empty cell + c = getcellindir(c, turndir); + while (c != endcell) { + setcelltype(c, c->habitat->emptycelltype); + c = getcellindir(c, turndir); + } + } else { + // give up?? + if (db) dblog(" Cannot find a way to link up."); + } + } else { int whichway,sel; - // now pick the shortest one - // get list of all the maximums and randomly tie-break + // now pick the shortest one which hits the edge + // get list of all the minimums and randomly tie-break nposs2 = 0; for (d = D_N; d <= D_W; d++) { - if (dist[d] == bestdist) { + if (dist[d] == mindist) { poss2[nposs2++] = d; } } @@ -2680,7 +2872,7 @@ int linkexits(map_t *m, int roomid, int minx, int miny, int maxx, int maxy) { whichway = poss2[sel]; // now create a path - if (db) dblog(" Linking %s (distance %d).", getdirname(whichway), bestdist); + if (db) dblog(" Linking %s (distance %d).", getdirname(whichway), mindist); nadded++; c = getcellindir(poss[i], whichway); while (c && !cellwalkable(NULL, c, NULL)) { @@ -2752,6 +2944,7 @@ int createroom(map_t *map, int roomid, int overrideminw, int overrideminh, int x int minroomh = MIN_ROOMH; int maxroomw = MAX_ROOMW; int maxroomh = MAX_ROOMH; + room_t *thisroom = NULL; if (overrideminw != NA) { minroomw = overrideminw; @@ -2783,6 +2976,15 @@ int createroom(map_t *map, int roomid, int overrideminw, int overrideminh, int x maxx = minx + (w-1); maxy = miny + (h-1); + map->room[map->nrooms].id = roomid; + map->room[map->nrooms].x1 = minx; + map->room[map->nrooms].y1 = miny; + map->room[map->nrooms].x2 = maxx; + map->room[map->nrooms].y2 = maxy; + map->room[map->nrooms].vault = NULL; + thisroom = &(map->room[map->nrooms]); + map->nrooms++; + for (y = miny; y <= maxy; y++) { for (x = minx; x <= maxx; x++) { cell = getcellat(map, x, y); @@ -2801,7 +3003,7 @@ int createroom(map_t *map, int roomid, int overrideminw, int overrideminh, int x } else { setcelltype(cell, CT_ROOM); } - cell->roomid = roomid; + cell->room = thisroom; } } } @@ -2811,8 +3013,6 @@ int createroom(map_t *map, int roomid, int overrideminw, int overrideminh, int x autodoors(map, roomid, minx, miny, maxx, maxy, doorpct, 50); } - map->nrooms++; - return B_FALSE; } @@ -3188,6 +3388,16 @@ regiontype_t *findregiontype(enum REGIONTYPE rtype) { return NULL; } +room_t *findroom(map_t *m, int roomid) { + int i; + for (i = 0; i < m->nrooms; i++) { + if (m->room[i].id == roomid) { + return &(m->room[i]); + } + } + return NULL; +} + map_t *findsurfaceexitmap(map_t *m) { object_t *o; cell_t *c; @@ -3281,13 +3491,20 @@ cell_t *getcellindir(cell_t *cell, int dir) { return newcell; } +vault_t *getcellvault(cell_t *c) { + if (c->room) { + return c->room->vault; + } + return NULL; +} + cell_t *getclosestroomcell(lifeform_t *lf, int roomid) { int i; cell_t *c,*best = NULL; int closest = 9999; for (i = 0; i < lf->cell->map->w * lf->cell->map->h; i++) { c = lf->cell->map->cell[i]; - if ((c->roomid == roomid) & cellwalkable(lf, c, NULL)) { + if ((getroomid(c) == roomid) & cellwalkable(lf, c, NULL)) { if (getcelldist(lf->cell, c) < closest) { best = c; } @@ -3591,10 +3808,10 @@ cell_t *getrandomroomcell(map_t *map, int roomid) { //if (c && cellwalkable(NULL, c, NULL)) { if (c && !c->type->solid) { int ok = B_FALSE; - if (c->roomid == roomid) { + if (getroomid(c) == roomid) { ok = B_TRUE; } else if (roomid == ANYROOM) { - if (c->roomid != -1) { + if (isroom(c) != -1) { ok = B_TRUE; } } @@ -3623,7 +3840,7 @@ void getroomcells(map_t *m, int roomid, cell_t **retcell, int *ncells) { *ncells = 0; for (i = 0; i < m->w*m->h; i++) { c = m->cell[i]; - if (c && (c->roomid == roomid)) { + if (c && (getroomid(c) == roomid)) { retcell[*ncells] = c; (*ncells)++; } @@ -3878,6 +4095,8 @@ int isempty(cell_t *c) { //returns TT_ based on what you can scan there int isinscanrange(cell_t *c, void **thing, char *desc, glyph_t *glyph) { flag_t *f; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; int i; // handle scanner f = lfhasflag(player, F_DETECTLIFE); @@ -3952,8 +4171,7 @@ int isinscanrange(cell_t *c, void **thing, char *desc, glyph_t *glyph) { } // get list of all detected ob ids. - getflags(player->flags, F_DETECTOBS, F_NONE); - + getflags(player->flags, retflag, &nretflags, F_DETECTOBS, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if (getcelldistorth(player->cell, c) <= f->val[0]) { @@ -4057,7 +4275,7 @@ int isoutdoors(map_t *m) { } int isroom(cell_t *c) { - if (c && (c->roomid >= 0)) { + if (c && (getroomid(c) >= 0)) { return B_TRUE; } return B_FALSE; @@ -4147,6 +4365,8 @@ int linkstairs(object_t *o, object_t *o2) { cell_t *staircell; flag_t *f; + assert(o); + staircell = getoblocation(o); stairmap = staircell->map; @@ -4198,10 +4418,9 @@ int linkstairs(object_t *o, object_t *o2) { } } 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); + dblog("ERROR - stairs link to existing map %d(depth %d), but it has no free stairs.",othermap->id, othermap->depth); + msg("ERROR - stairs link to existing map %d(depth %d), but it has no free stairs.",othermap->id, othermap->depth); more(); - assert(0 == 1); } } // end if othermap } // end if !o2 @@ -4332,6 +4551,7 @@ void mapentereffects(map_t *m) { cell_t *c; flag_t *f; for (i = 0; i < m->w * m->h; i++) { + vault_t *v; // teleport shopkeepers back to their shops c = m->cell[i]; if (c->lf && hasjob(c->lf, J_SHOPKEEPER) && !isplayer(c->lf)) { @@ -4347,12 +4567,13 @@ void mapentereffects(map_t *m) { } } } + v = getcellvault(c); // replace people in the Inn - if (c->vault && streq(c->vault->id, "inn") && c->lf && (c->lf->race->id == R_HUMAN)) { + if (v && streq(v->id, "inn") && c->lf && (c->lf->race->id == R_HUMAN)) { lifeform_t *lf; killlf(c->lf); lf = addmonster(c, R_HUMAN, NULL, B_TRUE, 1, B_FALSE, NULL); - addflag(lf->flags, F_STAYINROOM, c->roomid, B_MAYCHASE, NA, NULL); + addflag(lf->flags, F_STAYINROOM, getroomid(c), B_MAYCHASE, NA, NULL); } } } @@ -4464,7 +4685,6 @@ void setcelltype(cell_t *cell, enum CELLTYPE id) { assert(cell); cell->type = findcelltype(id); assert(cell->type); - //cell->roomid = -1; if ((gamemode == GM_GAMESTARTED) && haslos(player, cell)) { needredraw = B_TRUE; } diff --git a/map.h b/map.h index b5fdb83..596ec97 100644 --- a/map.h +++ b/map.h @@ -26,6 +26,7 @@ flag_t *getmapcoords(map_t *m, int *x, int *y); int getmapdifficulty(map_t *m); map_t *getmapindir(map_t *src, int dir); void getradiuscells(cell_t *centre, int radius, int dirtype, enum LOFTYPE needlof, int wantcentre, cell_t **retcell, int *ncells); +int getroomid(cell_t *c); void getroomedge(map_t *m, int roomid, int minx, int miny, int maxx, int maxy, int whichside, cell_t **retcell, int *ncells, int onlywantsolid); object_t *gettopobject(cell_t *where, int forglyph); void calclight(map_t *map); @@ -36,6 +37,7 @@ int countadjcellswithflag(cell_t *cell, enum FLAG fid, int dirtype); int countadjwalls(cell_t *cell); int countcellexits(cell_t *cell); int countcellexitsfor(lifeform_t *lf); +int countmapobs(map_t *m, enum OBTYPE oid); void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_t *entryob); void createforest(map_t *map, int depth, map_t *parentmap, int exitdir, object_t *entryob, int nclearings); void createhabitat(map_t *map, int depth, map_t *parentmap, int exitdir, object_t *entryob); @@ -64,9 +66,11 @@ region_t *findregion(int regionid); region_t *findregionbytype(enum REGIONTYPE rtid); map_t *findregionmap(int regionid, int depth); regiontype_t *findregiontype(enum REGIONTYPE rtype); +room_t *findroom(map_t *m, int roomid); map_t *findsurfaceexitmap(map_t *m); void forgetcells(map_t *map, int amt); cell_t *getcellindir(cell_t *cell, int dir); +vault_t *getcellvault(cell_t *c); cell_t *getclosestroomcell(lifeform_t *lf, int roomid); int getnewdigdir(cell_t *cell, int lastdir, int turnpct, int *moved); int getobchance(int habitat); @@ -102,7 +106,7 @@ int isonmap(map_t *map, int x, int y); int isoutdoors(map_t *m); int isroom(cell_t *c); int iswallindir(cell_t *cell, int dir); -int linkexits(map_t *m, int roomid, int minx, int miny, int maxx, int maxy); +int linkexits(map_t *m, int roomid); int linkholes(map_t *map); int linkstairs(object_t *o, object_t *o2); void makedoor(cell_t *cell, int openchance); diff --git a/move.c b/move.c index 7619302..b3dd51d 100644 --- a/move.c +++ b/move.c @@ -882,8 +882,13 @@ int moveeffects(lifeform_t *lf) { int didmsg = B_FALSE; if (isbleeding(lf)) { - if (rnd(1,2) == 1) { + if (lfhasflagval(lf, F_INJURY, BP_LEGS, DT_SLASH, NA, NULL)) { bleed(lf); + losehp(lf, 1, DT_DIRECT, NULL, "blood loss"); + } else { + if (rnd(1,2) == 1) { + bleed(lf); + } } } @@ -928,6 +933,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) { int preshop = -1; int prespeed = B_FALSE, postspeed = B_FALSE; int prewater = B_FALSE; + vault_t *v; assert(newcell); @@ -943,9 +949,10 @@ int movelf(lifeform_t *lf, cell_t *newcell) { // update current cell + room id prespeed = getmovespeed(lf); - preroom = lf->cell->roomid; - if (lf->cell->vault && hasflag(lf->cell->vault->flags, F_VAULTISSHOP)) { - preshop = lf->cell->roomid; + preroom = getroomid(lf->cell); + v = getcellvault(lf->cell); + if (v && hasflag(v->flags, F_VAULTISSHOP)) { + preshop = getroomid(lf->cell); } // getting out of water? @@ -979,7 +986,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) { assert(!newcell->lf); // remember new room... - postroom = lf->cell->roomid; + postroom = getroomid(lf->cell); postspeed = getmovespeed(lf); // update new cell @@ -1198,6 +1205,11 @@ int movelf(lifeform_t *lf, cell_t *newcell) { if (cansee(l, lf)) { int dointerrupt = B_FALSE; + // much larger creatures moving will cause our los to be recalculated + if (getlfsize(lf) - getlfsize(l) >= 2) { + precalclos(l); + } + if (isplayer(l)) { if (areenemies(lf, l)) { if (lfhasflag(l, F_RUNNING) || lfhasflag(l, F_TRAINING)) { @@ -1238,7 +1250,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) { // leaving a shop if (preshop) { // are you about to go outside a shop with stolen goods? - if ((lf->cell->roomid == preshop) && (lf->cell->type->id != CT_FLOORSHOP)) { + if ((getroomid(lf->cell) == preshop) && (lf->cell->type->id != CT_FLOORSHOP)) { lifeform_t *shk; int nitems = 0; shk = findshopkeeper(lf->cell->map, preshop); @@ -1248,7 +1260,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) { sayphrase(shk, SP_PAYWARN, SV_SHOUT, NA, (nitems == 1) ? "that" : "those" ); didmsg = B_TRUE; } - } else if (lf->cell->roomid != preshop) { + } else if (getroomid(lf->cell) != preshop) { // you've left the shop lifeform_t *shk; shk = findshopkeeper(lf->cell->map, preshop); @@ -1592,17 +1604,19 @@ int opendoor(lifeform_t *lf, object_t *o) { } where = getoblocation(o); - if (!haslos(player, where)) { - // don't anonuce this if we can see it. - // normally 'noise()' takes care of this by - // checking if we have LOS to the lifeform making - // sound, but in this case it's the door making - // the sound, not the lf. - noise(where, NULL, NC_OTHER, 2, "a door opening.", NULL); - } - if (player && haslos(player, where)) { - needredraw = B_TRUE; - drawscreen(); + + if (player) { + if (haslos(player, where)) { + needredraw = B_TRUE; + drawscreen(); + } else { + // don't anonuce this if we can see it. + // normally 'noise()' takes care of this by + // checking if we have LOS to the lifeform making + // sound, but in this case it's the door making + // the sound, not the lf. + noise(where, NULL, NC_OTHER, 2, "a door opening.", NULL); + } } } return B_FALSE; @@ -2551,7 +2565,7 @@ int willmove(lifeform_t *lf, int dir, enum ERROR *error) { roomid = f->val[0]; if (roomid == NA) { // don't move out of ANY room. - if ((lf->cell->roomid != cell->roomid)) { + if ((getroomid(lf->cell) != getroomid(cell))) { if ((f->val[1] != NA) && aihastarget(lf)) { // exception! } else { @@ -2561,7 +2575,7 @@ int willmove(lifeform_t *lf, int dir, enum ERROR *error) { } } else { // don't move out of the given room. - if ((lf->cell->roomid == roomid) && (lf->cell->roomid != cell->roomid)) { + if ((getroomid(lf->cell) == roomid) && (getroomid(lf->cell) != getroomid(cell))) { if ((f->val[1] != NA) && aihastarget(lf)) { // exception! } else { diff --git a/nexus.c b/nexus.c index 6197860..152b392 100644 --- a/nexus.c +++ b/nexus.c @@ -1272,7 +1272,7 @@ int rollmpdice(lifeform_t *lf) { } else { return 0; } - mod = 100 + getstatmod(lf, A_IQ); + mod = 100 + getstatmod(lf, A_IQ) + (getskill(lf, SK_SPELLCASTING)/2); roll = rolldie(ndice, 4) + plus; @@ -1426,6 +1426,8 @@ void sortcommands(void) { void timeeffectsworld(map_t *map) { + flag_t *retflag[MAXCANDIDATES]; + int nretflags; lifeform_t *l; int db = B_FALSE; object_t *o,*nexto; @@ -1515,7 +1517,7 @@ void timeeffectsworld(map_t *map) { // now finish off water spread noredraw = B_TRUE; - getflags(map->flags, F_NEWWATERDEPTH, F_NONE); + getflags(map->flags, retflag, &nretflags, F_NEWWATERDEPTH, F_NONE); for (i = 0; i < nretflags; i++) { cell_t *c; f = retflag[i]; diff --git a/objects.c b/objects.c index 20f208e..53b532a 100644 --- a/objects.c +++ b/objects.c @@ -26,9 +26,6 @@ extern obmod_t *firstobmod,*lastobmod; extern material_t *material,*lastmaterial; extern skill_t *firstskill, *lastskill; -extern flag_t *retflag[]; -extern int nretflags; - void (*precalclos)(lifeform_t *); extern object_t *retobs[MAXPILEOBS+1]; @@ -442,6 +439,8 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes int wantlit = B_FALSE; int wantrarity = RR_NONE; int wantgoodness = G_NA; + map_t *targetmap = NULL; // for portals + cell_t *targetcell = NULL; // for portals int donesomething; object_t *addedob[MAXPILEOBS]; int nadded = 0; @@ -708,6 +707,36 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes corpserace = findracebyname(racename); ot = findot(OT_HEAD); + } else if (strstarts(p, "portal to lv")) { + char *pp; + int dlev; + pp = p + strlen("portal to lv"); + dlev = atoi(pp); + if (dlev > 0) { + cell_t *c; + c = getobpilelocation(where); + if (c) { + // find map within this region with the given depth + targetmap = findregionmap(c->map->region->id, dlev); + if (!targetmap) { + // create it + targetmap = addmap(); + createmap(targetmap, dlev, c->map->region, NULL, D_NONE, NULL); + } + targetcell = getrandomroomcell(targetmap, ANYROOM); + while (!cellwalkable(NULL, targetcell, NULL)) { + targetcell = getrandomadjcell(targetcell, WE_WALKABLE, B_ALLOWEXPAND); + } + } else { + // ie. adding to dummy cell + targetmap = NULL; + targetcell = NULL; + } + } else { + return NULL; + } + + ot = findot(OT_PORTAL); } else if (strstarts(p, "sign ")) { char *pp; pp = strchr(p, '\"'); @@ -1008,6 +1037,16 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes addflag(o->flags, F_SIGNTEXT, NA, NA, NA, signtext); } + // fill in portal destinations + if (targetmap) { + int tx = NA,ty = NA; + if (targetcell) { + tx = targetcell->x; + ty = targetcell->y; + } + addflag(o->flags, F_MAPLINK, targetmap->id, tx, ty, NULL); + } + // fill in door flags if (ndoorflags && isdoor(o, NULL)) { int n; @@ -1492,9 +1531,13 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes } // apply cost to shop items - if (o->pile->where && o->pile->where->vault && hasflag(o->pile->where->vault->flags, F_VAULTISSHOP)) { - if (canpickup(NULL, o, 1)) { - addflag(o->flags, F_SHOPITEM, getobvalue(o), o->pile->where->roomid, NA, NULL); + if (o->pile->where) { + vault_t *v; + v = getcellvault(o->pile->where); + if (v && hasflag(v->flags, F_VAULTISSHOP)) { + if (canpickup(NULL, o, 1)) { + addflag(o->flags, F_SHOPITEM, getobvalue(o), getroomid(o->pile->where), NA, NULL); + } } } @@ -2381,6 +2424,18 @@ int countobs(obpile_t *op, int onlyifknown) { return count; } +int countobsoftype(obpile_t *op, enum OBTYPE oid) { + object_t *o; + + int count = 0; + for (o = op->first ; o ; o = o->next) { + if (o->id == oid) { + count++; + } + } + return count; +} + int countnoncosmeticobs(obpile_t *op, int onlyifknown) { object_t *o; @@ -2471,6 +2526,12 @@ int doobtraps(object_t *o, lifeform_t *lf) { trapid = f->val[0]; trapeffects(NULL, trapid, lf); killflag(f); // now the trap gets removed + + // explosion traps kill the object + if (trapid == OT_TRAPMINE) { + killob(o); + } + return B_TRUE; } return B_FALSE; @@ -3057,8 +3118,10 @@ int getobaccuracy(object_t *wep, lifeform_t *weilder) { int getobbonus(object_t *o) { int bonus = 0,i; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; - getflags(o->flags, F_BONUS, F_NONE); + getflags(o->flags, retflag, &nretflags, F_BONUS, F_NONE); for (i = 0; i < nretflags; i++) { bonus += retflag[i]->val[0]; } @@ -3128,6 +3191,8 @@ int getobvalue(object_t *o) { flag_t *f; int rarity = 0,i; enum RARITY rr = RR_COMMON; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; if (o->type->id == OT_GOLD) { return o->amt; @@ -3143,7 +3208,7 @@ int getobvalue(object_t *o) { price += f->val[0]; } - getflags(o->flags, F_ARMOURRATING, F_BONUS, F_DAM, F_EDIBLE, F_LINKSPELL, F_MANUALOF, F_NONE); + getflags(o->flags, retflag, &nretflags, F_ARMOURRATING, F_BONUS, F_DAM, F_EDIBLE, F_LINKSPELL, F_MANUALOF, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; // damage @@ -3306,12 +3371,23 @@ char *getoperateverb(object_t *o) { // ie if you call this on a gem inside a bag inside // a barrel, will return the barrel. object_t *getoutercontainer(object_t *o) { + /* while (o->pile->parentob) { o = o->pile->parentob; } return o; + */ + return getoutercontainerop(o->pile); } +object_t *getoutercontainerop(obpile_t *op) { + object_t *o = NULL; + while (op->parentob) { + o = op->parentob; + op = o->pile; + } + return o; +} // ie. "it has xxx accuracy" char *getaccuracyname(int accpct) { @@ -3368,6 +3444,8 @@ object_t *getrandomammo(lifeform_t *lf) { object_t *o; flag_t *f; int i; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; gun = getfirearm(lf); if (!gun) { return NULL; @@ -3377,7 +3455,7 @@ object_t *getrandomammo(lifeform_t *lf) { // pick a specific ammo to use. USe a flag on wep // to do this? Or a flag on the player? - getflags(gun->flags, F_AMMOOB, F_NONE); + getflags(gun->flags, retflag, &nretflags, F_AMMOOB, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; for (o = lf->pack->first ; o ; o = o->next) { @@ -3967,6 +4045,8 @@ char *getobextrainfo(object_t *o, char *buf) { } cell_t *getoblocation(object_t *o) { + return getobpilelocation(o->pile); + /* if (o->pile->owner) { // held by someone return o->pile->owner->cell; } else if (o->pile->where) { // on the ground @@ -3979,6 +4059,22 @@ cell_t *getoblocation(object_t *o) { } // in a dummy cell return NULL; + */ +} + +cell_t *getobpilelocation(obpile_t *op) { + if (op->owner) { // held by someone + return op->owner->cell; + } else if (op->where) { // on the ground + return op->where; + } else if (op->parentob) { // inside another object + object_t *outerob; + // get outside object + outerob = getoutercontainerop(op); + return getoblocation(outerob); + } + // in a dummy cell + return NULL; } char *getobname(object_t *o, char *buf, int count) { @@ -4004,6 +4100,8 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan int hasunknownmod = B_FALSE; cell_t *where; int no_a = B_FALSE; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; // default to normal name if (hasflag(o->flags, F_VENDITEM)) { @@ -4404,7 +4502,7 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan // are all of the brand flags known? for (brf = br->flags->first ; brf ; brf = brf->next) { int i; - getflags(o->flags, brf->id, F_NONE); + getflags(o->flags, retflag, &nretflags, brf->id, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if (f->lifetime == FROMBRAND) { @@ -6567,7 +6665,7 @@ void initobjects(void) { addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); // l3 - addot(OT_S_POISONBOLT, "poison bolt", "Fires a glob of venom at the target.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addot(OT_S_POISONBOLT, "venom bolt", "Fires a glob of venom at the target.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); @@ -6597,27 +6695,27 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); + // l5 addot(OT_S_ANIMATEDEAD, "animate dead", "Imbues nearby corpses with life, creating an undead zombie.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); - addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 5, NA, NA, NULL); // TODO: should be "castnearob ot_corpse" addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL); - // l5 - addot(OT_S_FEEBLEMIND, "feeblemind", "Temporarily lowers the target's intelligence to that of an animal.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addot(OT_S_FEEBLEMIND, "brain freeze", "Temporarily lowers the target's intelligence to that of an animal.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_ENCHANTMENT, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 5, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); - // l7 + // l6 addot(OT_S_POSSESSION, "possession", "Completely possess an enemy, moving your consciousness into their body.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); - addflag(lastot->flags, F_SPELLLEVEL, 7, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 6, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); - // l8 addot(OT_S_INFINITEDEATH, "infinite death", "Annihilates all nearby life, including the caster!", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); - addflag(lastot->flags, F_SPELLLEVEL, 8, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 6, NA, NA, NULL); addflag(lastot->flags, F_CASTINGTIME, 2, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL); /////////////////// @@ -6635,35 +6733,36 @@ void initobjects(void) { addot(OT_S_MAPPING, "sense surroundings", "Magically imbues the caster with a map of his/her surroundings.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINATION, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); + // l3 addot(OT_S_SEEINVIS, "see invisible", "Allows the caster to see invisible creatures.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINATION, NA, NA, NULL); - addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL); addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL); addot(OT_S_DETECTOBS, "detect objects", "Senses objects near the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINATION, NA, NA, NULL); - addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); - // l3 + // l4 addot(OT_S_DETECTAURA, "detect aura", "Senses holiness or evil near the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINATION, NA, NA, NULL); - addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); addot(OT_S_LORE, "lore", "Obtain knowledge about any one species.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINATION, NA, NA, NULL); - addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL); addot(OT_S_REVEALHIDDEN, "reveal hidden", "Reveals hidden doors or invisible creatures in the caster's line of sight.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINATION, NA, NA, NULL); - addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); - // l4 + addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); + // l5 addot(OT_S_DETECTMAGIC, "detect magic", "Allows the caster to detect magical enchantments.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINATION, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); - addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); - // l8 + addflag(lastot->flags, F_SPELLLEVEL, 5, NA, NA, NULL); + // l6 addot(OT_S_IDENTIFY, "identification", "Completely identifies any one item.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINATION, NA, NA, NULL); - addflag(lastot->flags, F_SPELLLEVEL, 8, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 6, NA, NA, NULL); /////////////////// // enchantment @@ -6671,14 +6770,14 @@ void initobjects(void) { // l7 addot(OT_S_ENCHANT, "enchantment", "Magically enhances a weapon or piece of armour.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_ENCHANTMENT, NA, NA, NULL); - addflag(lastot->flags, F_SPELLLEVEL, 7, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 6, NA, NA, NULL); // TODO: hardcode how ai casts this spell /////////////////// // elemental - air /////////////////// // l1 - addot(OT_S_MIST, "obscuring mist", "Hides the caster from view with a thick cloud of mist.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addot(OT_S_MIST, "pea soup", "Hides the caster from view with a thick cloud of mist.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_AIR, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); @@ -6731,7 +6830,7 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_NEED, NA, NULL); // l5 - addot(OT_S_CHAINLIGHTNING, "chain lightning", "Electricity arcs between all nearby enemies.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addot(OT_S_CHAINLIGHTNING, "chain lightning", "Electricity arcs up to 5 times between all nearby enemies. The initial arc deals 2d6 damage, the next deals 2d5 damage, etc.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_AIR, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 5, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); @@ -6747,13 +6846,13 @@ void initobjects(void) { addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); // l2 - addot(OT_S_BLADEBURN, "bladeburn", "Ignites the target's bladed weapon, causing it to temporarily deal fire damage.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addot(OT_S_BLADEBURN, "bladeburn", "Ignites the target's bladed weapon, causing it to temporarily deal fire damage. The spell's power determines how long it will last.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_ENCHANTMENT, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); - addot(OT_S_FIREDART, "flame dart", "Fires a medium-sized dart of fire, dealing 1d6+power fire damage.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addot(OT_S_FIREDART, "flame dart", "Fires a medium-sized dart of fire, dealing 1d6+^bpower^n fire damage.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); @@ -6787,7 +6886,7 @@ void initobjects(void) { // elemental - ice /////////////////// // l1 - addot(OT_S_FROSTBITE, "frostbite", "Deals minor (1d3) cold damage to a single target.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addot(OT_S_CHILL, "chill", "Deals minor (1d3) cold damage to a single target.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_COLD, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); @@ -6797,6 +6896,7 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_COLD, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL); addot(OT_S_ICEEDGE, "ice edge", "Enhances the edge of a bladed weapon with a layer of ice.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_ENCHANTMENT, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_COLD, NA, NA, NULL); @@ -6821,7 +6921,7 @@ void initobjects(void) { addflag(lastot->flags, F_AICASTTOFLEE, ST_VICTIM, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); // l4 - addot(OT_S_CHILL, "chill", "Deals 3-24 cold damage to target creature per exposed body part.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addot(OT_S_FROSTBITE, "frostbite", "Deals 3-24 cold damage to target creature per exposed body part.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_COLD, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL); @@ -6957,14 +7057,6 @@ void initobjects(void) { addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL); - addot(OT_S_HAILSTORM, "hail storm", "Creates an intense storm of hail, causing damage to all within.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); - addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); - addflag(lastot->flags, F_SPELLSCHOOL, SS_COLD, NA, NA, NULL); - addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); - addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); - addflag(lastot->flags, F_AICASTTOFLEE, ST_VICTIM, NA, NA, NULL); - addflag(lastot->flags, F_MAXPOWER, 5, NA, NA, NULL); - addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); addot(OT_S_SATEHUNGER, "sate hunger", "Immediately satisfies the hunger of one living creature.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); @@ -6980,6 +7072,15 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_NEED, NA, NULL); + // l5 + addot(OT_S_HAILSTORM, "hail storm", "Creates an intense storm of hail, causing damage to all within.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_COLD, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 5, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOFLEE, ST_VICTIM, NA, NA, NULL); + addflag(lastot->flags, F_MAXPOWER, 5, NA, NA, NULL); + addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); // l6 addot(OT_S_LIGHTNINGSTORM, "lightning storm", "Blasts all visible enemies bolts of lightning from the sky.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); @@ -6991,7 +7092,7 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLLEVEL, 6, NA, NA, NULL); addflag(lastot->flags, F_MAXPOWER, 5, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL); - addot(OT_S_FLOOD, "flood", "Converts the earth directly into water, creating a deep pool.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addot(OT_S_FLOOD, "flood", "Creates a massive ball of water.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 6, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); @@ -6999,28 +7100,29 @@ void initobjects(void) { // gravity /////////////////// // l1 - addot(OT_S_TRUESTRIKE, "true strike", "Gives the target unerring accuracy, making their attacks always hit.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addot(OT_S_TRUESTRIKE, "weapon attraction", "Gives the target unerring accuracy, making their attacks always hit.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_ENCHANTMENT, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_GRAVITY, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); addflag(lastot->flags, F_VARPOWER, B_TRUE, NA, NA, NULL); - // l3 + // l2 addot(OT_S_GRAVLOWER, "lessen gravity", "Causes the caster to fall very slowly.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_GRAVITY, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL); + // l3 + addot(OT_S_SLOW, "slowness", "Decreases the speed of the target.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addflag(lastot->flags, F_SPELLSCHOOL, SS_ENCHANTMENT, NA, NA, NULL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_GRAVITY, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOFLEE, ST_VICTIM, NA, NA, NULL); // l4 addot(OT_S_GRAVBOOST, "boost gravity", "Greatly increases gravity around the target, stopping them from moving.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_GRAVITY, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); - addot(OT_S_SLOW, "slowness", "Decreases the speed of the target.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); - addflag(lastot->flags, F_SPELLSCHOOL, SS_ENCHANTMENT, NA, NA, NULL); - addflag(lastot->flags, F_SPELLSCHOOL, SS_GRAVITY, NA, NA, NULL); - addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); - addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); - addflag(lastot->flags, F_AICASTTOFLEE, ST_VICTIM, NA, NA, NULL); addot(OT_S_LEVITATION, "levitation", "Causes the caster hover a metre above the ground.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_ENCHANTMENT, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_GRAVITY, NA, NA, NULL); @@ -7056,6 +7158,7 @@ void initobjects(void) { // l2 addot(OT_S_SPEAKDEAD, "speak with dead", "Temporarily allow a corpse to answer questions about its former life.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); addot(OT_S_SMITEEVIL, "smite evil", "Instantly deals 1-^bpower*2^n damage to evil creatures.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); @@ -7173,16 +7276,16 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL); + // l2 addot(OT_S_DARKNESS, "darkness", "Permenantly darkens the area around the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL); - addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL); addot(OT_S_MENDING, "mending", "Repairs minor damage to objects.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_ENCHANTMENT, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); - addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); - // l2 + addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); addot(OT_S_GREASE, "grease", "Creates a large pool of greasy oil.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); @@ -7197,14 +7300,20 @@ void initobjects(void) { addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, NA, NA, NULL); //addflag(lastot->flags, F_XPVAL, 50, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); - addot(OT_S_PASSWALL, "passwall", "Allows the caster to temporarily walk through walls.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addot(OT_S_PASSWALL, "passwall", "Allows the caster to temporarily walk through a single wall.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_ENCHANTMENT, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_TRANSLOCATION, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); + // l5 + addot(OT_S_GASEOUSFORM, "gaseous form", "Changes the caster into a cloud of gas.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 5, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL); // l6 - addot(OT_S_PETRIFY, "petrify", "Causes the target mosnter to turn into stone.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addot(OT_S_PETRIFY, "petrify", "Causes a living creature to turn into stone.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 6, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); @@ -7213,12 +7322,6 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLLEVEL, 6, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, 10, NA, NULL); addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, NA, NA, NULL); - // l7 - addot(OT_S_GASEOUSFORM, "gaseous form", "Changes the caster into a cloud of gas.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); - addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL); - addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); - addflag(lastot->flags, F_SPELLLEVEL, 7, NA, NA, NULL); - addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL); /////////////////// // summoning @@ -7270,21 +7373,20 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL); - // l5 addot(OT_S_DISPERSAL, "dispersal", "Scatters everything in the target cell around the area.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_TRANSLOCATION, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 5, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOFLEE, ST_VICTIM, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); - // l6 + // l5 addot(OT_S_GATE, "gate", "Creates a portal to a different dungeon level.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_TRANSLOCATION, NA, NA, NULL); - addflag(lastot->flags, F_SPELLLEVEL, 6, NA, NA, NULL); - // l9 + addflag(lastot->flags, F_SPELLLEVEL, 5, NA, NA, NULL); + // l6 addot(OT_S_PLANESHIFT, "planeshift", "Instantly transports the caster to a different plane of existence.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_TRANSLOCATION, NA, NA, NULL); - addflag(lastot->flags, F_SPELLLEVEL, 9, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 6, NA, NA, NULL); addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL); addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, NA, NA, NULL); @@ -7340,25 +7442,25 @@ void initobjects(void) { addot(OT_A_LEVELUP, "levelup", "Bestow the given xp level.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addot(OT_S_WISH, "wish", "Grants the caster any item of their choice. Beware - casting this powerful spell will reduce the caster's hit points by 50%.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); - addflag(lastot->flags, F_SPELLLEVEL, 9, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 6, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINE, NA, NA, NULL); addot(OT_S_WISHLIMITED, "limited wish", "Grants the caster a wish of their choice. Beware - casting this powerful spell will reduce the caster's hit points by 25%.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); - addflag(lastot->flags, F_SPELLLEVEL, 7, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 5, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINE, NA, NA, NULL); addot(OT_S_CONFISCATE, "confiscate", "Takes any object from the target.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINE, NA, NA, NULL); - addflag(lastot->flags, F_SPELLLEVEL, 9, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 6, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); addot(OT_S_GIFT, "gift", "Grants the target any item of their choice (with some limitations).", MT_NOTHING, 0, OC_SPELL, SZ_TINY); - addflag(lastot->flags, F_SPELLLEVEL, 9, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 6, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINE, NA, NA, NULL); addot(OT_S_CLEARLEVEL, "blank level", "Blanks out the current map.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); - addflag(lastot->flags, F_SPELLLEVEL, 9, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 6, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINE, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL); addot(OT_S_CREATEVAULT, "create vault", "Create a vault of the given type.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); - addflag(lastot->flags, F_SPELLLEVEL, 9, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 6, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINE, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL); @@ -8878,6 +8980,7 @@ void initobjects(void) { addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_UNARMED, NA, NA, NULL); addflag(lastot->flags, F_UNARMEDWEP, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_CRITCHANCE, 1, NA, NA, NULL); // this one is for the pirate addot(OT_HOOKHAND, "hook", "hook", MT_METAL, 0, OC_WEAPON, SZ_TINY); @@ -8897,6 +9000,7 @@ void initobjects(void) { 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); + addflag(lastot->flags, F_CRITCHANCE, 3, NA, NA, NULL); addot(OT_CLAWS, "claws", "claws object", MT_BONE, 0, OC_WEAPON, SZ_TINY); addflag(lastot->flags, F_DAM, DT_SLASH, NA, NA, "1d2"); @@ -8910,6 +9014,7 @@ void initobjects(void) { 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); + addflag(lastot->flags, F_CRITCHANCE, 5, NA, NA, NULL); addot(OT_HOOF, "hooves", "hoof object", MT_BONE, 0, OC_WEAPON, SZ_TINY); addflag(lastot->flags, F_DAM, DT_BASH, NA, NA, "1d2"); @@ -8917,6 +9022,7 @@ void initobjects(void) { 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); + addflag(lastot->flags, F_CRITCHANCE, 5, NA, NA, NULL); addot(OT_BUTT, "headbutt", "headbutt object", MT_BONE, 0, OC_WEAPON, SZ_TINY); addflag(lastot->flags, F_DAM, DT_BASH, NA, NA, "1d2"); @@ -8924,6 +9030,7 @@ void initobjects(void) { 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); + addflag(lastot->flags, F_CRITCHANCE, 5, NA, NA, NULL); addot(OT_STING, "sting", "sting object", MT_BONE, 0, OC_WEAPON, SZ_TINY); addflag(lastot->flags, F_ATTACKVERB, NA, NA, NA, "sting"); @@ -8939,12 +9046,14 @@ void initobjects(void) { 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); + addflag(lastot->flags, F_CRITCHANCE, 5, NA, NA, NULL); addot(OT_TENTACLE, "tentacle", "tentacle object", MT_FLESH, 0, OC_WEAPON, SZ_TINY); 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); + addflag(lastot->flags, F_CRITCHANCE, 5, NA, NA, NULL); addot(OT_ZAPPER, "zapper", "zapper object", MT_NOTHING, 0, OC_WEAPON, SZ_TINY); addflag(lastot->flags, F_DAM, DT_ELECTRIC, NA, NA, "1d2"); @@ -9051,6 +9160,7 @@ void initobjects(void) { addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_AXES, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, 9, NA, NULL); + addflag(lastot->flags, F_CRITCHANCE, 5, NA, NA, NULL); addot(OT_BATTLEAXE, "battleaxe", "An large axe specifically designed for combat.", MT_METAL, 8, OC_WEAPON, SZ_MEDIUM); addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); addflag(lastot->flags, F_DAM, DT_CHOP, NA, NA, "1d8+1"); @@ -9073,6 +9183,7 @@ void initobjects(void) { addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_AXES, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, 7, NA, NULL); + addflag(lastot->flags, F_CRITCHANCE, 5, NA, NA, NULL); addot(OT_WARAXE, "war axe", "An axe made for combat.", MT_METAL, 7, OC_WEAPON, SZ_MEDIUM); addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); addflag(lastot->flags, F_DAM, DT_CHOP, NA, NA, "1d7+1"); @@ -9090,6 +9201,7 @@ void initobjects(void) { addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_PICKLOCKS, 7, B_BLUNTONFAIL, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_SHORTBLADES, NA, NA, NULL); + addflag(lastot->flags, F_CRITCHANCE, 2, NA, NA, NULL); addot(OT_DAGGER, "dagger", "A short stabbing weapon with a pointed blade.", MT_METAL, 1, OC_WEAPON, SZ_SMALL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL); addflag(lastot->flags, F_DAM, DT_PIERCE, NA, NA, "1d4"); @@ -9099,6 +9211,7 @@ void initobjects(void) { addflag(lastot->flags, F_OBHP, 2, 2, NA, NULL); addflag(lastot->flags, F_PICKLOCKS, 7, B_BLUNTONFAIL, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_SHORTBLADES, NA, NA, NULL); + addflag(lastot->flags, F_CRITCHANCE, 2, NA, NA, NULL); addot(OT_KNIFE, "knife", "A moderately sharp stabbing tool.", MT_METAL, 0.5, OC_WEAPON, SZ_SMALL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, NULL); addflag(lastot->flags, F_DAM, DT_SLASH, NA, NA, "1d3"); @@ -9122,12 +9235,14 @@ void initobjects(void) { 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); + addflag(lastot->flags, F_CRITCHANCE, 2, NA, NA, NULL); addot(OT_RAPIER, "rapier", "A long, narrow French sword lacking a cutting edge. Made for stabbing.", MT_METAL, 3.5, OC_WEAPON, SZ_MEDIUM); addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, 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, 6, NA, NULL); + addflag(lastot->flags, F_CRITCHANCE, 3, NA, NA, NULL); addot(OT_SAI, "sai", "A dagger with two long prongs on either side, made to trap opponents' weapons.", MT_METAL, 1.5, OC_WEAPON, SZ_SMALL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 81, NA, NULL); addflag(lastot->flags, F_DAM, DT_PIERCE, NA, NA, "1d4"); @@ -9141,11 +9256,13 @@ void initobjects(void) { 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, 6, NA, NULL); + addflag(lastot->flags, F_CRITCHANCE, 5, NA, NA, NULL); addot(OT_SICKLE, "sickle", "A hand-held agricultural tool with a curved blade.", MT_METAL, 1, OC_WEAPON, SZ_SMALL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, 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); + addflag(lastot->flags, F_CRITCHANCE, 2, NA, NA, NULL); addot(OT_STEAKKNIFE, "steak knife", "A common kitchen knife.", MT_METAL, 0.2, OC_WEAPON, SZ_SMALL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, NULL); addflag(lastot->flags, F_DAM, DT_SLASH, NA, NA, "1d2"); @@ -9162,6 +9279,7 @@ void initobjects(void) { addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_LONGBLADES, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, 13, NA, NULL); + addflag(lastot->flags, F_CRITCHANCE, 5, NA, NA, NULL); addot(OT_GREATSWORD, "greatsword", "A massive two-handed sword.", MT_METAL, 10, OC_WEAPON, SZ_MEDIUM); addflag(lastot->flags, F_RARITY, H_DUNGEON, 55, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 150, NA, NA, NULL); @@ -9170,12 +9288,14 @@ void initobjects(void) { addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_LONGBLADES, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, 13, NA, NULL); + addflag(lastot->flags, F_CRITCHANCE, 7, NA, NA, NULL); addot(OT_LONGSWORD, "longsword", "Standard issue long slashing weapon.", MT_METAL, 5, OC_WEAPON, SZ_MEDIUM); addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); addflag(lastot->flags, F_DAM, DT_SLASH, NA, NA, "1d8"); 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, 10, NA, NULL); + addflag(lastot->flags, F_CRITCHANCE, 5, NA, NA, NULL); addot(OT_ORNSWORD, "ornamental sword", "A gleaming (but quite blunt) blade.", MT_METAL, 6, OC_WEAPON, SZ_MEDIUM); addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); addflag(lastot->flags, F_SHINY, B_TRUE, NA, NA, NULL); @@ -9189,12 +9309,14 @@ void initobjects(void) { addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_LONGBLADES, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, 8, NA, NULL); + addflag(lastot->flags, F_CRITCHANCE, 7, NA, NA, NULL); addot(OT_CUTLASS, "cutlass", "An accurate, light-weight pirate blade.", MT_METAL, 4, OC_WEAPON, SZ_MEDIUM); addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); addflag(lastot->flags, F_DAM, DT_SLASH, NA, NA, "1d7"); addflag(lastot->flags, F_ACCURACY, 90, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_LONGBLADES, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, 8, NA, NULL); + addflag(lastot->flags, F_CRITCHANCE, 5, NA, NA, NULL); // polearms addot(OT_GLAIVE, "glaive", "A single-edged blade attached to a long pole.", MT_METAL, 10, OC_WEAPON, SZ_HUMAN); @@ -9205,6 +9327,7 @@ void initobjects(void) { addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_POLEARMS, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, 13, NA, NULL); + addflag(lastot->flags, F_CRITCHANCE, 1, NA, NA, NULL); addot(OT_GUISARME, "guisarme", "A hooked polearm, made by attaching a hook to a spear shaft.", MT_METAL, 10, OC_WEAPON, SZ_HUMAN); addflag(lastot->flags, F_RARITY, H_DUNGEON, 67, NA, NULL); addflag(lastot->flags, F_TRIPATTACK, B_TRUE, NA, NA, NULL); @@ -9215,6 +9338,7 @@ void initobjects(void) { addflag(lastot->flags, F_USESSKILL, SK_POLEARMS, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, 13, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_DEX, 7, NA, NULL); + addflag(lastot->flags, F_CRITCHANCE, 1, NA, NA, NULL); addot(OT_HALBERD, "halberd", "A spiked axe blade mounted on a long shaft, with a hook on the back.", MT_METAL, 12, OC_WEAPON, SZ_HUMAN); addflag(lastot->flags, F_RARITY, H_DUNGEON, 71, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 130, NA, NA, NULL); @@ -9225,6 +9349,7 @@ void initobjects(void) { addflag(lastot->flags, F_USESSKILL, SK_POLEARMS, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, 13, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_DEX, 9, NA, NULL); + addflag(lastot->flags, F_CRITCHANCE, 2, NA, NA, NULL); addot(OT_LANCE, "lance", "A pole weapon designed for use while mounted.", MT_METAL, 12, OC_WEAPON, SZ_HUMAN); addflag(lastot->flags, F_RARITY, H_DUNGEON, 67, NA, NULL); addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); @@ -9233,6 +9358,7 @@ void initobjects(void) { 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, 13, NA, NULL); + addflag(lastot->flags, F_CRITCHANCE, 1, NA, NA, NULL); addot(OT_RANSEUR, "ranseur", "A long spear and cross hilt, resembling a pole-mounted sai. Good for disarming.", MT_METAL, 12, OC_WEAPON, SZ_HUMAN); addflag(lastot->flags, F_RARITY, H_DUNGEON, 67, NA, NULL); addflag(lastot->flags, F_DISARMATTACK, B_TRUE, NA, NA, NULL); @@ -9261,12 +9387,14 @@ void initobjects(void) { addflag(lastot->flags, F_OBHP, 15, 15, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_POLEARMS, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, 7, NA, NULL); + addflag(lastot->flags, F_CRITCHANCE, 1, NA, NA, NULL); addot(OT_TRIDENT, "trident", "A three-pronged stabbing weapon.", MT_METAL, 5, OC_WEAPON, SZ_HUMAN); addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, 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, 7, NA, NULL); + addflag(lastot->flags, F_CRITCHANCE, 5, NA, NA, NULL); // staves addot(OT_QUARTERSTAFF, "quarterstaff", "A long, stout pole.", MT_WOOD, 4, OC_WEAPON, SZ_HUMAN); @@ -9278,6 +9406,7 @@ void initobjects(void) { addflag(lastot->flags, F_USESSKILL, SK_STAVES, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, 7, NA, NULL); addflag(lastot->flags, F_RODSHAPED, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_CRITCHANCE, 5, NA, NA, NULL); addot(OT_BAMBOOSTAFF, "bamboo staff", "A long hard pole made from bamboo.", MT_WOOD, 3, OC_WEAPON, SZ_HUMAN); addflag(lastot->flags, F_RARITY, H_DUNGEON, 85, NA, NULL); @@ -9287,6 +9416,7 @@ void initobjects(void) { addflag(lastot->flags, F_USESSKILL, SK_STAVES, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, 6, NA, NULL); addflag(lastot->flags, F_RODSHAPED, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_CRITCHANCE, 5, NA, NA, NULL); addot(OT_BLADEDSTAFF, "bladed staff", "A long wooden pole with blades on either end.", MT_WOOD, 5, OC_WEAPON, SZ_HUMAN); addflag(lastot->flags, F_RARITY, H_DUNGEON, 85, NA, NULL); @@ -9298,6 +9428,7 @@ void initobjects(void) { addflag(lastot->flags, F_ATTREQ, A_STR, 7, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_DEX, 9, NA, NULL); addflag(lastot->flags, F_RODSHAPED, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_CRITCHANCE, 5, NA, NA, NULL); addot(OT_IRONSTAFF, "iron staff", "A long, stout metal pole.", MT_METAL, 8, OC_WEAPON, SZ_HUMAN); addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL); @@ -9308,6 +9439,7 @@ void initobjects(void) { addflag(lastot->flags, F_USESSKILL, SK_STAVES, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, 9, NA, NULL); addflag(lastot->flags, F_RODSHAPED, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_CRITCHANCE, 8, NA, NA, NULL); // clubs (bashing) @@ -9317,12 +9449,14 @@ void initobjects(void) { addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_CLUBS, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, 7, NA, NULL); + addflag(lastot->flags, F_CRITCHANCE, 5, NA, NA, NULL); addot(OT_FLAIL, "flail", "A flexible chain attached to a heavy weight.", MT_METAL, 9, OC_WEAPON, SZ_MEDIUM); addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); addflag(lastot->flags, F_DAM, DT_BASH, NA, NA, "2d4"); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_CLUBS, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, 9, NA, NULL); + addflag(lastot->flags, F_CRITCHANCE, 5, NA, NA, NULL); addot(OT_FLAILHEAVY, "heavy flail", "A flexible chain attached to a very heavy weight.", MT_METAL, 12, OC_WEAPON, SZ_MEDIUM); addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 115, NA, NA, NULL); @@ -9330,6 +9464,7 @@ void initobjects(void) { 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, 13, NA, NULL); + addflag(lastot->flags, F_CRITCHANCE, 8, NA, NA, NULL); addot(OT_GREATCLUB, "great club", "An enormous, very heavy, blunt instrument to hit things with.", MT_STONE, 15, OC_WEAPON, SZ_MEDIUM); addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 180, NA, NA, NULL); @@ -9344,6 +9479,7 @@ void initobjects(void) { addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_CLUBS, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, 9, NA, NULL); + addflag(lastot->flags, F_CRITCHANCE, 7, NA, NA, NULL); addot(OT_MORNINGSTAR, "morningstar", "A heavy, spiked mace.", MT_METAL, 12, OC_WEAPON, SZ_MEDIUM); addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 150, NA, NA, NULL); @@ -9352,6 +9488,7 @@ void initobjects(void) { addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_CLUBS, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, 13, NA, NULL); + addflag(lastot->flags, F_CRITCHANCE, 8, NA, NA, NULL); addot(OT_NUNCHAKU, "nunchaku", "Two stout sticks connected with a short or rope. Good for disarming.", MT_WOOD, 4.5, OC_WEAPON, SZ_MEDIUM); addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); addflag(lastot->flags, F_DISARMATTACK, B_TRUE, NA, NA, NULL); @@ -9359,6 +9496,7 @@ void initobjects(void) { 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, 10, NA, NULL); + addflag(lastot->flags, F_CRITCHANCE, 3, NA, NA, NULL); addot(OT_SPANNER, "spanner", "A long, heavy metal wrench.", MT_METAL, 1, OC_WEAPON, SZ_MEDIUM); addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); addflag(lastot->flags, F_DAM, DT_BASH, NA, NA, "1d4"); @@ -9474,6 +9612,7 @@ void initobjects(void) { addot(OT_ENERGYBLADE, "energy blade", "A summoned weapon made of pure magical energy.", MT_MAGIC, 0, OC_WEAPON, SZ_MEDIUM); addflag(lastot->flags, F_DAM, DT_MAGIC, NA, NA, "1d4"); // will be replaced when summoned addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL); + addflag(lastot->flags, F_CRITCHANCE, 5, NA, NA, NULL); addot(OT_HANDOFGOD, "hand of god", "The ultimate power.", MT_FLESH, 0.1, OC_WEAPON, SZ_MEDIUM); //addflag(lastot->flags, F_RARITY, H_DUNGEON, RR_UNIQUE, NA, NULL); @@ -10304,6 +10443,8 @@ void makeknown(enum OBTYPE otid) { enum FLAG fttogive[MAXPILEOBS*3]; int nobs = 0; int i; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; if (player) { // if player is holding an object of that type with F_CONFER.. IFKNOWN... and isn't known... @@ -10312,7 +10453,7 @@ void makeknown(enum OBTYPE otid) { // keep a list of objects and flags here, then give them afterwards. for (o = player->pack->first ; o ; o = o->next) { if ((o->type->id == otid) && !isknown(o)) { - getflags(o->flags, F_ACTIVATECONFER, F_EQUIPCONFER, F_HOLDCONFER, F_NONE); + getflags(o->flags, retflag, &nretflags, F_ACTIVATECONFER, F_EQUIPCONFER, F_HOLDCONFER, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; @@ -12861,7 +13002,13 @@ int readsomething(lifeform_t *lf, object_t *o) { dospelleffects(lf, OT_S_MENDING, power, NULL, oo, NULL, o->blessed, &seen, B_FALSE); } } - if (seen) makeknown(o->type->id); + if (seen) { + makeknown(o->type->id); + } else { + if (isplayer(lf) || cansee(player, lf)) nothinghappens(); + } + if (isplayer(lf)) msg("The scroll crumbles to dust."); + removeob(o, 1); } else if (o->type->obclass->id == OC_SCROLL) { // cast linked spell object_t *targob = NULL; @@ -14533,6 +14680,8 @@ void timeeffectsob(object_t *o) { object_t *sg; char obname[BUFLEN],ownername[BUFLEN]; int i; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; if (hasflag(o->flags, F_DEAD)) return; @@ -14577,7 +14726,7 @@ void timeeffectsob(object_t *o) { int nearundead = B_FALSE; // are we glowing? - getflags(o->flags, F_PRODUCESLIGHT, F_NONE); + getflags(o->flags, retflag, &nretflags, F_PRODUCESLIGHT, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if ((f->id == F_PRODUCESLIGHT) && (f->lifetime == FROMBLESSING)) { @@ -14749,7 +14898,7 @@ void timeeffectsob(object_t *o) { // check each flag for this object... - getflags(o->flags, F_ACTIVATED, F_EDIBLE, F_MATCONVERT, F_OBHPDRAIN, F_ONFIRE, F_RECHARGE, F_WALKDAM, F_WET, F_NONE); + getflags(o->flags, retflag, &nretflags, F_ACTIVATED, F_EDIBLE, F_MATCONVERT, F_OBHPDRAIN, F_ONFIRE, F_RECHARGE, F_WALKDAM, F_WET, F_NONE); for (i = 0; i < nretflags; i++) { object_t *oo,*nextoo; f = retflag[i]; @@ -15357,6 +15506,11 @@ int validateobs(void) { printf("ERROR - spell %s doesn't have F_SPELLLEVEL.\n", ot->name); goterror = B_TRUE; } + f = hasflag(ot->flags, F_SPELLLEVEL); + if (f && (f->val[0] > MAXSPELLLEV)) { + printf("ERROR - spell %s level (%d) > MAXSPELLLEVEL (%d).\n", ot->name, f->val[0], MAXSPELLLEV); + goterror = B_TRUE; + } } else if (ot->obclass->id == OC_SCROLL) { if (foundspells) { printf("ERROR in object '%s' - all Scrolls must be defined before Spells.\n", ot->name); @@ -15507,6 +15661,32 @@ int willshatter(enum MATERIAL mat) { return B_FALSE; } +int getcritchance(lifeform_t *lf, object_t *o) { + flag_t *f; + int chance = 0; + if (!o) return 0; + + f = hasflag(o->flags, F_CRITCHANCE); + if (f) { + return chance += f->val[0]; + } + + if (lf) { + enum SKILLLEVEL weplev = PR_INEPT; + skill_t *wepsk = NULL; + wepsk = getobskill(o); + if (wepsk) { + weplev = getskill(lf, wepsk->id); + if (weplev != PR_INEPT) { + chance += (weplev*5); // ie. up to 30% bonus + } + } + } + + + return chance; +} + // determine how long a conferred effect should last, based on its blessed/cursed status. // blessed: always max // uncursed: random number between min & max diff --git a/objects.h b/objects.h index b955a5b..05842fc 100644 --- a/objects.h +++ b/objects.h @@ -38,6 +38,7 @@ void colourmatchob(object_t *o, lifeform_t *lf); void copyobprops(object_t *dst, object_t *src); int countnames(char **list); int countobs(obpile_t *op, int onlyifknown); +int countobsoftype(obpile_t *op, enum OBTYPE oid); int countnoncosmeticobs(obpile_t *op, int onlyifknown); int curseob(object_t *o); void damageallobs(object_t *srcob, obpile_t *op, int howmuch, int damtype); @@ -58,6 +59,7 @@ void genhiddennames(void); object_t *getbestcontainer(obpile_t *op); int getchargeinfo(object_t *o, int *cur, int *max); int getcharges(object_t *o); +int getcritchance(lifeform_t *lf, object_t *o); int geteffecttime(int min, int max, enum BLESSTYPE isblessed); objecttype_t *getlinkspell(object_t *o); enum COLOUR getmaterialcolour(enum MATERIAL mat ); @@ -72,6 +74,7 @@ int getobspellpower(object_t *o, lifeform_t *lf); int getobvalue(object_t *o); char *getoperateverb(object_t *o); object_t *getoutercontainer(object_t *o); +object_t *getoutercontainerop(obpile_t *op); //int getobtypevalue(objecttype_t *ot); char *getaccuracyname(int accpct); object_t *getammo(object_t *gun); @@ -103,6 +106,7 @@ char *getobdesc(object_t *o, char *buf); char *getobequipinfo(object_t *o, char *buf); char *getobextrainfo(object_t *o, char *buf); cell_t *getoblocation(object_t *o); +cell_t *getobpilelocation(obpile_t *op); char *getobname(object_t *o, char *buf, int count); char *getobnametrue(object_t *o, char *buf, int count); char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wantcondition, int adjustforblind, int wantblesscurse, int showall); diff --git a/save.c b/save.c index ac1db76..5b7b550 100644 --- a/save.c +++ b/save.c @@ -329,6 +329,16 @@ map_t *loadmap(char *basefile) { fscanf(f, "%s\n",buf); } + // load room defs + fscanf(f, "nrooms:%d\n",&m->nrooms); + for (i = 0; i < m->nrooms; i++) { + fscanf(f, "%d,%d,%d,%d,%d,%s\n",&m->room[i].id, + &m->room[i].x1, &m->room[i].y1, + &m->room[i].x2, &m->room[i].y2, buf); + m->room[i].vault = findvault(buf); + } + + // load cells if (db) dblog("--> Loading map cells...\n"); fscanf(f, "cells:\n"); @@ -339,32 +349,19 @@ map_t *loadmap(char *basefile) { int celltypeid; long obid; int temphab; - int vid; + int roomid; //if (db) dblog("cell %d,%d...",x,y); // allocate this cell c = addcell(m, x, y); - /* - c = m->cell[y * m->w + x]; - c->map = m; - c->obpile = addobpile(NULL, c); - c->lf = NULL; - c->x = x; - c->y = y; - c->roomid = -1; - */ // cell info - fscanf(f, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", - &c->roomid, &celltypeid, &c->known, &c->knownglyph.ch, &c->knownglyph.colour, &c->visited, &c->lit, &c->origlit, &c->littimer,&temphab,&vid); + fscanf(f, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", + &roomid, &celltypeid, &c->known, &c->knownglyph.ch, &c->knownglyph.colour, &c->visited, &c->lit, &c->origlit, &c->littimer,&temphab); c->habitat = findhabitat(temphab); - if (vid == -1) { - c->vault = NULL; - } else { - c->vault = findvaultbyid(vid); - } + c->room = findroom(m, roomid); ct = findcelltype(celltypeid); if (ct) { @@ -878,6 +875,15 @@ int savemap(map_t *m) { } fprintf(f, "endlifeforms\n"); + // save room defs + fprintf(f, "nrooms:%d\n",m->nrooms); + for (i = 0; i < m->nrooms; i++) { + fprintf(f, "%d,%d,%d,%d,%d,%s\n",m->room[i].id, + m->room[i].x1, m->room[i].y1, + m->room[i].x2, m->room[i].y2, + m->room[i].vault ? m->room[i].vault->id : "^^^"); + } + // cells fprintf(f, "cells:\n"); for (y = 0; y < m->h; y++) { @@ -885,8 +891,8 @@ int savemap(map_t *m) { cell_t *c; c = getcellat(m, x, y); // cell info - fprintf(f, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", - c->roomid, c->type->id, c->known, c->knownglyph.ch, c->knownglyph.colour, c->visited,c->lit,c->origlit,c->littimer,c->habitat->id, c->vault ? c->vault->numid : -1); + fprintf(f, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", + c->room ? c->room->id : -1, c->type->id, c->known, c->knownglyph.ch, c->knownglyph.colour, c->visited,c->lit,c->origlit,c->littimer,c->habitat->id ); // cell objects for (o = c->obpile->first ; o ; o = o->next) { fprintf(f, "ob:%ld\n",o->id); @@ -896,6 +902,7 @@ int savemap(map_t *m) { } } + // save object definitions from map cells fprintf(f, "MAPOBS:%d\n",obcount); for (y = 0; y < m->h; y++) { diff --git a/spell.c b/spell.c index 184cf6a..92d46cc 100644 --- a/spell.c +++ b/spell.c @@ -1516,7 +1516,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef } // stealing shop items - if (isroom(user->cell) && hasobwithflagval(user->cell->obpile, F_SHOPITEM, NA, user->cell->roomid, NA, NULL)) { + if (isroom(user->cell) && hasobwithflagval(user->cell->obpile, F_SHOPITEM, NA, getroomid(user->cell), NA, NULL)) { // stealing from a shop char yn; yn = askchar("Steal something from this shop?", "yn","n", B_TRUE); @@ -1529,7 +1529,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef value = 0; for (o = user->cell->obpile->first ; o ; o = o->next) { - f = hasflagval(o->flags, F_SHOPITEM, NA, user->cell->roomid, NA, NULL); + f = hasflagval(o->flags, F_SHOPITEM, NA, getroomid(user->cell), NA, NULL); if (f) { value += f->val[0]; } @@ -1554,7 +1554,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef lifeform_t *shk; msg("You try to steal something, but fail."); // failed - shk = findshopkeeper(user->cell->map, user->cell->roomid); + shk = findshopkeeper(user->cell->map, getroomid(user->cell)); if (shk) { // doesn't need to see you - he SENSES it! say(shk, "THIEF!", SV_ROAR); fightback(shk, user); @@ -2712,7 +2712,6 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } else if (spellid == OT_S_CHILL) { char lfname[BUFLEN]; - int exposedlimbs,dam; if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE; target = targcell->lf; if (!target) { @@ -2721,23 +2720,18 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } getlfname(target, lfname); - // how many body parts are impacted? - exposedlimbs = getexposedlimbs(target); - - dam = rolldie(exposedlimbs, 3); - if (isplayer(target)) { if (isimmuneto(target->flags, DT_COLD)) { msg("You feel mildly chilly."); } else { - msg("You feel extremely cold!"); + msg("You feel very cold!"); } if (seenbyplayer) *seenbyplayer = B_TRUE; } else if (cansee(player, target)) { if (isimmuneto(target->flags, DT_COLD)) { msg("%s looks mildly chilly.", lfname); } else { - msg("%s looks extremely cold!", lfname); + msg("%s looks very cold!", lfname); } if (seenbyplayer) *seenbyplayer = B_TRUE; } @@ -2745,7 +2739,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ // target takes magical damage // always hit if (!isimmuneto(target->flags, DT_COLD)) { - losehp(target, dam, DT_COLD, caster, "a chill spell"); + losehp(target, roll("1d3"), DT_COLD, caster, "a frostbite spell"); } } else if (spellid == OT_S_COLDBURST) { int range = 1; @@ -3997,6 +3991,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } else if (spellid == OT_S_FROSTBITE) { char lfname[BUFLEN]; + int exposedlimbs,dam; if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE; target = targcell->lf; if (!target) { @@ -4005,18 +4000,23 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } getlfname(target, lfname); + // how many body parts are impacted? + exposedlimbs = getexposedlimbs(target); + + dam = rolldie(exposedlimbs, 3); + if (isplayer(target)) { if (isimmuneto(target->flags, DT_COLD)) { msg("You feel mildly chilly."); } else { - msg("You feel very cold!"); + msg("You feel extremely cold!"); } if (seenbyplayer) *seenbyplayer = B_TRUE; } else if (cansee(player, target)) { if (isimmuneto(target->flags, DT_COLD)) { msg("%s looks mildly chilly.", lfname); } else { - msg("%s looks very cold!", lfname); + msg("%s looks extremely cold!", lfname); } if (seenbyplayer) *seenbyplayer = B_TRUE; } @@ -4024,7 +4024,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ // target takes magical damage // always hit if (!isimmuneto(target->flags, DT_COLD)) { - losehp(target, roll("1d3"), DT_COLD, caster, "a frostbite spell"); + losehp(target, dam, DT_COLD, caster, "a chill spell"); } } else if (spellid == OT_S_GASEOUSFORM) { if (!target) target = caster; @@ -5097,7 +5097,6 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ newmap = addmap(); createmap(newmap, newdepth, caster->cell->map->region, NULL, D_NONE, NULL); } - // find a random cell there newcell = getrandomcell(newmap); @@ -6574,15 +6573,10 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } return B_FALSE; } else { - if (isplayer(target)) { - msg("You are stunned!"); - if (seenbyplayer) *seenbyplayer = B_TRUE; - } else if (haslos(player, target->cell)) { - getlfname(target, buf); - msg("%s is stunned!", buf); + stun(target, 2); + if (isplayer(target) || cansee(player, target)) { if (seenbyplayer) *seenbyplayer = B_TRUE; } - taketime(target, getactspeed(target)*2); } } else if (spellid == OT_S_SUCK) { if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE; diff --git a/text.c b/text.c index 9dfe624..79cf397 100644 --- a/text.c +++ b/text.c @@ -252,6 +252,44 @@ char *getdrunktext(flag_t *drunkflag) { return "??drunk??"; } +char *getinjuredbpname(enum BODYPART bp) { + switch (bp) { + case BP_HEAD: return "head"; + case BP_HANDS: return "arm"; + case BP_LEGS: return "leg"; + default: break; + } + return "body"; +} +char *getinjuryname(enum DAMTYPE dt) { + switch (dt) { + case DT_BASH: return "bruised"; + case DT_SLASH: return "bleeding"; + default: break; + + } + return "injured"; +} +char *getinjurydesc(enum BODYPART where, enum DAMTYPE dt) { + if (dt == DT_SLASH) { + if (where == BP_LEGS) { + return " (moving causes damage)"; + } else if (where == BP_HANDS) { + return " (attacking causes damage)"; + } else if (where == BP_BODY) { + return " (take extra damage from melee hits)"; + } + } else if (dt == DT_BASH) { + if (where == BP_LEGS) { + return " (penalty to movement speed)"; + } else if (where == BP_HANDS) { + return " (penalty to attack accuracy)"; + } + } + return ""; +} + + char *getrarityname(enum RARITY rr) { switch (rr) { case RR_UNIQUE: return "Unique"; diff --git a/text.h b/text.h index 78bd963..f1e7baf 100644 --- a/text.h +++ b/text.h @@ -11,6 +11,9 @@ char *getattrname(enum ATTRIB att); int gethitconferlifetime(char *text, int *min, int *max); char *getpossessive(char *text); char *getdrunktext(flag_t *drunkflag); +char *getinjuredbpname(enum BODYPART bp); +char *getinjuryname(enum DAMTYPE dt); +char *getinjurydesc(enum BODYPART bp, enum DAMTYPE dt); char *getrarityname(enum RARITY rr); char *getsizetext(enum LFSIZE sz); char *gettimetext(char *retbuf); diff --git a/vaults/jimbo.vlt b/vaults/jimbo.vlt index f0e8ea5..ed9dde8 100644 --- a/vaults/jimbo.vlt +++ b/vaults/jimbo.vlt @@ -27,6 +27,7 @@ c:ob:lit candelabrum @flags goesin:dungeon norandom +atoneof(10,1)(10,3)(10,5) ob:portal to lv1 scatter(1,1,-2,-2) ob:wooden footstool:0-3 scatter(1,1,-2,-2) ob:random food:0-2 mayrotate