diff --git a/attack.c b/attack.c index 07fe4ba..7e9e6bc 100644 --- a/attack.c +++ b/attack.c @@ -317,15 +317,17 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) { if (!force && isplayer(lf) && wepdullable(priwep) && (getattrbracket(getattr(player, A_IQ), A_IQ, NULL) >= AT_GTAVERAGE) && !lfhasflag(lf, F_RAGE)) { - char obname[BUFLEN],wepname[BUFLEN],buf[BUFLEN]; - char ch; - real_getobname(o, obname, o->amt, B_NOPREMODS, B_NOCONDITION, B_BLINDADJUST, B_NOBLESSINGS, B_NOUSED, B_NOSHOWALL); - getobname(priwep, wepname, priwep->amt); - snprintf(buf, BUFLEN, "Attacking %s might damage your %s. Proceed?", obname, noprefix(wepname)); - ch = askchar(buf, "yn","n", B_TRUE, B_FALSE); - if (ch == 'n') { - // cancel. - return B_TRUE; + if (!hasflagknown(priwep->flags, F_IMMUTABLE)) { + char obname[BUFLEN],wepname[BUFLEN],buf[BUFLEN]; + char ch; + real_getobname(o, obname, o->amt, B_NOPREMODS, B_NOCONDITION, B_BLINDADJUST, B_NOBLESSINGS, B_NOUSED, B_NOSHOWALL); + getobname(priwep, wepname, priwep->amt); + snprintf(buf, BUFLEN, "Attacking %s might damage your %s. Proceed?", obname, noprefix(wepname)); + ch = askchar(buf, "yn","n", B_TRUE, B_FALSE); + if (ch == 'n') { + // cancel. + return B_TRUE; + } } }; } else { @@ -580,7 +582,7 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) { angergodmaybe(R_GODPURITY, 50, GA_ASSAULT); switch (getalignment(attacktarget)) { case AL_EVIL: - angergodmaybe(R_GODDEATH, 20, GA_ASSAULT); // even more + //angergodmaybe(R_GODDEATH, 20, GA_ASSAULT); // even more break; case AL_GOOD: angergodmaybe(R_GODPURITY, 20, GA_ASSAULT); // even more @@ -956,7 +958,6 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) int damreducedbyarmour = 0; int backstab = B_FALSE; int prebleed = B_FALSE; - flag_t *rust; if (firstisbackstab && (i == 0)) backstab = B_TRUE; @@ -966,22 +967,14 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) } // modify for rusted weapon. - rust = hasflag(wep->flags, F_RUSTED); - if (rust) { - switch (damtype[i]) { - case DT_PIERCE: - case DT_SLASH: - if (rust->val[0] >= R_TRUSTY) { - dam[i] -= (pctof(50, dam[i])); - } else if (rust->val[0] >= R_VRUSTY) { - dam[i] -= (pctof(25, dam[i])); - } else { - dam[i] -= (pctof(10, dam[i])); - } - break; - default: - break; - } + switch (damtype[i]) { + case DT_PIERCE: + case DT_SLASH: + case DT_CHOP: + dam[i] = pctof(getrustdampct(wep), dam[i]); + break; + default: + break; } // blocked by defender's shield? @@ -1267,6 +1260,11 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) } // other effects + + if ((victim->material->id == MT_WATER) && wep && !isunarmed) { + makewet(wep, 1); + } + if (!isdead(victim) && !blocked && !dodged) { // special weapon effects, as long as you're not doing a heavy blow if (!lfhasflag(lf, F_HEAVYBLOW) && dam[0]) { @@ -1850,7 +1848,7 @@ void criticalhit(lifeform_t *lf, lifeform_t *victim, enum BODYPART hitpos, int d protected = checkcritprotection(victim,armour); takedamage(armour, dam, damtype); } - if (!protected) injure(victim, BP_BODY, damtype); + if (!protected) injure(victim, BP_BODY, damtype, IJ_NONE); break; case BP_HEAD: if (pctchance(80)) fall(victim, lf, B_TRUE); @@ -1883,7 +1881,7 @@ void criticalhit(lifeform_t *lf, lifeform_t *victim, enum BODYPART hitpos, int d takedamage(o, dam, damtype); } } else { - injure(victim, BP_HEAD, damtype); + injure(victim, BP_HEAD, damtype, IJ_NONE); } break; case BP_HANDS: @@ -1891,7 +1889,7 @@ void criticalhit(lifeform_t *lf, lifeform_t *victim, enum BODYPART hitpos, int d protected = checkcritprotection(victim,armour); takedamage(armour, dam, damtype); } - if (!protected) injure(victim, BP_HANDS, damtype); + if (!protected) injure(victim, BP_HANDS, damtype, IJ_NONE); if (onein(2)) { // drop your weapon! @@ -1915,7 +1913,7 @@ void criticalhit(lifeform_t *lf, lifeform_t *victim, enum BODYPART hitpos, int d */ takedamage(armour, dam, damtype); } else { - injure(victim, BP_LEGS, damtype); + injure(victim, BP_LEGS, damtype, IJ_NONE); } break; } @@ -1924,7 +1922,7 @@ void criticalhit(lifeform_t *lf, lifeform_t *victim, enum BODYPART hitpos, int d protected = checkcritprotection(victim,armour); takedamage(armour, dam, damtype); } - if (!protected) injure(victim, hitpos, damtype); + if (!protected) injure(victim, hitpos, damtype, IJ_NONE); } else if (damtype == DT_EXPLOSIVE) { if ((armour = getarmour(victim, hitpos)) != NULL) { int min,max; @@ -1934,7 +1932,7 @@ void criticalhit(lifeform_t *lf, lifeform_t *victim, enum BODYPART hitpos, int d limit(&min, 1, NA); takedamage(armour, rnd(min,max), DT_EXPLOSIVE); } - if (!protected) injure(victim, hitpos, damtype); + if (!protected) injure(victim, hitpos, damtype, IJ_NONE); } if (lf) { @@ -2300,7 +2298,7 @@ int getdamroll(object_t *o, lifeform_t *victim, flag_t *damflag) { int pct; sumflags(o->pile->owner->flags, F_MELEEDAMPCT, &pct, NULL, NULL); if (pct != 0) { - dam = pctof(f->val[0], dam); + dam = pctof(pct, dam); } } return dam; @@ -2529,6 +2527,7 @@ void wepeffects(flagpile_t *fp, cell_t *where, flag_t *damflag, int dam) { int i; flag_t *retflag[MAXCANDIDATES]; int nretflags = 0; + char frombuf[BUFLEN]; if (!where) return; @@ -2544,7 +2543,27 @@ void wepeffects(flagpile_t *fp, cell_t *where, flag_t *damflag, int dam) { } victim = where->lf; - getflags(fp, retflag, &nretflags, F_FLAMESTRIKE, F_HEAVYBLOW, F_HITCONFER, F_RACESLAY, F_REVENGE, F_NONE); + // calculate 'frombuf' string + strcpy(frombuf, "something unknown"); + if (wep) { + if (owner) { + char lfname[BUFLEN]; + char wepname[BUFLEN]; + getlfnamea(owner, lfname); + getobname(wep, wepname, 1); + // ie. "a goblin's poisoned short sword" + snprintf(frombuf, BUFLEN, "%s%s %s",lfname,getpossessive(lfname), wepname); + } else { + char wepname[BUFLEN]; + getobname(wep, wepname, 1); + // ie "a poisoned short sword" + snprintf(frombuf, BUFLEN, "%s", wepname); + } + } + + + + getflags(fp, retflag, &nretflags, F_FLAMESTRIKE, F_HEAVYBLOW, F_HITCONFER, F_RACESLAY, F_REVENGE, F_RUSTED, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if (f->id == F_FLAMESTRIKE) { @@ -2660,31 +2679,8 @@ void wepeffects(flagpile_t *fp, cell_t *where, flag_t *damflag, int dam) { if (fid == F_POISONED) { // need to fill in the name of what poisoned us - char frombuf[BUFLEN]; enum POISONTYPE ptype; int ppower; - if (wep) { - if (owner) { - char lfname[BUFLEN]; - char wepname[BUFLEN]; - getlfnamea(owner, lfname); - getobname(wep, wepname, 1); - // ie. "a goblin's poisoned short sword" - snprintf(frombuf, BUFLEN, "%s%s %s",lfname,getpossessive(lfname), wepname); - } else { - char wepname[BUFLEN]; - getobname(wep, wepname, 1); - // ie "a poisoned short sword" - snprintf(frombuf, BUFLEN, "%s", wepname); - } - } else { - if (strlen(ftext)) { - strcpy(frombuf, ftext); - } else { - strcpy(frombuf, "something unknown"); - } - } - if (valflag) { ptype = valflag->val[0]; @@ -2699,6 +2695,9 @@ void wepeffects(flagpile_t *fp, cell_t *where, flag_t *damflag, int dam) { ppower = 1; } + if (!wep && strlen(ftext)) { + strcpy(frombuf, ftext); + } poison(victim, howlong, ptype, ppower, frombuf, owner ? owner->race->id : R_NONE); } else { // flag values @@ -2718,7 +2717,14 @@ void wepeffects(flagpile_t *fp, cell_t *where, flag_t *damflag, int dam) { addflag(owner->flags, F_USEDPOISON, B_TRUE, NA, NA, NULL); } } - } // end if (fid == hitconfer) + } else if ((f->id == F_RUSTED) && victim ) { + int pct; + pct = f->val[0] * 10; + if (pctchance(pct)) { + poison(victim, PERMENANT, P_TETANUS, 1, frombuf, owner ? owner->race->id : R_NONE); + } + + } // end if (fid == xxx) } if (wep && owner && victim) { diff --git a/data.c b/data.c index 3cd543e..3a7464c 100644 --- a/data.c +++ b/data.c @@ -1024,6 +1024,7 @@ void initobjects(void) { addpoisontype(P_FOODBAD, "salmonella poisoning", "Poisoned", "^bYOU vomit#S violently.", OT_VOMITPOOL, 2, 33, PS_POISON, 30); addpoisontype(P_GAS, "gas inhalation", "Poisoned", "^bYOU cough#S.", OT_NONE, 1, 25, PS_POISON,0); addpoisontype(P_ROT, "the mummy's curse", "Cursed", "", OT_NONE, 0, 0, PS_CURSE, 0); + addpoisontype(P_TETANUS, "tetanus", "Sick", "^bYOUR muscles spasm violently!", OT_NONE, 0, 3, PS_DISEASE, 15); addpoisontype(P_VENOM, "venom poisoning", "Poisoned", "^bYOU cough#S up blood.", OT_BLOODSPLASH, 1, 25, PS_POISON, 0); addpoisontype(P_WEAKNESS, "weakening poison", "Poisoned", "cough", B_FALSE, 0, 0, PS_POISON, 0); @@ -1528,6 +1529,8 @@ void initobjects(void) { addflag(lastot->flags, F_DTVULN, DT_CHOP, NA, NA, NULL); addflag(lastot->flags, F_CANHAVEOBMOD, OM_MASTERWORK, 25, NA, NULL); addflag(lastot->flags, F_CANHAVEOBMOD, OM_SHODDY, 25, NA, NULL); + addflag(lastot->flags, F_GROWSTO, CT_WALLWOOD, VT_CELL, NA, NULL); + addflag(lastot->flags, F_SHRINKSTO, OT_BED, VT_OB, NA, NULL); addot(OT_DOORIRON, "iron door", "A strong iron door.", MT_METAL, 300, OC_DFEATURE, SZ_LARGE); // GLYPH here is a special case in getglyph @@ -1543,7 +1546,8 @@ void initobjects(void) { addflag(lastot->flags, F_DTIMMUNE, DT_PIERCE, NA, NA, NULL); addflag(lastot->flags, F_DTIMMUNE, DT_SLASH, NA, NA, NULL); addflag(lastot->flags, F_DTRESIST, DT_CHOP, NA, NA, NULL); - + addflag(lastot->flags, F_GROWSTO, CT_WALLMETAL, VT_CELL, NA, NULL); + addflag(lastot->flags, F_SHRINKSTO, OT_SHIELD, VT_OB, NA, NULL); addot(OT_FOUNTAIN, "fountain", "A running fountain of some kind of liquid.", MT_WATER, 20, OC_MISC, SZ_MEDIUM); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL); @@ -1559,6 +1563,7 @@ void initobjects(void) { addflag(lastot->flags, F_DTCREATEOB, DT_FIRE, 0, DT_COMPASS, "cloud of steam"); addflag(lastot->flags, F_DRINKABLE, B_TRUE, NA, B_DONTKILL, NULL); addflag(lastot->flags, F_LINKOB, OT_POT_WATER, NA, NA, NULL); + addflag(lastot->flags, F_GROWSTO, OT_WATERDEEP, VT_OB, NA, NULL); // blocks movement, but you can see and fire through them. addot(OT_GATEIRON, "iron gate", "A gate comprised of a series of vertical iron bars, raised slightly above the floor.", MT_METAL, 500, OC_DFEATURE, SZ_LARGE); @@ -1573,8 +1578,22 @@ void initobjects(void) { addflag(lastot->flags, F_DTIMMUNE, DT_PIERCE, NA, NA, NULL); addflag(lastot->flags, F_DTIMMUNE, DT_SLASH, NA, NA, NULL); addflag(lastot->flags, F_DTRESIST, DT_CHOP, NA, NA, NULL); + addflag(lastot->flags, F_GROWSTO, CT_WALLMETAL, VT_CELL, NA, NULL); + addflag(lastot->flags, F_SHRINKSTO, OT_IRONSTAFF, VT_OB, NA, NULL); + + addot(OT_GATEBONE, "bone gate", "A grisly gate created from human bones.", MT_BONE, 60, OC_DFEATURE, SZ_LARGE); + addflag(lastot->flags, F_GLYPH, C_GREY, '+', NA, NULL); + addflag(lastot->flags, F_DOOR, SZ_MIN, SZ_MAX, NA, NULL); + addflag(lastot->flags, F_IMPASSABLE, SZ_MIN, SZ_MAX, NA, NULL); + addflag(lastot->flags, F_LOCKABLE, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_OBHP, 50, 50, NA, NULL); + addflag(lastot->flags, F_SHRINKSTO, OT_BONE, VT_OB, NA, NULL); + addot(OT_GATEWOOD, "wooden gate", "A gate comprised of a series of wooden slats.", MT_WOOD, 200, OC_DFEATURE, SZ_LARGE); - addflag(lastot->flags, F_GLYPH, C_BROWN, '+', NA, NULL); + addflag(lastot->flags, F_GLYPH, C_GREY, '+', NA, NULL); addflag(lastot->flags, F_DOOR, SZ_MIN, SZ_MAX, NA, NULL); addflag(lastot->flags, F_IMPASSABLE, SZ_MIN, SZ_MAX, NA, NULL); addflag(lastot->flags, F_LOCKABLE, B_TRUE, NA, NA, NULL); @@ -1583,6 +1602,18 @@ void initobjects(void) { addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OBHP, 30, 30, NA, NULL); addflag(lastot->flags, F_DTVULN, DT_CHOP, NA, NA, NULL); + addflag(lastot->flags, F_GROWSTO, CT_WALLWOOD, VT_CELL, NA, NULL); + addflag(lastot->flags, F_SHRINKSTO, OT_BED, VT_OB, NA, NULL); + + addot(OT_FENCEBONE, "bone fence", "A tell fence created from what appear to be human bones.", MT_BONE, 150, OC_DFEATURE, SZ_LARGE); + addflag(lastot->flags, F_GLYPH, C_GREY, '/', NA, NULL); + addflag(lastot->flags, F_IMPASSABLE, SZ_MIN, SZ_MAX, NA, NULL); + addflag(lastot->flags, F_BLOCKSVIEW, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_BLOCKSLOF, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_OBHP, 50, 50, NA, NULL); + addflag(lastot->flags, F_SHRINKSTO, OT_BONE, VT_OB, NA, NULL); addot(OT_FENCEWOOD, "wooden fence", "A tell fence created from a series of upright logs of wood.", MT_WOOD, 200, OC_DFEATURE, SZ_LARGE); addflag(lastot->flags, F_IMPASSABLE, SZ_MIN, SZ_MAX, NA, NULL); @@ -1590,9 +1621,10 @@ void initobjects(void) { addflag(lastot->flags, F_BLOCKSLOF, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); - addflag(lastot->flags, F_LOCKABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OBHP, 30, 30, NA, NULL); addflag(lastot->flags, F_DTVULN, DT_CHOP, NA, NA, NULL); + addflag(lastot->flags, F_GROWSTO, CT_WALLWOOD, VT_CELL, NA, NULL); + addflag(lastot->flags, F_SHRINKSTO, OT_BED, VT_OB, NA, NULL); addot(OT_GRATINGFLOOR, "drainage grate", "A hatchway in the ground made of strong iron mesh.", MT_METAL, 40, OC_DFEATURE, SZ_MEDIUM); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_RARE, NULL); @@ -1687,6 +1719,27 @@ void initobjects(void) { // buildings + + + // baba yaga's hut + addot(OT_BABAYAGAHUT, "wooden hut", "A small wooden cabin on the ground, two chicken's legs folded underneath it.", MT_DRAGONWOOD, 1000, OC_BUILDING, SZ_LARGE); + addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_GLYPH, C_BROWN, '_', NA, NULL); + addflag(lastot->flags, F_CLIMBABLE, D_IN, NA, NA, "hut's door"); + addflag(lastot->flags, F_OPPOSITESTAIRS, OT_BYHUTDOOR, NA, NA, NULL); + killflagsofid(lastot->flags, F_SHOP); + + // the exit to baba yaga's hut + addot(OT_BYHUTDOOR, "doorway", "The front door of Baba Yaga's hut.", MT_STONE, 3000, OC_DFEATURE, SZ_HUGE); + addflag(lastot->flags, F_GLYPH, C_BROWN, '>', NA, NULL); + addflag(lastot->flags, F_CLIMBABLE, D_IN, NA, NA, "doorway"); + addflag(lastot->flags, F_OPPOSITESTAIRS, OT_BABAYAGAHUT, NA, NA, NULL); + addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_LOCKED, B_TRUE, 40, NA, NULL); + addflag(lastot->flags, F_LOCKABLE, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); + addot(OT_MOTEL, "motel", "A small structure providing cheap overnight rooms for rent", MT_METAL, 500, OC_BUILDING, SZ_LARGE); addflag(lastot->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL); addflag(lastot->flags, F_RARITY, H_CAVE, NA, RR_RARE, NULL); @@ -1857,6 +1910,7 @@ void initobjects(void) { addflag(lastot->flags, F_LINKOB, OT_POT_WATER, NA, NA, NULL); addflag(lastot->flags, F_DEEPWATER, DP_MAX, NA, NA, NULL); addflag(lastot->flags, F_ONEPERCELL, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_SHRINKSTO, NA, VT_OB, NA, "water fountain"); // traps - cell only addot(OT_TRAPARROW, "arrow trap", "A pressure plate which causes arrows to shoot at you.", MT_NOTHING, 0, OC_TRAP, SZ_SMALL); @@ -2050,6 +2104,8 @@ void initobjects(void) { addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OBHP, 80, 80, NA, NULL); addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "50-100 stones"); + addflag(lastot->flags, F_GROWSTO, OT_DUSTCLOUD, VT_OB, NA, NULL); + addflag(lastot->flags, F_SHRINKSTO, OT_STONE, VT_OB, NA, NULL); addot(OT_ICICLE, "huge icicle", "A massive ice stalacmite.", MT_ICE, 200, OC_ROCK, SZ_LARGE); addflag(lastot->flags, F_GLYPH, C_CYAN, '\'', NA, NULL); @@ -2059,6 +2115,7 @@ void initobjects(void) { addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OBHP, 80, 80, NA, NULL); + addflag(lastot->flags, F_SHRINKSTO, OT_ICESHEET, VT_OB, NA, NULL); addot(OT_STATUE, "statue", "A stone statue of a monster.", MT_STONE, 80, OC_ROCK, SZ_HUMAN); addflag(lastot->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, ""); @@ -2176,6 +2233,7 @@ void initobjects(void) { addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_POWDER, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_FEELTEXT, NA, NA, NA, "some ash"); + addflag(lastot->flags, F_GROWSTO, OT_DUSTCLOUD, VT_OB, NA, NULL); addot(OT_ASHCONCEAL, "pile of concealing powder", "A pile of ash.", MT_STONE, 0.1, OC_ROCK, SZ_TINY); addflag(lastot->flags, F_GLYPH, NA, ',', NA, NULL); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, ""); @@ -2187,6 +2245,7 @@ void initobjects(void) { addflag(lastot->flags, F_FEELTEXT, NA, NA, NA, "some ash"); addflag(lastot->flags, F_AIFLEEITEM, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_VALUE, 80, NA, NA, NULL); + addflag(lastot->flags, F_GROWSTO, OT_DUSTCLOUD, VT_OB, NA, NULL); addot(OT_ASHEXPLODE, "pile of exploding powder", "A pile of ash.", MT_STONE, 0.1, OC_ROCK, SZ_TINY); addflag(lastot->flags, F_GLYPH, NA, ',', NA, NULL); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, ""); @@ -2198,6 +2257,7 @@ void initobjects(void) { addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, "pile of ash"); addflag(lastot->flags, F_FEELTEXT, NA, NA, NA, "some ash"); addflag(lastot->flags, F_VALUE, 100, NA, NA, NULL); + addflag(lastot->flags, F_GROWSTO, OT_DUSTCLOUD, VT_OB, NA, NULL); addot(OT_ASHINVIS, "pile of prankster's dust", "A pile of ash.", MT_STONE, 0.1, OC_ROCK, SZ_TINY); addflag(lastot->flags, F_GLYPH, NA, ',', NA, NULL); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, ""); @@ -2209,6 +2269,7 @@ void initobjects(void) { addflag(lastot->flags, F_FEELTEXT, NA, NA, NA, "some ash"); addflag(lastot->flags, F_AIFLEEITEM, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_VALUE, 100, NA, NA, NULL); + addflag(lastot->flags, F_GROWSTO, OT_DUSTCLOUD, VT_OB, NA, NULL); addot(OT_ASHSLEEP, "pile of sleeping powder", "A pile of ash.", MT_STONE, 0.1, OC_ROCK, SZ_TINY); addflag(lastot->flags, F_GLYPH, NA, ',', NA, NULL); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, ""); @@ -2219,6 +2280,7 @@ void initobjects(void) { addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, "pile of ash"); addflag(lastot->flags, F_FEELTEXT, NA, NA, NA, "some ash"); addflag(lastot->flags, F_VALUE, 80, NA, NA, NULL); + addflag(lastot->flags, F_GROWSTO, OT_DUSTCLOUD, VT_OB, NA, NULL); addot(OT_GEMOFSEEING, "gem of seeing", "Magically enhances your eyesight.", MT_STONE, 1, OC_ROCK, SZ_TINY); addflag(lastot->flags, F_HOLDCONFER, F_XRAYVIS, 1, NA, NULL); addflag(lastot->flags, F_HOLDCONFER, F_SEEINVIS, B_TRUE, NA, NULL); @@ -2280,6 +2342,8 @@ void initobjects(void) { addflag(lastot->flags, F_NUMAPPEAR, 1, 10, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DTVULN, DT_FIRE, NA, NA, "3d6"); + addflag(lastot->flags, F_GROWSTO, OT_SHRUB, VT_OB, NA, NULL); + addflag(lastot->flags, F_SHRINKSTO, OT_LEAF, VT_OB, NA, NULL); addot(OT_LEAF, "leaf", "A fallen leaf from a tree.", MT_PLANT, 0.01, OC_FLORA, SZ_TINY); addflag(lastot->flags, F_RARITY, H_FOREST, 100, RR_FREQUENT, ""); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, ""); @@ -2287,6 +2351,7 @@ void initobjects(void) { addflag(lastot->flags, F_NUMAPPEAR, 1, 10, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DTVULN, DT_FIRE, NA, NA, "3d6"); + addflag(lastot->flags, F_GROWSTO, OT_SHRUB, VT_OB, NA, NULL); addot(OT_MISTLETOE, "sprig of mistletoe", "A small cutting of mistletoe. Druids can sacrifice these cuttings to increase their magical reserves.", MT_PLANT, 0.01, OC_FLORA, SZ_TINY); addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, "leaf"); addflag(lastot->flags, F_RARITY, H_FOREST, 100, NA, ""); @@ -2295,6 +2360,7 @@ void initobjects(void) { addflag(lastot->flags, F_NUMAPPEAR, 1, 3, NA, NULL); addflag(lastot->flags, F_DTVULN, DT_FIRE, NA, NA, "3d6"); addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_GROWSTO, OT_SHRUB, VT_OB, NA, NULL); addot(OT_SHRUB, "shrub", "A small but dense shrub.", MT_PLANT, 50, OC_FLORA, SZ_MEDIUM); addflag(lastot->flags, F_RARITY, H_FOREST, 100, RR_FREQUENT, ""); addflag(lastot->flags, F_GLYPH, C_GREEN, '%', NA, NULL); @@ -2305,6 +2371,7 @@ void initobjects(void) { addflag(lastot->flags, F_OBHP, 20, 20, NA, NULL); addflag(lastot->flags, F_DTVULN, DT_FIRE, NA, NA, "2d6"); addflag(lastot->flags, F_DTVULN, DT_CHOP, NA, NA, NULL); + addflag(lastot->flags, F_GROWSTO, OT_TREE, VT_OB, NA, NULL); addot(OT_STUMP, "tree stump", "A large tree stump.", MT_WOOD, 150, OC_FLORA, SZ_LARGE); addflag(lastot->flags, F_RARITY, H_FOREST, 100, RR_FREQUENT, ""); addflag(lastot->flags, F_GLYPH, C_BROWN, '\'', NA, NULL); @@ -2315,6 +2382,8 @@ void initobjects(void) { addflag(lastot->flags, F_OBHP, 30, 30, NA, NULL); addflag(lastot->flags, F_DTVULN, DT_FIRE, NA, NA, "2d6"); addflag(lastot->flags, F_DTVULN, DT_CHOP, NA, NA, NULL); + addflag(lastot->flags, F_GROWSTO, OT_TREE, VT_OB, NA, NULL); + addflag(lastot->flags, F_SHRINKSTO, OT_STICK, VT_OB, NA, NULL); addot(OT_TREE, "tree", "A tree.", MT_WOOD, 200, OC_FLORA, SZ_LARGE); addflag(lastot->flags, F_RARITY, H_FOREST, 100, NA, ""); //addflag(lastot->flags, F_GLYPH, C_GREEN, '#', NA, NULL); @@ -2329,6 +2398,8 @@ void initobjects(void) { addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DTVULN, DT_FIRE, NA, NA, "2d6"); addflag(lastot->flags, F_DTVULN, DT_CHOP, NA, NA, NULL); + addflag(lastot->flags, F_GROWSTO, CT_WALLTREE, VT_CELL, NA, NULL); + addflag(lastot->flags, F_SHRINKSTO, OT_STUMP, VT_OB, NA, NULL); // food addot(OT_APPLE, "apple", "A crunchy apple.", MT_FOOD, 0.5, OC_FOOD, SZ_TINY); @@ -2382,6 +2453,7 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_FOREST, 100, RR_VERYRARE, NULL); addflag(lastot->flags, F_HOLDCONFER, F_EXTRALUCK, 1, NA, NULL); addflag(lastot->flags, F_VALUE, 300, NA, NA, ""); + addflag(lastot->flags, F_GROWSTO, OT_SHRUB, VT_OB, NA, NULL); killflagsofid(lastot->flags, F_STACKABLE); addot(OT_CURADOUGH, "loaf of curadough", "This very rare form of bread can magically heal whoever eats it, as well as lowering their metabolism for a short period afterwards.", MT_FOOD, 0.5, OC_FOOD, SZ_TINY); addflag(lastot->flags, F_GLYPH, C_YELLOW, '%', NA, NULL); @@ -2443,6 +2515,7 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_FOREST, 90, NA, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL); addflag(lastot->flags, F_NUMAPPEAR, 1, 12, NA, ""); + addflag(lastot->flags, F_GROWSTO, OT_TREE, VT_OB, NA, NULL); addot(OT_ONION, "onion", "An edible bulb, known for its irritant effects on the eyes.", MT_FOOD, 0.2, OC_FOOD, SZ_TINY); addflag(lastot->flags, F_GLYPH, C_BROWN, '%', NA, NULL); addflag(lastot->flags, F_EDIBLE, B_TRUE, 60, NA, ""); @@ -3829,6 +3902,10 @@ void initobjects(void) { addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); addflag(lastot->flags, F_PLEASESGOD, R_GODLIFE, 2, NA, NULL); // l3 + addot(OT_S_DISRUPTUNDEAD, "disrupt undead", "Disrupts the very essence of undead creatures, dealing 2-6 damage per spell power.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); + addflag(lastot->flags, F_PLEASESGOD, R_GODLIFE, 1, NA, NULL); addot(OT_S_HEALING, "healing", "Restores 10-20 health to the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "This spell heals an extra 2 damage per power level."); addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL); @@ -3838,7 +3915,7 @@ void initobjects(void) { addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); addflag(lastot->flags, F_PLEASESGOD, R_GODLIFE, 3, NA, NULL); - addot(OT_S_HOLYAURA, "holy aura", "Surrounds the target with a holy aura, causing their weapon to deal holy damage.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addot(OT_S_HOLYAURA, "holy aura", "Surrounds the target with a holy aura, causing their weapon to deal holy damage against vulnerable creatures.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL); addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); @@ -4037,7 +4114,20 @@ 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); + addot(OT_S_CREATEWATER, "create water", "Creates a large pool of shallow water.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The spell's power determines the size of the pool."); + addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); + addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOFLEE, ST_VICTIM, NA, NA, NULL); // l2 + addot(OT_S_OBJECTSHRINK, "shrink object", "Causes the target object to shrink to a tiny size.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL); + addflag(lastot->flags, F_TARGETTEDSPELL, TT_OBJECT, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); + addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); addot(OT_S_SIZEUP, "unnatural growth", "Causes the target's body to grow in size. They will become easier to hit, but deal more damage.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines how long the effect will last."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At power level V, self-targetted spells will also resize your armour."); @@ -4816,6 +4906,7 @@ void initobjects(void) { addflag(lastot->flags, F_STARTOBRND, 50, NA, NA, NULL); addflag(lastot->flags, F_STARTOBRND, 30, NA, NA, NULL); addflag(lastot->flags, F_STARTOBRND, 10, NA, NA, NULL); + addflag(lastot->flags, F_GROWSTO, OT_SACKLARGE, VT_OB, NA, NULL); addot(OT_SACKLARGE, "large sack", "A large cloth sack.", MT_CLOTH, 1, OC_TOOLS, SZ_MEDIUM); addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_UNCOMMON, NULL); @@ -4830,6 +4921,8 @@ void initobjects(void) { addflag(lastot->flags, F_STARTOBRND, 100, NA, NA, NULL); addflag(lastot->flags, F_STARTOBRND, 50, NA, NA, NULL); addflag(lastot->flags, F_STARTOBRND, 50, NA, NA, NULL); + addflag(lastot->flags, F_GROWSTO, OT_SACKHUGE, VT_OB, NA, NULL); + addflag(lastot->flags, F_SHRINKSTO, OT_SACK, VT_OB, NA, NULL); addot(OT_SACKHUGE, "huge sack", "An enormous cloth sack.", MT_CLOTH, 1, OC_TOOLS, SZ_LARGE); addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_RARE, NULL); @@ -4848,6 +4941,7 @@ void initobjects(void) { addflag(lastot->flags, F_STARTOBRND, 50, NA, NA, NULL); addflag(lastot->flags, F_STARTOBRND, 50, NA, NA, NULL); addflag(lastot->flags, F_STARTOBRND, 50, NA, NA, NULL); + addflag(lastot->flags, F_SHRINKSTO, OT_SACKLARGE, VT_OB, NA, NULL); addot(OT_BAGOFHOLDING, "bag of holding", "A magical sack which causes items placed inside it to become weightless.", MT_CLOTH, 0.5, OC_TOOLS, SZ_SMALL); @@ -4864,6 +4958,7 @@ void initobjects(void) { addflag(lastot->flags, F_STARTOBRND, 30, NA, NA, NULL); addflag(lastot->flags, F_STARTOBRND, 10, NA, NA, NULL); addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, "sack"); + addflag(lastot->flags, F_GROWSTO, OT_BAGOFHOLDINGLARGE, VT_OB, NA, NULL); addot(OT_BAGOFHOLDINGLARGE, "large bag of holding", "A large magical sack which causes items placed inside it to become weightless.", MT_CLOTH, 0.5, OC_TOOLS, SZ_MEDIUM); addflag(lastot->flags, F_RARITY, H_ALL, 80, RR_RARE, NULL); @@ -4880,6 +4975,8 @@ void initobjects(void) { addflag(lastot->flags, F_STARTOBRND, 50, NA, NA, NULL); addflag(lastot->flags, F_STARTOBRND, 50, NA, NA, NULL); addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, "large sack"); + addflag(lastot->flags, F_GROWSTO, OT_BAGOFHOLDINGHUGE, VT_OB, NA, NULL); + addflag(lastot->flags, F_SHRINKSTO, OT_BAGOFHOLDING, VT_OB, NA, NULL); addot(OT_BAGOFHOLDINGHUGE, "huge bag of holding", "An enormous magical sack which causes items placed inside it to become weightless.", MT_CLOTH, 0.5, OC_TOOLS, SZ_LARGE); addflag(lastot->flags, F_RARITY, H_ALL, 80, RR_VERYRARE, NULL); @@ -4900,6 +4997,7 @@ void initobjects(void) { addflag(lastot->flags, F_STARTOBRND, 50, NA, NA, NULL); addflag(lastot->flags, F_STARTOBRND, 50, NA, NA, NULL); addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, "huge sack"); + addflag(lastot->flags, F_SHRINKSTO, OT_BAGOFHOLDINGLARGE, VT_OB, NA, NULL); addot(OT_SAFEBOX, "safebox", "A small metal container for safely storing valuables.", MT_METAL, 2, OC_TOOLS, SZ_SMALL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 77, RR_UNCOMMON, NULL); @@ -5262,6 +5360,8 @@ void initobjects(void) { addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_SLIPPERY, 14, NA, NA, NULL); + addflag(lastot->flags, F_GROWSTO, OT_ICICLE, VT_OB, NA, NULL); + addflag(lastot->flags, F_SHRINKSTO, OT_ICECHUNK, VT_OB, NA, NULL); addot(OT_ICECHUNK, "chunk of ice", "A chunk of ice.", MT_ICE, 0.5, OC_MISC, SZ_SMALL); addflag(lastot->flags, F_EDIBLE, B_TRUE, 3, NA, NULL); addflag(lastot->flags, F_STACKABLE, NA, NA, NA, NULL); @@ -5275,6 +5375,8 @@ void initobjects(void) { addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOSHATTER, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_GROWSTO, OT_ICICLE, VT_OB, NA, NULL); + addflag(lastot->flags, F_SHRINKSTO, OT_PUDDLEWATER, VT_OB, NA, NULL); addot(OT_MELTEDWAX, "lump of melted wax", "A useless lump of melted wax.", MT_WAX, 0.1, OC_MISC, SZ_TINY); addflag(lastot->flags, F_STACKABLE, NA, NA, NA, NULL); @@ -5563,6 +5665,8 @@ void initobjects(void) { addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_HELPSREST, 15, 1, NA, NULL); + addflag(lastot->flags, F_GROWSTO, OT_DOORWOOD, VT_OB, NA, NULL); + addflag(lastot->flags, F_SHRINKSTO, OT_WOODENTABLE, VT_OB, NA, NULL); addot(OT_BOOKSHELF, "bookshelf", "A set of wooden shelves, sized for book storage.", MT_WOOD, 150, OC_FURNITURE, SZ_HUMAN); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_RARE, NULL); @@ -5627,6 +5731,8 @@ void initobjects(void) { addflag(lastot->flags, F_ONLYINROOM, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_IMPASSABLE, SZ_MIN, SZ_MAX, NA, NULL); addflag(lastot->flags, F_MAKESNOISE, 33, 1, NA, "crackling flames."); + addflag(lastot->flags, F_GROWSTO, OT_FIRELARGE, VT_OB, NA, NULL); + addflag(lastot->flags, F_SHRINKSTO, NA, VT_OB, NA, "red-hot helmet"); addot(OT_WEAPONRACK, "weapon rack", "A large matel frame, made to store weapons.", MT_METAL, 150, OC_FURNITURE, SZ_HUMAN); addflag(lastot->flags, F_RARITY, H_ALL, 80, RR_UNCOMMON, NULL); @@ -5660,6 +5766,8 @@ void initobjects(void) { addflag(lastot->flags, F_STARTOBCLASS, 50, OC_FOOD, NA, NULL); addflag(lastot->flags, F_STARTOBCLASS, 50, OC_FOOD, NA, NULL); addflag(lastot->flags, F_STARTOBCLASS, 50, OC_FOOD, NA, NULL); + addflag(lastot->flags, F_GROWSTO, OT_DOORWOOD, VT_OB, NA, NULL); + addflag(lastot->flags, F_SHRINKSTO, OT_STICK, VT_OB, NA, NULL); addot(OT_WOODENTABLE, "wooden table", "A waist-height wooden table.", MT_WOOD, 25, OC_FURNITURE, SZ_HUMAN); addflag(lastot->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL); @@ -5673,6 +5781,8 @@ void initobjects(void) { addflag(lastot->flags, F_OBHP, 10, 10, NA, NULL); addflag(lastot->flags, F_DTVULN, DT_BASH, NA, NA, NULL); addflag(lastot->flags, F_DTVULN, DT_CHOP, NA, NA, NULL); + addflag(lastot->flags, F_GROWSTO, OT_DOORWOOD, VT_OB, NA, NULL); + addflag(lastot->flags, F_SHRINKSTO, OT_WOODENSTOOL, VT_OB, NA, NULL); addot(OT_WOODENSTOOL, "wooden footstool", "A small, wooden footstool.", MT_WOOD, 5, OC_FURNITURE, SZ_MEDIUM); addflag(lastot->flags, F_RARITY, H_ALL, 83, RR_COMMON, NULL); @@ -5681,6 +5791,8 @@ void initobjects(void) { addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OBHP, 4, 4, NA, NULL); addflag(lastot->flags, F_DTVULN, DT_CHOP, NA, NA, NULL); + addflag(lastot->flags, F_GROWSTO, OT_WOODENTABLE, VT_OB, NA, NULL); + addflag(lastot->flags, F_SHRINKSTO, OT_STICK, VT_OB, NA, NULL); // trail objects addot(OT_FOOTPRINT, "footprints", "Footprints which show the passage of some kind of creature.", MT_NOTHING, 0, OC_MISC, SZ_MINI); @@ -5715,6 +5827,7 @@ void initobjects(void) { addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "!"); addflag(lastot->flags, F_CAUSESCOUGH, 18, NA, NA, NULL); + addflag(lastot->flags, F_SHRINKSTO, OT_STONE, VT_OB, NA, NULL); addot(OT_DUSTPUFF, "small dust cloud", "A small cloud of dust particles.", MT_GAS, 0, OC_EFFECT, SZ_MEDIUM); addflag(lastot->flags, F_GLYPH, C_BROWN, UNI_SHADELIGHT, NA, NULL); @@ -5739,6 +5852,7 @@ void initobjects(void) { addflag(lastot->flags, F_PRODUCESLIGHT, 10, NA, NA, NULL); addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "!"); addflag(lastot->flags, F_MAKESNOISE, 33, 3, NA, "roaring flames."); + addflag(lastot->flags, F_SHRINKSTO, OT_FIREMED, VT_OB, NA, NULL); addot(OT_FIREMED, "medium fire", "A medium-sized roaring fire.", MT_FIRE, 0, OC_EFFECT, SZ_MEDIUM); addflag(lastot->flags, F_GLYPH, C_RED, '}', NA, NULL); addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "small fire"); @@ -5751,6 +5865,8 @@ void initobjects(void) { addflag(lastot->flags, F_PRODUCESLIGHT, 7, NA, NA, NULL); addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "!"); addflag(lastot->flags, F_MAKESNOISE, 33, 2, NA, "roaring flames."); + addflag(lastot->flags, F_GROWSTO, OT_FIRELARGE, VT_OB, NA, NULL); + addflag(lastot->flags, F_SHRINKSTO, OT_FIRESMALL, VT_OB, NA, NULL); addot(OT_FIRESMALL, "small fire", "A small blaze.", MT_FIRE, 0, OC_EFFECT, SZ_SMALL); addflag(lastot->flags, F_GLYPH, C_RED, '}', NA, NULL); addflag(lastot->flags, F_OBDIETEXT, B_TRUE, NA, NA, "goes out"); @@ -5762,6 +5878,7 @@ void initobjects(void) { addflag(lastot->flags, F_PRODUCESLIGHT, 5, NA, NA, NULL); addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "!"); addflag(lastot->flags, F_MAKESNOISE, 33, 1, NA, "crackling flames."); + addflag(lastot->flags, F_GROWSTO, OT_FIREMED, VT_OB, NA, NULL); addot(OT_STEAMCLOUD, "cloud of steam", "A thick cloud of scalding steam.", MT_GAS, 0, OC_EFFECT, SZ_HUMAN); addflag(lastot->flags, F_GLYPH, C_WHITE, UNI_SHADEMED, NA, NULL); @@ -6428,6 +6545,7 @@ void initobjects(void) { addflag(lastot->flags, F_EQUIPCONFER, F_SHIELDPENALTY, 5, NA, NULL); addflag(lastot->flags, F_OBHP, 20, 20, NA, NULL); addflag(lastot->flags, F_CRITPROTECTION, 100, NA, NA, NULL); + addflag(lastot->flags, F_GROWSTO, OT_WOODENTABLE, VT_OB, NA, NULL); // similar to a buckler, but repairable, lighter, and less durable addot(OT_SHIELDHIDE, "hide shield", "A small shield constructed out of animal skin.", MT_LEATHER, 2.00, OC_ARMOUR, SZ_SMALL); addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_COMMON, NULL); @@ -6437,6 +6555,7 @@ void initobjects(void) { addflag(lastot->flags, F_EQUIPCONFER, F_SHIELDPENALTY, 5, NA, NULL); addflag(lastot->flags, F_OBHP, 18, 18, NA, NULL); addflag(lastot->flags, F_CRITPROTECTION, 100, NA, NA, NULL); + addflag(lastot->flags, F_GROWSTO, OT_CORPSE, VT_OB, NA, NULL); addot(OT_SHIELD, "shield", "A medium-sized metal shield.", MT_METAL, 4.00, OC_ARMOUR, SZ_MEDIUM); addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_UNCOMMON, NULL); addflag(lastot->flags, F_SHIELD, B_TRUE, NA, NA, NULL); @@ -6445,6 +6564,7 @@ void initobjects(void) { addflag(lastot->flags, F_EQUIPCONFER, F_SHIELDPENALTY, 15, NA, NULL); addflag(lastot->flags, F_OBHP, 30, 30, NA, NULL); addflag(lastot->flags, F_CRITPROTECTION, 100, NA, NA, NULL); + addflag(lastot->flags, F_GROWSTO, OT_SHIELDLARGE, VT_OB, NA, NULL); addot(OT_SHIELDLARGE, "large shield", "A large (if somewhat cumbersome) shield.", MT_METAL, 6.00, OC_ARMOUR, SZ_MEDIUM); addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_UNCOMMON, NULL); addflag(lastot->flags, F_SHIELD, B_TRUE, NA, NA, NULL); @@ -6452,6 +6572,8 @@ void initobjects(void) { addflag(lastot->flags, F_EQUIPCONFER, F_SHIELDPENALTY, 20, NA, NULL); addflag(lastot->flags, F_OBHP, 40, 40, NA, NULL); addflag(lastot->flags, F_CRITPROTECTION, 100, NA, NA, NULL); + addflag(lastot->flags, F_GROWSTO, OT_SHIELDTOWER, VT_OB, NA, NULL); + addflag(lastot->flags, F_SHRINKSTO, OT_SHIELD, VT_OB, NA, NULL); addot(OT_SHIELDTOWER, "tower shield", "An enormous but very cumbersome shield.", MT_METAL, 11.00, OC_ARMOUR, SZ_HUMAN); addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_RARE, NULL); addflag(lastot->flags, F_SHIELD, B_TRUE, NA, NA, NULL); @@ -6460,6 +6582,7 @@ void initobjects(void) { addflag(lastot->flags, F_EQUIPCONFER, F_SHIELDPENALTY, 30, NA, NULL); addflag(lastot->flags, F_OBHP, 50, 50, NA, NULL); addflag(lastot->flags, F_CRITPROTECTION, 100, NA, NA, NULL); + addflag(lastot->flags, F_SHRINKSTO, OT_SHIELDLARGE, VT_OB, NA, NULL); // amulets addot(OT_AMU_ANGER, "amulet of anger", "Allows its wearer to enter a state of bezerk rage at will.", MT_METAL, 0.3, OC_AMULET, SZ_TINY); @@ -8142,7 +8265,7 @@ void initrace(void) { addbehaviour(BH_SCRAWNY, "scrawny"); // givebehaviour() will modify maxhp - // unique monsters + // unique monsters / bosses addrace(R_JAILER, "jailer", 110, '@', C_MAGENTA, MT_FLESH, RC_HUMANOID, "Jailers are generally known for their surplus of brawn and utter lack of brains. This one is no different."); setbodytype(lastrace, BT_HUMANOID); addflag(lastrace->flags, F_NAME, NA, NA, NA, "Jimbo"); @@ -8179,6 +8302,78 @@ void initrace(void) { addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 3, NA, "shouts^a shout"); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); + addrace(R_BABAYAGA, "Baba Yaga", 50, '@', C_MAGENTA, MT_FLESH, RC_HUMANOID, "A hideous old hag with long, thin grey hair. Her face is covered with warts, and her few remaining teeth are filed to sharp points."); + setbodytype(lastrace, BT_HUMANOID); + addflag(lastrace->flags, F_NAME, NA, NA, NA, "Baba Yaga"); + addflag(lastrace->flags, F_UNIQUE, NA, NA, NA, NULL); + addflag(lastrace->flags, F_HOSTILE, NA, NA, NA, NULL); + addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); + addflag(lastrace->flags, F_HITDICE, 20, NA, NA, NULL); + addflag(lastrace->flags, F_TR, 20, NA, NA, NULL); + //addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); + //addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, NULL); + addflag(lastrace->flags, F_MAXATTACKS, 2, 2, NA, NULL); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 6, NA, NULL); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 6, NA, NULL); + addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 6, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_STR, AT_EXHIGH, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_AGI, AT_AVERAGE, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_IQ, AT_EXHIGH, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_WIS, AT_EXHIGH, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_CON, AT_AVERAGE, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_CHA, AT_EXLOW, NA, NULL); + addflag(lastrace->flags, F_RESISTMAG, 75, NA, NA, NULL); + addflag(lastrace->flags, F_DTRESIST, DT_FIRE, NA, NA, NULL); + addflag(lastrace->flags, F_DTRESIST, DT_COLD, NA, NA, NULL); + addflag(lastrace->flags, F_DTRESIST, DT_MAGIC, NA, NA, NULL); + addflag(lastrace->flags, F_DTRESIST, DT_POISON, NA, NA, NULL); + addflag(lastrace->flags, F_DTIMMUNE, DT_NECROTIC, NA, NA, NULL); + addflag(lastrace->flags, F_SEEINVIS, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_AWARENESS, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NOFLEE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_CANWILL, OT_A_GRAB, NA, NA, NULL); + addflag(lastrace->flags, F_CANCAST, OT_S_FEAR, NA, NA, "pw:3;"); + addflag(lastrace->flags, F_CANCAST, OT_S_WEAKEN, NA, NA, "pw:5;"); + addflag(lastrace->flags, F_CANCAST, OT_S_SUMMONANIMALSSM, 10, 10, "pw:5;count:5;"); + addflag(lastrace->flags, F_CANCAST, OT_S_SUMMONANIMALSMD, 10, 10, "pw:5;count:4;"); + addflag(lastrace->flags, F_CANCAST, OT_S_ENTANGLE, NA, NA, "pw:10;"); + addflag(lastrace->flags, F_CANCAST, OT_S_BLINK, NA, NA, "pw:6;"); + addflag(lastrace->flags, F_SPELLCASTTEXT, OT_NONE, NA, B_APPENDYOU, "grins"); + addflag(lastrace->flags, F_CASTCHANCE, 50, NA, NA, NULL); + addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 3, NA, "cackles evilly^an evil cackling"); + addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); + + + addrace(R_BABAYAGAHUT, "walking hut", 1000, '_', C_BROWN, MT_DRAGONWOOD, RC_MAGIC, "A small wooden cabin which walks around upon enormous chicken legs. It has a single doorway, lined with razor-sharp teeth."); + addbodypart(lastrace, BP_BODY, "walls"); + addbodypart(lastrace, BP_LEGS, "legs"); + addbodypart(lastrace, BP_FEET, "feet"); + addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "wooden hut"); + addflag(lastrace->flags, F_HOSTILE, NA, NA, NA, NULL); + addflag(lastrace->flags, F_SIZE, SZ_HUGE, NA, NA, NULL); + addflag(lastrace->flags, F_HITDICE, 5, NA, NA, NULL); + addflag(lastrace->flags, F_TR, 10, NA, NA, NULL); + //addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); + //addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, NULL); + addflag(lastrace->flags, F_MAXATTACKS, 1, 1, NA, NULL); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 9, NA, NULL); + addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 12, NA, NULL); + addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); + addflag(lastrace->flags, F_ACTIONSPEED, SP_SLOW, NA, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_STR, AT_HIGH, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_AGI, AT_GTAVERAGE, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_IQ, AT_EXLOW, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_WIS, AT_EXLOW, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_CON, AT_AVERAGE, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_CHA, AT_AVERAGE, NA, NULL); + addflag(lastrace->flags, F_STAYINROOM, NA, NA, NA, NULL); + addflag(lastrace->flags, F_CANWILL, OT_A_JUMP, NA, NA, NULL); + addflag(lastrace->flags, F_NOISETEXT, N_WALK, 2, NA, "^clucking"); + addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_TIMID, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); + // races / monsters // playable races addrace(R_HUMAN, "human", 75, '@', C_BROWN, MT_FLESH, RC_HUMANOID, "Your average example of the Homo Sapiens species."); @@ -8261,7 +8456,7 @@ void initrace(void) { // stats addflag(lastrace->flags, F_PLAYABLE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, AT_GTAVERAGE, NA, NULL); - addflag(lastrace->flags, F_STARTATT, A_AGI, AT_LOW, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_AGI, AT_GTAVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, AT_GTAVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_CON, AT_GTAVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_WIS, AT_LOW, NA, NULL); @@ -11582,7 +11777,7 @@ void initrace(void) { addflag(lastrace->flags, F_MORALE, 8, NA, NA, NULL); - addrace(R_SKOOB, "skoob", 40, 'g', C_WHITE, MT_ICE, RC_MAGIC, "Your typical snowman right down to the carrot nose, with just a two key differences: it is alive, and it is homocidal."); + addrace(R_SKOOB, "skoob", 40, 'g', C_WHITE, MT_WATER, RC_MAGIC, "Your typical snowman right down to the carrot nose, with just a two key differences: it is alive, and it is homocidal."); setbodytype(lastrace, BT_HUMANOID); addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "carrot"); addflag(lastrace->flags, F_BLOODOB, NA, NA, NA, "puddle of water"); @@ -13595,6 +13790,7 @@ void initrace(void) { addflag(lastrace->flags, F_SEEINDARK, 4, NA, NA, NULL); addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL); addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_WALKVERB, NA, NA, NA, "scuttle"); addrace(R_RATDIRE, "dire rat", 3, 'r', C_MAGENTA, MT_FLESH, RC_ANIMAL, "Dire rats are massive rats, larger than most dogs. Unlike dogs, dire rats are equipped with razor sharp shark-like teeth and their bite is very much worse than their bark."); setbodytype(lastrace, BT_QUADRAPED); @@ -13624,6 +13820,7 @@ void initrace(void) { addflag(lastrace->flags, F_SEEINDARK, 4, NA, NA, NULL); addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 4, NA, NA, NULL); + addflag(lastrace->flags, F_WALKVERB, NA, NA, NA, "scuttle"); addrace(R_RATPLAGUE, "plague rat", 3, 'r', C_GREEN, MT_FLESH, RC_ANIMAL, "Plague rats are named both for their infectious bite as well as the great speed at which they run."); setbodytype(lastrace, BT_QUADRAPED); @@ -13655,6 +13852,7 @@ void initrace(void) { addflag(lastrace->flags, F_SEEINDARK, 4, NA, NA, NULL); addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL); addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_WALKVERB, NA, NA, NA, "scuttle"); addrace(R_ROC, "roc", 1, 'A', C_MAGENTA, MT_FLESH, RC_ANIMAL, "Rocs are unbelievably gargantuan birds or prey, large enough to carry a fully-grown elephant. They are generally peaceful, but deadly once provoked."); // 'A' for Avian setbodytype(lastrace, BT_BIRD); @@ -14014,6 +14212,7 @@ void initrace(void) { addflag(lastrace->flags, F_HOMELEVOB, NA, NA, NA, "1-10 webs"); addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_FLEEONHPPCT, 25, NA, NA, ""); + addflag(lastrace->flags, F_WALKVERB, NA, NA, NA, "creep"); addrace(R_SPIDERFUNNELWEB, "giant funnelweb", 5, 'S', C_MAGENTA, MT_FLESH, RC_ANIMAL, "Like a giant spider... but extremely venomous."); setbodytype(lastrace, BT_SPIDER); lastrace->baseid = R_SPIDER; @@ -14050,6 +14249,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_FLEEONHPPCT, 25, NA, NA, ""); addflag(lastrace->flags, F_EATCONFER, F_DTRESIST, DT_POISON, NA, "15"); + addflag(lastrace->flags, F_WALKVERB, NA, NA, NA, "creep"); addrace(R_SPIDERREDBACK, "giant redback", 5, 'S', C_RED, MT_FLESH, RC_ANIMAL, "A version of a giant spider with a highly painful bite."); setbodytype(lastrace, BT_SPIDER); lastrace->baseid = R_SPIDER; @@ -14086,6 +14286,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_FLEEONHPPCT, 25, NA, NA, ""); addflag(lastrace->flags, F_EATCONFER, F_DTRESIST, DT_POISON, NA, "10"); + addflag(lastrace->flags, F_WALKVERB, NA, NA, NA, "creep"); addrace(R_SPIDERTOMB, "tomb spider", 5, 'S', C_BLUE, MT_FLESH, RC_ANIMAL, "Tomb spiders are truly nightmarish beings. Their skin can absorb light itself, and they can boost their own life force by consuming the flesh of their victims."); setbodytype(lastrace, BT_SPIDER); addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_RARE, NULL); @@ -14121,6 +14322,7 @@ void initrace(void) { addflag(lastrace->flags, F_FLEEONHPPCT, 25, NA, NA, ""); addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, B_COVETS, NA, NULL); + addflag(lastrace->flags, F_WALKVERB, NA, NA, NA, "creep"); addrace(R_SWAN, "swan", 1, 'c', C_WHITE, MT_FLESH, RC_ANIMAL, "A graceful waterbird."); setbodytype(lastrace, BT_BIRD); diff --git a/data/hiscores.db b/data/hiscores.db index 96e30a7..5a5ac67 100644 Binary files a/data/hiscores.db and b/data/hiscores.db differ diff --git a/defs.h b/defs.h index 9e2dd9c..15d23dd 100644 --- a/defs.h +++ b/defs.h @@ -805,6 +805,7 @@ enum CELLTYPE { CT_WALLMETAL, CT_WALLTREE, CT_WALLWOOD, + CT_WALLDWOOD, // empty CT_CORRIDOR, CT_DIRT, @@ -978,6 +979,8 @@ enum RACE { R_RANDOM, R_SPECIFIED, // unique monstesr R_JAILER, + R_BABAYAGAHUT, + R_BABAYAGA, // playable races R_ASHKARI, R_AVIAD, @@ -1325,8 +1328,10 @@ enum OBTYPE { OT_STATUE, OT_DOORWOOD, OT_DOORIRON, + OT_FENCEBONE, OT_FENCEWOOD, OT_FOUNTAIN, + OT_GATEBONE, OT_GATEIRON, OT_GATEWOOD, OT_SIGN, @@ -1343,6 +1348,8 @@ enum OBTYPE { OT_PORTAL, OT_STOMACHEXIT, // buildings - rememebr to update MAXBUILDINGTYPES! + OT_BABAYAGAHUT, + OT_BYHUTDOOR, OT_MOTEL, OT_SHOPARMOUR, OT_SHOPBOOK, @@ -1622,6 +1629,7 @@ enum OBTYPE { OT_S_TRUESTRIKE, OT_S_WHATGOESUP, // -- life magic / cleric + OT_S_DISRUPTUNDEAD, OT_S_HEALING, OT_S_HEALINGMIN, OT_S_HEALINGMAJ, @@ -1652,6 +1660,7 @@ enum OBTYPE { OT_S_TELEKINESIS, // -- modification OT_S_ANIMATESTATUE, + OT_S_CREATEWATER, // also nature OT_S_DARKNESS, OT_S_ENCHANT, OT_S_GASEOUSFORM, @@ -1663,6 +1672,7 @@ enum OBTYPE { OT_S_LIGHT, OT_S_MENDING, OT_S_OBJECTGROWTH, + OT_S_OBJECTSHRINK, OT_S_PASSWALL, OT_S_PETRIFY, OT_S_POLYMORPH, @@ -2312,6 +2322,7 @@ enum POISONTYPE { P_GAS, P_MIGRAINE, P_ROT, + P_TETANUS, P_VENOM, P_WEAKNESS, }; @@ -2367,6 +2378,10 @@ enum FLAG { F_ENCHANTABLE, // object can get +1/-1 ect F_GEM, // this object is a gem. F_GODGIFT, // this was a gift form god with race v0. + F_GROWSTO, // used for spells. v0=new oid or celltype. + // v1 = VT_OB or VT_CELL + F_SHRINKSTO, // used for spells. v0=new oid or celltype. + // v1 = VT_OB or VT_CELL F_NOSHATTER, // object will not shatter, even if it's material should. F_STACKABLE, // can stack multiple objects togethr F_NO_PLURAL, // this obname doesn't need an 's' for plurals (eg. gold, money) @@ -2379,6 +2394,7 @@ enum FLAG { // v2=regionthing ID of RT_REGIONLINK thing // text = what this is a map to ie. "the goblin caves" F_SIGNTEXT, // for 'sign' objects. f->text is what is says. + F_IMMUTABLE, // this object cannot be damaged OR repaired. F_IDWHENUSED, // fully identify an object when worn/weilded/operated/etc F_STARTBLESSED, // v0 = b_blessed or b_cursed F_REPELBLESSED, // v0 = b_blessed or b_cursed. repels other obejcts @@ -3910,6 +3926,7 @@ enum REGIONTYPE { RG_SEWER, RG_STOMACH, RG_WOODS, + RG_BABAYAGAHUT, }; enum HABITAT { @@ -3922,6 +3939,7 @@ enum HABITAT { H_SEWER = 7, H_STOMACH = 8, H_SWAMP = 9, + H_BYHUT = 10, H_ALL = 999 }; @@ -3935,6 +3953,7 @@ typedef struct regiontype_s { int deeperdir; int majorbranch; int depthmod; + int addparentdepth; struct regiontype_s *next, *prev; } regiontype_t; diff --git a/io.c b/io.c index c2d984e..3c626b6 100644 --- a/io.c +++ b/io.c @@ -313,6 +313,46 @@ void animcells(cell_t *src, cell_t **dst, int ndst, int gradual, char ch, char c needredraw = B_TRUE; } +// make all the passed cells 'flash' +void animflashcells(cell_t **cell, int ncells, int ch,int colour, char *seetext) { + glyph_t gl; + int i; + int nseen = 0; + + gl.ch = ch; + gl.colour = colour; + if (ncells == 0) return; + + // update screen + updateviewfor(cell[0]); + drawlevelfor(player); + + // hide cursor + curs_set(0); + + for (i = 0; i <= ncells; i++) { + if (haslos(player, cell[i])) { + if (colour == C_RANDOM) gl.colour = rnd(C_FIRST, C_LAST); + drawglyph(&gl, cell[i]->x - viewx, cell[i]->y - viewy); + nseen++; + } + } + + if (nseen) { + wrefresh(gamewin); + usleep(DEF_ANIMDELAY); + + if (seetext) { + msg(seetext); + more(); + } + } + // show cursor + curs_set(1); + needredraw = B_TRUE; + drawscreen(); +} + void animline(cell_t *src, cell_t *dst, int gradual, char ch, char ch2, int colour) { glyph_t gl; int i; @@ -1567,6 +1607,7 @@ int announceflaggain(lifeform_t *lf, flag_t *f) { p = readuntil(buf, f->text, '^'); msg("^%c%s%s %s!", getlfcol(lf, CC_VBAD), lfname, getpossessive(lfname), buf); donesomething = B_TRUE; + if (isplayer(lf)) more(); } break; case F_INVISIBLE: @@ -6141,8 +6182,10 @@ char *makedesc_ob(object_t *o, char *retbuf) { strncat(retbuf, "\n", HUGEBUFLEN); // been made invulnerable ? - if (hasflagknown(o->type->flags, F_INVULNERABLE) && !hasflag(o->flags, F_DAMAGABLE)) { + if (hasflagknown(o->flags, F_INVULNERABLE) && !hasflag(o->flags, F_DAMAGABLE)) { strncat(retbuf, "It is invulnerable to most damage.\n", HUGEBUFLEN); + } else if (hasflag(o->flags, F_IMMUTABLE)) { + strncat(retbuf, "Powerful magic has made its current condition permenant.\n", HUGEBUFLEN); } else { // immunities strcpy(buf, ""); @@ -6293,7 +6336,17 @@ char *makedesc_ob(object_t *o, char *retbuf) { } f = hasflag(o->flags, F_RUSTED); if (f) { - sprintf(buf, "It is rusty.\n"); + char rustbuf[BUFLEN]; + switch (f->val[0]) { + case R_TRUSTY: + strcpy(rustbuf, "thouroughly rusty"); break; + case R_VRUSTY: + strcpy(rustbuf, "very rusty"); break; + case R_RUSTY: + default: + strcpy(rustbuf, "rusty"); break; + } + sprintf(buf, "It is %s (-%d%% damage).\n", rustbuf, 100 - getrustdampct(o)); strncat(retbuf, buf, HUGEBUFLEN); } f = hasflag(o->flags, F_WATERPROOF); diff --git a/io.h b/io.h index 13b6ab3..371f391 100644 --- a/io.h +++ b/io.h @@ -5,6 +5,7 @@ void addheading(prompt_t *p, char *text); void addmsghist(char *text); void addpromptq(prompt_t *p, char *q); void anim(cell_t *src, cell_t *dst, char ch, int colour); +void animflashcells(cell_t **cell, int ncells, int ch,int colour, char *seetext); void animline(cell_t *src, cell_t *dst, int gradual, char ch, char ch2, int colour); void animcells(cell_t *src, cell_t **dst, int ndst, int gradual, char ch, char ch2, int colour); //void animradial(cell_t *src, int radius, int ch, int colour); diff --git a/lf.c b/lf.c index 5009872..03e86a1 100644 --- a/lf.c +++ b/lf.c @@ -1353,8 +1353,10 @@ int canwear(lifeform_t *lf, object_t *o, enum BODYPART where) { // paladin? if (getsubjob(lf) == SJ_PALADIN) { if (!isblessed(o) || !o->blessknown) { - reason = E_PALADIN; - return B_FALSE; + if (isarmour(o)) { + reason = E_PALADIN; + return B_FALSE; + } } } // injuries? @@ -2529,6 +2531,18 @@ int continuerepairing(lifeform_t *lf, flag_t *repairflag) { return B_FALSE; } + f = hasflag(o->flags, F_IMMUTABLE); + if (f) { + if (isplayer(lf)) { + char obname[BUFLEN]; + real_getobname(o, obname, o->amt, B_PREMODS, B_NOCONDITION, B_BLINDADJUST, B_BLESSINGS, B_NOUSED, B_NOSHOWALL); + msg("Your %s somehow resists your attempts to repair it!", noprefix(obname)); + } + killflag(repairflag); + f->known = B_TRUE; + return B_TRUE; + } + // get helper ob helpob = getworkhelpob(lf->pack, o->material->id); if (helpob) { @@ -3282,6 +3296,11 @@ void die(lifeform_t *lf) { headob = addob(corpsecell->obpile, headname); colourmatchob(headob, lf); } + + if (corpse->type->id == OT_BABAYAGAHUT) { + // link the hut to the new region. + createregionlink(corpsecell->map, corpsecell, corpse, NULL, RG_BABAYAGAHUT, corpsecell->map->region); + } } // For bones files: @@ -5145,7 +5164,6 @@ int exchangeweapon(lifeform_t *lf) { object_t *wep,*sec = NULL,*newsec = NULL; // get secondary (if available) sec = hasobwithflag(lf->pack, F_SECONDARY); - // get current weapon wep = getweapon(lf); @@ -5163,7 +5181,6 @@ int exchangeweapon(lifeform_t *lf) { if (sec) { - killflagsofid(sec->flags, F_SECONDARY); // try to weild secondary if (weild(lf, sec)) { // error @@ -5289,7 +5306,7 @@ int fall_from_air(lifeform_t *lf) { } } if (willfall) fall(lf, NULL, B_TRUE); - if (willinjure) injure(lf, getrandomcorebp(lf, NULL), DT_BASH); + if (willinjure) injure(lf, getrandomcorebp(lf, NULL), DT_BASH, IJ_NONE); if (willfall || willinjure) { return B_TRUE; } @@ -10297,6 +10314,7 @@ void givesubjob(lifeform_t *lf, enum SUBJOB sj) { } // can permenantly turn undead for 0 power. addtempflag(lf->flags, F_CANWILL, OT_S_TURNUNDEAD, NA, NA, NULL, FROMJOB); + addtempflag(lf->flags, F_LEVABIL, 5, OT_S_DISRUPTUNDEAD, NA, NULL, FROMJOB); if (isplayer(lf)) { addflag(lf->flags, F_SHORTCUT, getnextshortcut(lf), NA, NA, "turn undead"); } @@ -11325,11 +11343,13 @@ void inc_quad_range(enum QUADRANT *start, enum QUADRANT *end, int howmuch) { // where shoudl always be body, hands, legs or head // damtype should be bash or slash -int injure(lifeform_t *lf, enum BODYPART where, enum DAMTYPE damtype) { - char lfname[BUFLEN]; +// +// if forcetype is not supplied, injury type will be selected randomly. +int injure(lifeform_t *lf, enum BODYPART where, enum DAMTYPE damtype, enum INJURY forcetype) { + char lfname[BUFLEN],buf[BUFLEN]; char *desc = NULL; enum INJURY inj = IJ_NONE; - enum BODYPART bp2; + enum BODYPART bp2 = BP_NONE; object_t *wep = NULL,*o; int howlong; @@ -11375,266 +11395,300 @@ int injure(lifeform_t *lf, enum BODYPART where, enum DAMTYPE damtype) { howlong = rnd(30,80); // might be overridden depending on injury - if (damtype == DT_BASH) { - switch (where) { - case BP_BODY: - switch (rnd(1,5)) { - case 1: - inj = IJ_RIBCRACKED; desc = strdup("ribs are cracked^carrying capacity halved"); break; - case 2: - inj = IJ_RIBBROKEN; desc = strdup("ribs are broken^carrying capacity halved, -6 accuracy"); break; - case 3: - inj = IJ_TORSOBRUISED; desc = strdup("torso is bruised^-2 accuracy"); break; - case 4: - inj = IJ_TORSOBRUISEDBAD; desc = strdup("torso is badly bruised^-4 accuracy, -10% dam"); break; - case 5: - inj = IJ_WINDED; desc = strdup("stomach is winded^-1 Fitness"); howlong = rnd(3,5); break; - } - break; - case BP_HANDS: - switch (rnd(1,3)) { - case 1: - inj = IJ_FINGERBROKEN; desc = strdup("finger is broken^-2 accuracy"); break; - case 2: - inj = IJ_SHOULDERDISLOCATED; desc = strdup("shoulder is dislocated^-4 accuracy, cannot weild heavy weapons"); break; - case 3: - inj = IJ_HANDSWOLLEN; desc = strdup("hand is swollen^cannot wear/remove gloves"); break; - } - break; - case BP_HEAD: - switch (rnd(1,4)) { - case 1: - if (!eyesshaded(lf)) { - inj = IJ_BLACKEYE; - desc = strdup("eye is bruised^vision range halved"); + if (forcetype) { + inj = forcetype; + } else { + if (damtype == DT_BASH) { + switch (where) { + case BP_BODY: + switch (rnd(1,5)) { + case 1: + inj = IJ_RIBCRACKED; break; + case 2: + inj = IJ_RIBBROKEN; break; + case 3: + inj = IJ_TORSOBRUISED; break; + case 4: + inj = IJ_TORSOBRUISEDBAD; break; + case 5: + inj = IJ_WINDED; howlong = rnd(3,5); break; + } + break; + case BP_HANDS: + switch (rnd(1,3)) { + case 1: + inj = IJ_FINGERBROKEN; break; + case 2: + inj = IJ_SHOULDERDISLOCATED; break; + case 3: + inj = IJ_HANDSWOLLEN; break; + } + break; + case BP_HEAD: + switch (rnd(1,4)) { + case 1: + if (!eyesshaded(lf)) { + inj = IJ_BLACKEYE; + } + break; + case 2: + inj = IJ_CONCUSSION; + break; + case 3: + inj = IJ_WINDPIPECRUSHED; + break; + case 4: + inj = IJ_NOSEBROKEN; + break; + } + break; + case BP_LEGS: + if (onein(3)) { + inj = IJ_LEGBROKEN; + break; + } else { + switch (rnd(1,2)) { + case 1: + inj = IJ_LEGBRUISE; + break; + case 2: + inj = IJ_ANKLESWOLLEN; + break; } - break; - case 2: - inj = IJ_CONCUSSION; - desc = strdup("brain is concussed^random movement"); - break; - case 3: - inj = IJ_WINDPIPECRUSHED; - desc = strdup("windpipe is crushed^fitness penalty"); - break; - case 4: - inj = IJ_NOSEBROKEN; - desc = strdup("nose is broken^charisma penalty,reduced smell sense"); - break; - } - break; - case BP_LEGS: - if (onein(3)) { - inj = IJ_LEGBROKEN; - desc = strdup("leg is broken^movement speed greatly lowered"); break; - } else { + } + break; + case BP_TAIL: switch (rnd(1,2)) { case 1: - inj = IJ_LEGBRUISE; - desc = strdup("leg is bruised^movement speed lowered"); break; + inj = IJ_TAILBRUISED; + break; case 2: - inj = IJ_ANKLESWOLLEN; - desc = strdup("ankle is swollen^cannot wear/remove boots"); break; + inj = IJ_TAILBROKEN; + break; } - } - break; - case BP_TAIL: - switch (rnd(1,2)) { - case 1: - inj = IJ_TAILBRUISED; - desc = strdup("tail is bruised^accuracy penalty"); break; - case 2: - inj = IJ_TAILBROKEN; - desc = strdup("tail is fractured^occasional random movement"); break; - } - break; - case BP_WINGS: - inj = IJ_WINGBRUISED; - desc = strdup("wings are bruised^flight speed lowered"); break; - break; - default: break; - } - } else if (damtype == DT_SLASH) { - switch (where) { - case BP_BODY: - if (pctchance(10)) { - if (isplayer(lf)) { - msg("^BYour heart is pierced!"); - } else if (cansee(player, lf)) { - msg("^%c%s%s heart is pierced!", getlfcol(lf, CC_VBAD), lfname, getpossessive(lfname)); + break; + case BP_WINGS: + inj = IJ_WINGBRUISED; + break; + default: break; + } + } else if (damtype == DT_SLASH) { + switch (where) { + case BP_BODY: + if (pctchance(10)) { + if (isplayer(lf)) { + msg("^BYour heart is pierced!"); + } else if (cansee(player, lf)) { + msg("^%c%s%s heart is pierced!", getlfcol(lf, CC_VBAD), lfname, getpossessive(lfname)); + } + if (lf->hp > 0) { + lf->hp = 0; + } + } else { + inj = IJ_CHESTBLEED; break; } - if (lf->hp > 0) { - lf->hp = 0; + break; + case BP_HANDS: + switch (rnd(1,4)) { + case 1: + inj = IJ_HANDBLEED; break; + case 2: + inj = IJ_TENDONCUT; break; + case 3: + inj = IJ_ARTERYPIERCE; break; + case 4: // severed finger + if (onein(2)) bp2 = BP_RIGHTFINGER; + else bp2 = BP_LEFTFINGER; + if (hasbp(lf, bp2)) { + object_t *o; + addob(lf->cell->obpile, "severed finger"); + o = getequippedob(lf->pack, bp2); + addflag(lf->flags, F_NOBODYPART, bp2, B_FROMINJURY, NA, NULL); + inj = IJ_FINGERMISSING; + howlong = PERMENANT; + if (o) { + char obname[BUFLEN]; + if (isplayer(lf)) { + getobname(o,obname,o->amt); + msg("Your %s drops to the ground.",noprefix(obname)); + } else if (cansee(player, lf)) { + getobname(o,obname,o->amt); + msg("%s%s %s drops to the ground.",lfname,getpossessive(lfname),noprefix(obname)); + } + moveob(o, lf->cell->obpile, o->amt); + } + break; + } + break; } - } else { - inj = IJ_CHESTBLEED; desc = strdup("chest is bleeding^damage from enemies is increased"); break; - } - break; - case BP_HANDS: - switch (rnd(1,4)) { - case 1: - inj = IJ_HANDBLEED; desc = strdup("hand is bleeding^attacking will cause damage"); break; - case 2: - inj = IJ_TENDONCUT; desc = strdup("right flexor tendon is cut^cannot weild weapons"); break; - case 3: - inj = IJ_ARTERYPIERCE; desc = strdup("radial artery is pierced^1d8 damage per turn"); break; - case 4: // severed finger - if (onein(2)) bp2 = BP_RIGHTFINGER; - else bp2 = BP_LEFTFINGER; - if (hasbp(lf, bp2)) { - object_t *o; - char buf[BUFLEN]; - addob(lf->cell->obpile, "severed finger"); - o = getequippedob(lf->pack, bp2); - addflag(lf->flags, F_NOBODYPART, bp2, B_FROMINJURY, NA, NULL); - inj = IJ_FINGERMISSING; - sprintf(buf, "%s is severed^cannot wear rings on this hand", getbodypartname(lf, bp2)); - desc = strdup(buf); - howlong = PERMENANT; - if (o) { + break; + case BP_HEAD: + if (pctchance(10)) { + if (isplayer(lf)) { + msg("^BYour brain is ruptured!"); + } else if (cansee(player, lf)) { + msg("^%c%s%s brain ruptures!", getlfcol(lf, CC_VBAD), lfname, getpossessive(lfname)); + } + if (lf->hp > 0) lf->hp = 0; + } else { + switch (rnd(1,2)) { + case 1: + inj = IJ_EYELIDSCRAPED; + break; + case 2: + inj = IJ_EYEDESTROYED; + howlong = PERMENANT; + break; + + } + } + break; + case BP_LEGS: + switch (rnd(1,2)) { + case 1: + inj = IJ_LEGBLEED; + break; + case 2: + inj = IJ_HAMSTRUNG; + break; + } + break; + case BP_TAIL: + inj = IJ_TAILBLEED; + break; + case BP_WINGS: + switch (rnd(1,2)) { + case 1: + inj = IJ_WINGTORN; + break; + case 2: + inj = IJ_WINGBLEED; + break; + } + default: break; + } + } else if (damtype == DT_EXPLOSIVE) { + switch (where) { + case BP_BODY: + switch (rnd(1,3)) { + case 1: // collapsed lung + inj = IJ_LUNGCOLLAPSED; + break; + case 2: + inj = IJ_RIBCRACKED; break; + case 3: + inj = IJ_RIBBROKEN; break; + } + break; + case BP_HANDS: + // lose limb + if (onein(2)) bp2 = BP_WEAPON; + else bp2 = BP_SECWEAPON; + if (hasbp(lf, bp2)) { + object_t *o[2]; + enum BODYPART fingerbp; + int i; + // drop anyting in that hand + o[0] = getequippedob(lf->pack, bp2); + if (bp2 == BP_WEAPON) { + o[1] = getequippedob(lf->pack, BP_RIGHTFINGER); + fingerbp = BP_RIGHTFINGER; + } else { + o[1] = getequippedob(lf->pack, BP_LEFTFINGER); + fingerbp = BP_LEFTFINGER; + } + addflag(lf->flags, F_NOBODYPART, bp2, B_FROMINJURY, NA, NULL); + addflag(lf->flags, F_NOBODYPART, fingerbp, B_FROMINJURY, NA, NULL); + inj = IJ_HANDMISSING; + howlong = PERMENANT; + for (i = 0; i < 2; i++) { + if (o[i]) { char obname[BUFLEN]; if (isplayer(lf)) { - getobname(o,obname,o->amt); + getobname(o[i],obname,o[i]->amt); msg("Your %s drops to the ground.",noprefix(obname)); } else if (cansee(player, lf)) { - getobname(o,obname,o->amt); + char lfname[BUFLEN]; + getobname(o[i],obname,o[i]->amt); msg("%s%s %s drops to the ground.",lfname,getpossessive(lfname),noprefix(obname)); } - moveob(o, lf->cell->obpile, o->amt); + moveob(o[i], lf->cell->obpile, o[i]->amt); } - break; } - break; - } - break; - case BP_HEAD: - if (pctchance(10)) { - if (isplayer(lf)) { - msg("^BYour brain is ruptured!"); - } else if (cansee(player, lf)) { - msg("^%c%s%s brain ruptures!", getlfcol(lf, CC_VBAD), lfname, getpossessive(lfname)); } - if (lf->hp > 0) lf->hp = 0; - } else { + break; + case BP_HEAD: + // burnt eyes switch (rnd(1,2)) { - case 1: - inj = IJ_EYELIDSCRAPED; desc = strdup("eyelid is scraped^accuracy penalty"); break; - case 2: - inj = IJ_EYEDESTROYED; desc = strdup("right eye is destroyed^field of view halved"); - howlong = PERMENANT; + case 1: // ringing ears + inj = IJ_EARSRINGING; + case 2: // blinded + addtempflag(lf->flags, F_BLIND, B_TRUE, NA, NA, NULL, rnd(50,100)); break; - } - } - break; - case BP_LEGS: - switch (rnd(1,2)) { - case 1: - inj = IJ_LEGBLEED; desc = strdup("leg is bleeding^movement will cause damage"); break; - case 2: - inj = IJ_HAMSTRUNG; desc = strdup("left hamstring is torn^lower move speed, chance of falling"); - break; - } - break; - case BP_TAIL: - inj = IJ_TAILBLEED; - desc = strdup("tail is bleeding^no additional effects"); - break; - case BP_WINGS: - switch (rnd(1,2)) { - case 1: - inj = IJ_WINGTORN; - desc = strdup("wings are torn^cannot fly"); - break; - case 2: - inj = IJ_WINGBLEED; - desc = strdup("wings are bleeding^flying causes damage"); - break; - } - default: break; - } - } else if (damtype == DT_EXPLOSIVE) { - switch (where) { - case BP_BODY: - switch (rnd(1,3)) { - case 1: // collapsed lung - inj = IJ_LUNGCOLLAPSED; - desc = strdup("lungs have collapsed^lose all stamina points"); - case 2: - inj = IJ_RIBCRACKED; desc = strdup("ribs are cracked^carrying capacity halved"); break; - break; - case 3: - inj = IJ_RIBBROKEN; desc = strdup("ribs are broken^carrying capacity halved, -6 accuracy"); break; - } - break; - case BP_HANDS: - // lose limb - if (onein(2)) bp2 = BP_WEAPON; - else bp2 = BP_SECWEAPON; - if (hasbp(lf, bp2)) { - object_t *o[2]; - char buf[BUFLEN]; - enum BODYPART fingerbp; - int i; - // drop anyting in that hand - o[0] = getequippedob(lf->pack, bp2); - if (bp2 == BP_WEAPON) { - o[1] = getequippedob(lf->pack, BP_RIGHTFINGER); - fingerbp = BP_RIGHTFINGER; - } else { - o[1] = getequippedob(lf->pack, BP_LEFTFINGER); - fingerbp = BP_LEFTFINGER; - } - addflag(lf->flags, F_NOBODYPART, bp2, B_FROMINJURY, NA, NULL); - addflag(lf->flags, F_NOBODYPART, fingerbp, B_FROMINJURY, NA, NULL); - inj = IJ_HANDMISSING; - sprintf(buf, "%s is destroyed^cannot use this hand", getbodypartname(lf, bp2)); - desc = strdup(buf); + break; + case BP_LEGS: + // lose limb + break; + case BP_TAIL: + inj = IJ_TAILLACERATED; howlong = PERMENANT; - for (i = 0; i < 2; i++) { - if (o[i]) { - char obname[BUFLEN]; - if (isplayer(lf)) { - getobname(o[i],obname,o[i]->amt); - msg("Your %s drops to the ground.",noprefix(obname)); - } else if (cansee(player, lf)) { - char lfname[BUFLEN]; - getobname(o[i],obname,o[i]->amt); - msg("%s%s %s drops to the ground.",lfname,getpossessive(lfname),noprefix(obname)); - } - moveob(o[i], lf->cell->obpile, o[i]->amt); - } - } - } - break; - case BP_HEAD: - // burnt eyes - switch (rnd(1,2)) { - case 1: // ringing ears - inj = IJ_EARSRINGING; - desc = strdup("ears are ringing^cannot hear sounds"); - case 2: // blinded - addtempflag(lf->flags, F_BLIND, B_TRUE, NA, NA, NULL, rnd(50,100)); - break; - } - break; - case BP_LEGS: - // lose limb - break; - case BP_TAIL: - inj = IJ_TAILLACERATED; - desc = strdup("tail is lacerated^chance of falling during movement"); - howlong = PERMENANT; - break; - case BP_WINGS: - inj = IJ_WINGDESTROYED; - desc = strdup("wings are destroyed^cannot fly"); - howlong = PERMENANT; - break; - default: - break; + break; + case BP_WINGS: + inj = IJ_WINGDESTROYED; + howlong = PERMENANT; + break; + default: + break; + } } } + + // set description based on injury + switch (inj) { + case IJ_RIBCRACKED: desc = strdup("ribs are cracked^carrying capacity halved"); break; + case IJ_RIBBROKEN: desc = strdup("ribs are broken^carrying capacity halved, -6 accuracy"); break; + case IJ_TORSOBRUISED: desc = strdup("torso is bruised^-2 accuracy"); break; + case IJ_TORSOBRUISEDBAD: desc = strdup("torso is badly bruised^-4 accuracy, -10% dam"); break; + case IJ_WINDED: desc = strdup("stomach is winded^-1 Fitness"); break; + case IJ_BLACKEYE: desc = strdup("eye is bruised^vision range halved"); break; + case IJ_CONCUSSION: desc = strdup("brain is concussed^random movement"); break; + case IJ_WINDPIPECRUSHED: desc = strdup("windpipe is crushed^fitness penalty"); break; + case IJ_NOSEBROKEN: desc = strdup("nose is broken^charisma penalty,reduced smell sense"); + case IJ_LEGBROKEN: desc = strdup("leg is broken^movement speed greatly lowered"); break; + case IJ_LEGBRUISE: desc = strdup("leg is bruised^movement speed lowered"); break; + case IJ_ANKLESWOLLEN: desc = strdup("ankle is swollen^cannot wear/remove boots"); break; + case IJ_TAILBRUISED: desc = strdup("tail is bruised^accuracy penalty"); break; + case IJ_TAILBROKEN: desc = strdup("tail is fractured^occasional random movement"); break; + case IJ_WINGBRUISED: desc = strdup("wings are bruised^flight speed lowered"); break; + case IJ_CHESTBLEED: desc = strdup("chest is bleeding^damage from enemies is increased"); break; + case IJ_HANDBLEED: desc = strdup("hand is bleeding^attacking will cause damage"); break; + case IJ_TENDONCUT: desc = strdup("right flexor tendon is cut^cannot weild weapons"); break; + case IJ_FINGERMISSING: + sprintf(buf, "%s is severed^cannot wear rings on this hand", getbodypartname(lf, bp2)); + desc = strdup(buf); + break; + case IJ_EYELIDSCRAPED: desc = strdup("eyelid is scraped^accuracy penalty"); break; + case IJ_EYEDESTROYED: desc = strdup("right eye is destroyed^field of view halved"); break; + case IJ_LEGBLEED: desc = strdup("leg is bleeding^movement will cause damage"); break; + case IJ_HAMSTRUNG: desc = strdup("left hamstring is torn^lower move speed, chance of falling"); break; + case IJ_TAILBLEED: desc = strdup("tail is bleeding^no additional effects"); break; + case IJ_WINGTORN: desc = strdup("wings are torn^cannot fly"); break; + case IJ_WINGBLEED: desc = strdup("wings are bleeding^flying causes damage"); break; + case IJ_LUNGCOLLAPSED: desc = strdup("lungs have collapsed^lose all stamina points"); break; + case IJ_HANDMISSING: + sprintf(buf, "%s is destroyed^cannot use this hand", getbodypartname(lf, bp2)); + desc = strdup(buf); + break; + case IJ_EARSRINGING: desc = strdup("ears are ringing^cannot hear sounds"); break; + case IJ_TAILLACERATED: desc = strdup("tail is lacerated^chance of falling during movement"); break; + case IJ_WINGDESTROYED: desc = strdup("wings are destroyed^cannot fly"); break; + case IJ_HANDSWOLLEN: desc = strdup("hand is swolled^rings cannot be put on/removed"); break; + case IJ_FINGERBROKEN: desc = strdup("finger is broken^acc penalty"); break; + case IJ_SHOULDERDISLOCATED: desc = strdup("shoulder is dislocated^acc penalty, cannot use heavy weapons"); break; + case IJ_ARTERYPIERCE: break; // fatal - no description + case IJ_NONE: break; + } if (inj == IJ_NONE) { if (desc) free(desc); @@ -14840,7 +14894,7 @@ void losehpeffects(lifeform_t *lf, int dam, enum DAMTYPE damtype, lifeform_t *fr char buf[BUFLEN],lfname[BUFLEN]; getlfname(lf, lfname); if (lf->hp > 0) { - // effects based on damage type + // effects based on damage type, if lf is still alive if (damtype == DT_COLD) { int i; if (lfhasflag(lf, F_COLDBLOOD)) { @@ -14885,6 +14939,15 @@ void losehpeffects(lifeform_t *lf, int dam, enum DAMTYPE damtype, lifeform_t *fr } } } + } else if (damtype == DT_ELECTRIC) { + if (getraceclass(lf) == RC_ROBOT) { + f = hasflag(lf->flags, F_CONFUSED); + if (f) { + if (f->lifetime > 0) f->lifetime += rnd(dam, dam*2); + } else { + addtempflag(lf->flags, F_CONFUSED, B_TRUE, NA, NA, NULL, rnd(dam,dam*2)); + } + } } else if (damtype == DT_POISONGAS) { if (dam > 0) { if (!skillcheck(lf, SC_POISON, 35, 0)) { // HARD. @@ -14894,6 +14957,27 @@ void losehpeffects(lifeform_t *lf, int dam, enum DAMTYPE damtype, lifeform_t *fr } } // end if hp > 0 + // effects based on damage type, even if lf is dead + if (damtype == DT_ELECTRIC) { + if (hasobofmaterial(lf->cell->obpile, MT_WATER)) { + cell_t *retcell[MAX_MAPW*MAX_MAPH]; + int nretcells = 0; + // anyone else in the water takes damage too + if (getconnectedwatercells(lf->cell, retcell, &nretcells)) { + int i; + animflashcells(retcell, nretcells, '/', C_WHITE, "Electricity arcs through the water!"); + noise(lf->cell, NULL, NC_OTHER, SV_CAR, "arcing electricity", NULL); + for (i = 0 ; i < nretcells; i++) { + if (retcell[i]->lf && (retcell[i]->lf != lf)) { + if (!isairborne(retcell[i]->lf)) { + losehp_real(retcell[i]->lf, dam, DT_ELECTRIC, fromlf, "an electric shock", B_TRUE, NULL, B_FALSE, NULL, B_FALSE); + } + } + } + } + } + } + // special cases if (lf->race->id == R_FUNGUSDREAM) { char buf2[BUFLEN]; @@ -16141,7 +16225,7 @@ void poison(lifeform_t *lf, int howlong, enum POISONTYPE ptype, int power, char } - if (psev != PS_CURSE) { + if ((psev != PS_CURSE) && (howlong != PERMENANT)) { // adjust time based on first aid skill howlong -= getskill(lf, SK_FIRSTAID); if (howlong <= 0) { @@ -16200,7 +16284,7 @@ void poison(lifeform_t *lf, int howlong, enum POISONTYPE ptype, int power, char if (ii->val[2] < 1) ii->val[2] = 1; if (getskill(lf, SK_FIRSTAID) >= PR_BEGINNER) { ii->known = B_TRUE; - msg("^BYou feel %s coming on more quickly.", pt->name); + msg("^BYou recognise the increased onset of %s.", pt->name); } } else { char ftext[BUFLEN]; @@ -16209,7 +16293,7 @@ void poison(lifeform_t *lf, int howlong, enum POISONTYPE ptype, int power, char ii->obfrom = srcrace ? srcrace->id : NA; if (getskill(lf, SK_FIRSTAID) >= PR_BEGINNER) { ii->known = B_TRUE; - msg("^BYou feel %s coming on.", pt->name); + msg("^BYou recognise the onset of %s.", pt->name); } else { ii->known = B_FALSE; } @@ -17534,7 +17618,7 @@ int sayphrase(lifeform_t *lf, enum SAYPHRASE what, int volume, int val0, char *t // returns TRUE if something happened int scare(lifeform_t *lf, lifeform_t *scarer, int howlong, int scarerbonus) { - int nfailures = 0,nsuccesses = 0,penalty = 0,i; + int nfailures = 0,nsuccesses = 0,scareebonus = 0,i; int nchecks; if (!scarer) return B_FALSE; @@ -17555,7 +17639,7 @@ int scare(lifeform_t *lf, lifeform_t *scarer, int howlong, int scarerbonus) { // determine morale check penalty if (isbleeding(lf) || islowhp(lf)) { - penalty += 5; + scareebonus -= 5; } if (lfhasflag(lf, F_HUMANOID)) { object_t *o; @@ -17575,13 +17659,10 @@ int scare(lifeform_t *lf, lifeform_t *scarer, int howlong, int scarerbonus) { } } } - - // modify by charisma: -3 to 3 - scarerbonus += (getstatmod(lf, A_CHA) / 15); // if you have morale left, you make 3 checks. chance of not fleeing at all. // if you DONT have morale left, the first check always fails. - if (getmorale(lf)) { + if (isplayer(lf) || lfhasflag(lf, F_MORALE)) { nfailures = 0; nchecks = 3; } else { @@ -17589,8 +17670,12 @@ int scare(lifeform_t *lf, lifeform_t *scarer, int howlong, int scarerbonus) { nchecks = 2; // two checks - first one always fails. } + + // the person being scared gets a wisdom bonus + scareebonus += (getattr(lf, A_WIS)/20); + for (i = 0; i < nchecks; i++) { - if (!skillcheckvs(lf, SC_MORALE, -penalty, scarer, SC_MORALE, scarerbonus)) { + if (!skillcheckvs(lf, SC_MORALE, scareebonus, scarer, SC_MORALE, scarerbonus)) { nfailures++; } } @@ -17761,6 +17846,9 @@ void setguntarget(lifeform_t *lf, lifeform_t *targ) { void sethomeroom(lifeform_t *lf) { flag_t *retflag[MAXCANDIDATES]; int nretflags = 0,i; + + if (gamemode == GM_LOADING) return; + getflags(lf->flags, retflag, &nretflags, F_STAYINROOM, F_NONE); for (i = 0; i < nretflags; i++) { if (retflag[i]->val[1] == NA) { @@ -17950,13 +18038,21 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) { if (!retainhp) { // generate hp/maxhp from hit dice lf->maxhp = 0; - for (i = 0; i < lf->level; i++) { - int wantmax = B_FALSE; - if ((i == 0) || !isplayer(lf)){ - wantmax = B_TRUE; + if (isplayer(lf)) { + for (i = 0; i < lf->level; i++) { + int wantmax = B_FALSE; + if (i == 0) { + wantmax = B_TRUE; + } + lf->maxhp += rollhitdice(lf, wantmax); + assert(lf->maxhp > 0); + } + } else { + lf->maxhp += rollhitdice(lf, B_TRUE); + // one more hitdie for every level after the first + for (i = 1; i < lf->level; i++) { + lf->maxhp += rolldie(1, HITDIESIDES); } - lf->maxhp += rollhitdice(lf, wantmax); - assert(lf->maxhp > 0); } lf->hp = lf->maxhp; @@ -18432,7 +18528,9 @@ int getskillcheckchance(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod) { othermod -= 10; } } else if (ct == SC_MORALE) { - othermod += (getstatmod(lf, A_WIS) / 30); // ie. -1 to 1 + if (isbleeding(lf) || islowhp(lf)) { + othermod -= 5; + } } else if (ct == SC_OPENLOCKS) { enum SKILLLEVEL slev; slev = getskill(lf, SK_LOCKPICKING); @@ -19543,16 +19641,23 @@ void startlfturn(lifeform_t *lf) { pt = findpoisontype(f->val[0]); // chance of fighting it off - gets easier over time. // - if ((f->lifetime > 0) && skillcheck(lf, SC_POISON, (f->lifetime * 9), 0 )) { + if ((f->lifetime > 0) && skillcheck(lf, SC_POISON, (f->lifetime * 9), -(f->val[1]) )) { killflag(f); } else { flag_t *asleep; + int chance; int ko; // being asleep helps. asleep = hasflag(lf->flags, F_ASLEEP); ko = isunconscious(lf); // chance of losing hp - if (!ko && pctchance(pt->dampct)) { + chance = pt->dampct; + if (f->val[1] > 1) { + //+10% chance per power > 1 + chance = pctof(100 + ((f->val[1] - 1)*10), chance); + } + + if (!ko && pctchance(chance)) { char buf[BUFLEN]; if (isplayer(lf) || cansee(player, lf)) { char *p; @@ -19595,8 +19700,69 @@ void startlfturn(lifeform_t *lf) { } } - snprintf(buf, BUFLEN, "%s^from %s",pt->name, f->text); - losehp(lf, pt->dam * f->val[1], DT_DIRECT, NULL, buf); + // special case + if (pt->id == P_TETANUS) { + enum BODYPART bp,poss[MAXBODYPARTS]; + int nposs = 0; + for (bp = 0; bp < MAXBODYPARTS; bp++) { + int ok; + switch (bp) { + case BP_LEGS: + case BP_HEAD: + case BP_HANDS: + case BP_BODY: + case BP_TAIL: + case BP_WINGS: + ok = B_TRUE; + break; + default: + ok = B_FALSE; + break; + } + if (ok && hasbp(lf, bp)) { + poss[nposs++] = bp; + } + } + if (nposs) { + object_t *oo; + bp = poss[rnd(0,nposs-1)]; + switch (bp) { + case BP_LEGS: + injure(lf, bp, DT_BASH, IJ_LEGBROKEN); + break; + case BP_HEAD: break; // no bad effects + case BP_HANDS: // drop your weapon + oo = getequippedob(lf->pack, bp); + if (oo) drop(oo, oo->amt); + break; + case BP_BODY: + if (onein(2)) { + injure(lf, bp, DT_BASH, IJ_RIBCRACKED); + } else { + if (isplayer(lf)) { + msg("^BYour spine snaps!"); + } else if (cansee(player, lf)) { + char lfname[BUFLEN]; + getlfname(lf, lfname); + msg("^%c%s%s spine snaps!", getlfcol(lf, CC_VBAD), + lfname, getpossessive(lfname)); + } + losehp_real(lf, lf->maxhp, DT_DIRECT, NULL, "tetanus", B_FALSE, NULL, B_FALSE, NULL, B_FALSE); + } + break; + case BP_TAIL: + injure(lf, bp, DT_BASH, IJ_TAILBROKEN); + break; + case BP_WINGS: + injure(lf, bp, DT_SLASH, IJ_WINGTORN); + break; + default: break; + } + } + } else { + snprintf(buf, BUFLEN, "%s^from %s",pt->name, f->text); + losehp(lf, pt->dam * f->val[1], DT_DIRECT, NULL, buf); + } if (pt->vomitob != OT_NONE) { addobfast(lf->cell->obpile, pt->vomitob); @@ -21446,7 +21612,7 @@ int usestairs(lifeform_t *lf, object_t *o, int onpurpose, int climb) { killflagsofid(lf->flags, F_FALLDISTANCE); if (!isimmuneto(lf->flags, DT_FALL, B_FALSE)) { // injure legs - injure(lf, BP_LEGS, DT_BASH); + injure(lf, BP_LEGS, DT_BASH, IJ_NONE); // fall over fall(lf, NULL, B_FALSE); } @@ -22558,6 +22724,7 @@ int weild(lifeform_t *lf, object_t *o) { if (o) { getobname(o, buf, o->amt); + killflagsofid(o->flags, F_SECONDARY); } else { snprintf(buf, BUFLEN, "nothing"); } diff --git a/lf.h b/lf.h index 67ea876..7c9c63a 100644 --- a/lf.h +++ b/lf.h @@ -291,7 +291,7 @@ int hashealableinjuries(lifeform_t *lf); job_t *hasjob(lifeform_t *lf, enum JOB job); int hassubjob(lifeform_t *lf, enum SUBJOB id); void inc_quad_range(enum QUADRANT *start, enum QUADRANT *end, int howmuch); -int injure(lifeform_t *lf, enum BODYPART where, enum DAMTYPE damtype); +int injure(lifeform_t *lf, enum BODYPART where, enum DAMTYPE damtype, enum INJURY forcetype); 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); diff --git a/map.c b/map.c index 2fc5770..af18cb3 100644 --- a/map.c +++ b/map.c @@ -903,7 +903,7 @@ regionthing_t *addregionthing(regionoutline_t *ro, int depth, int x, int y, enum return rt; } -regiontype_t *addregiontype(enum REGIONTYPE id, char *name, int pluralname, enum HABITAT defaulthabitat, int maxdepth, int stairsperlev, int deeperdir, int major, int depthmod) { +regiontype_t *addregiontype(enum REGIONTYPE id, char *name, int pluralname, enum HABITAT defaulthabitat, int maxdepth, int stairsperlev, int deeperdir, int major, int depthmod, int addparentdepth) { regiontype_t *a; // add to the end of the list @@ -931,10 +931,10 @@ regiontype_t *addregiontype(enum REGIONTYPE id, char *name, int pluralname, enum a->deeperdir = deeperdir; a->majorbranch = major; a->depthmod = depthmod; + a->addparentdepth = addparentdepth; return a; } - void adjustcellglyphforlight(cell_t *c, glyph_t *g) { if (g->ch == ' ') return; switch (c->lit) { @@ -1880,6 +1880,33 @@ enum DEPTH getcellwaterdepth(cell_t *c, lifeform_t *lf) { } +// note that *ncells should be set to 0 before this function is called +int getconnectedwatercells(cell_t *c, cell_t **retcell, int *ncells) { + int d; + int i,found = B_FALSE; + + for (i = 0; i < *ncells; i++) { + if (retcell[i] == c) { + found = B_TRUE; + break; + } + } + + if (c && // not off the map + !found && // not already processed + !c->type->solid && // empty cell + hasobofmaterial(c->obpile, MT_WATER)) { // has water + retcell[*ncells] = c; + (*ncells)++; + } else { + return 0; + } + for (d = DC_N; d <= DC_NW; d++) { + getconnectedwatercells(getcellindir(c, d), retcell, ncells); // recursive call + } + return *ncells; +} + // returns the closest cell next to 'dst', when coming from 'src' // ie. if you start walking from src to dst, where will you end up? cell_t *get_closest_adjcell(cell_t *src, cell_t *dst) { @@ -2433,6 +2460,33 @@ void createborder(map_t *map, enum CELLTYPE solidtype) { } } +void createbyhut(map_t *map, int depth, map_t *parentmap, int exitdir, object_t *entryob) { + int x,y; + enum CELLTYPE emptycell,solidcell; + cell_t *c; + vault_t *v; + //object_t *o; + + // what kind of cells will 'empty' ones be? + emptycell = getmapempty(map); + solidcell = getmapsolid(map); + // fill entire maze with walls + for (y = 0; y < map->h; y++) { + for (x = 0; x < map->w; x++) { + c = addcell(map, x, y); + setcelltype(c, solidcell); + } + } + // add a random babayaga's hut vault + v = findvaultwithtag("byhut"); + assert(v); + if (createvault(map, map->nrooms, v, NULL, NULL, NULL, NULL)) { + dblog("ERROR - couldn't create byhut vault '%s' on map %s", v->id, map->name); + msg("ERROR - couldn't create byhut vault '%s' on map %s", v->id, map->name); + assert("failed to create babayaga's hut" == 0); + } +} + void createcave(map_t *map, int depth, map_t *parentmap, int exitdir, object_t *entryob) { int wantrooms = B_TRUE; int x,y,i; @@ -3192,6 +3246,9 @@ void createhabitat(map_t *map, int depth, map_t *parentmap, int exitdir, object_ case H_SWAMP: createswamp(map, depth, parentmap, exitdir, entryob); break; + case H_BYHUT: + createbyhut(map, depth, parentmap, exitdir, entryob); + break; case H_ALL: dblog("ERROR - createhabitat with invalid habitat!"); msg("ERROR - createhabitat with invalid habitat!"); @@ -4860,7 +4917,9 @@ void createregionlink(map_t *m, cell_t *c, object_t *o, char *obname, enum REGIO flag_t *f; region_t *r; int basedepth = 0; - if (newregiontype != RG_MAINDUNGEON) { + regiontype_t *nrt; + nrt = findregiontype(newregiontype); + if (nrt->addparentdepth) { basedepth = getmapdifficulty(m); } // create a new region. @@ -6342,17 +6401,19 @@ cell_t *getstairdestination(object_t *o, int *madenewmap) { if (!f) return NULL; dir = getstairdirection(o); - if ((dir != D_UP) && (dir != D_DOWN)) { + //if ((dir != D_UP) && (dir != D_DOWN)) { + if (o->type->id == OT_PORTAL) { // ie this is a portal return NULL; } else { - if (dir == D_UP) newdepth = curmap->depth - 1; - else newdepth = curmap->depth + 1; if (f->val[1] == NA) { // use same region newregion = obcell->map->region; + if (dir == D_UP) newdepth = curmap->depth - 1; + else newdepth = curmap->depth + 1; } else { newregion = findregion(f->val[1]); + newdepth = 1; } } @@ -6469,6 +6530,7 @@ void initmap(void) { addhabitat(H_SEWER, "sewer", CT_CORRIDOR, CT_WALL, 5, 50, 0, MAXVISRANGE, OT_NONE, OT_NONE); addhabitat(H_STOMACH, "stomach", CT_FLOORFLESH, CT_WALLFLESH, 5, 80, 0, MAXVISRANGE, OT_NONE, OT_NONE); addhabitat(H_SWAMP, "swamp", CT_CORRIDOR, CT_WALL, 3, 50, 0, MAXVISRANGE, OT_STAIRSUP, OT_STAIRSDOWN); + addhabitat(H_BYHUT, "babayaga's hut", CT_CORRIDOR, CT_WALLDWOOD, 0, 0, 0, MAXVISRANGE, OT_BYHUTDOOR, OT_NONE); // cell types - solid // floorheight, hp @@ -6476,6 +6538,7 @@ void initmap(void) { addcelltype(CT_WALLBRICK, "brick wall", UNI_SHADEDARK, C_ORANGE, B_SOLID, B_OPAQUE, MT_STONE, 0, 40); addcelltype(CT_WALLDIRT, "dirt wall", UNI_SHADEDARK, C_BROWN, B_SOLID, B_OPAQUE, MT_STONE, 0, 20); addcelltype(CT_WALLWOOD, "wooden wall", UNI_SOLID, C_BROWN, B_SOLID, B_OPAQUE, MT_WOOD, 0, 30); + addcelltype(CT_WALLDWOOD, "wyrmwood wall", UNI_SOLID, C_BROWN, B_SOLID, B_OPAQUE, MT_DRAGONWOOD, 0, 100); addcelltype(CT_WALLFLESH, "flesh wall", UNI_SOLID, C_RED, B_SOLID, B_OPAQUE, MT_FLESH, 0, 25); addcelltype(CT_WALLGLASS, "glass wall", UNI_SOLID, C_CYAN, B_SOLID, B_TRANS, MT_GLASS, 0, 20); //addcelltype(CT_WALLTREE, "dense bushland", UNI_SHADEDARK, C_GREEN, B_SOLID, B_OPAQUE, MT_PLANT, 0, 100); @@ -6496,18 +6559,22 @@ void initmap(void) { addcelltype(CT_VLOWFLOOR, "very low rock floor", '.', C_GREY, B_EMPTY, B_TRANS, MT_STONE, -2, -1); // region types - // name, pluralname?, defaulthab, maxdepth stairs stair major? depthmod + // name, pluralname?, defaulthab, maxdepth stairs stair major? depthmod inherit_parent_depth? // perlev dir - addregiontype(RG_WORLDMAP, "The Surface", B_FALSE, H_FOREST, 10, 0, D_NONE, B_TRUE, 0); - addregiontype(RG_HEAVEN, "The Realm of Gods", B_FALSE, H_HEAVEN, 1, 0, D_NONE, B_FALSE, 0); + + addregiontype(RG_BABAYAGAHUT, "Baba Yaga's Hut", B_FALSE, H_BYHUT, 0, 0, D_NONE, B_FALSE, 0, B_FALSE); + + addregiontype(RG_WORLDMAP, "The Surface", B_FALSE, H_FOREST, 10, 0, D_NONE, B_TRUE, 0, B_FALSE); + addregiontype(RG_HEAVEN, "The Realm of Gods", B_FALSE, H_HEAVEN, 1, 0, D_NONE, B_FALSE, 0, B_FALSE); // main branches - addregiontype(RG_MAINDUNGEON, "The Main Dungeon", B_FALSE, H_DUNGEON, 25, 3, D_DOWN, B_TRUE, 0); - addregiontype(RG_CAVE, "The Goblin Caves", B_TRUE, H_CAVE, 5, 1, D_DOWN, B_TRUE, 2); - addregiontype(RG_WOODS, "The Sylvan Woods", B_TRUE, H_FOREST, 5, 3, D_DOWN, B_TRUE, 1); + addregiontype(RG_MAINDUNGEON, "The Main Dungeon", B_FALSE, H_DUNGEON, 25, 3, D_DOWN, B_TRUE, 0, B_FALSE); + addregiontype(RG_CAVE, "The Goblin Caves", B_TRUE, H_CAVE, 5, 1, D_DOWN, B_TRUE, 2, B_FALSE); + addregiontype(RG_WOODS, "The Sylvan Woods", B_TRUE, H_FOREST, 5, 3, D_DOWN, B_TRUE, 1, B_FALSE); // minor branches - addregiontype(RG_PIT, "A Pit", B_FALSE, H_PIT, 1, 1, D_DOWN, B_FALSE, 0); - addregiontype(RG_SEWER, "A Sewer", B_FALSE, H_SEWER, 1, 0, D_NONE, B_FALSE, 2); - addregiontype(RG_STOMACH, "A Stomach", B_FALSE, H_STOMACH, 1, 0, D_NONE, B_FALSE, 0); + addregiontype(RG_PIT, "A Pit", B_FALSE, H_PIT, 1, 1, D_DOWN, B_FALSE, 0, B_TRUE); + addregiontype(RG_SEWER, "A Sewer", B_FALSE, H_SEWER, 1, 0, D_NONE, B_FALSE, 2, B_TRUE); + addregiontype(RG_STOMACH, "A Stomach", B_FALSE, H_STOMACH, 1, 0, D_NONE, B_FALSE, 0, B_FALSE); + // special } diff --git a/map.h b/map.h index 786716c..e8466c3 100644 --- a/map.h +++ b/map.h @@ -10,7 +10,7 @@ int addrandomthing(cell_t *c, int obchance, int *nadded); region_t *addregion(enum REGIONTYPE rtype, region_t *parent, int outlineid, int depthmod, int createdby); regionoutline_t *addregionoutline(enum REGIONTYPE rtype); regionthing_t *addregionthing(regionoutline_t *ro, int depth, int x, int y, enum REGIONTHING whatkind, int value, char *what); -regiontype_t *addregiontype(enum REGIONTYPE id, char *name, int pluralname, enum HABITAT defaulthabitat, int maxdepth, int stairsperlev, int deeperdir, int major, int depthmod); +regiontype_t *addregiontype(enum REGIONTYPE id, char *name, int pluralname, enum HABITAT defaulthabitat, int maxdepth, int stairsperlev, int deeperdir, int major, int depthmod, int addparentdepth); void adjustcellglyphforlight(cell_t *c, glyph_t *col); int autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy, int doorpct, int dooropenchance); void breakwall(cell_t *c); @@ -37,6 +37,7 @@ enum CELLTYPE getcellsolid(cell_t *c); enum CELLTYPE getmapempty(map_t *m); enum CELLTYPE getmapsolid(map_t *m); enum DEPTH getcellwaterdepth(cell_t *c, lifeform_t *lf); +int getconnectedwatercells(cell_t *c, cell_t **retcell, int *ncells); cell_t *get_closest_adjcell(cell_t *src, cell_t *dst); int getdoorlockdiff(int depth); int getdoorsecretdiff(int depth); @@ -63,6 +64,7 @@ int countmapobswithflag(map_t *m, enum FLAG flagid); int countmapobswithflagval(map_t *m, enum FLAG flagid, int val0, int val1, int val2, char *text); int countstairs(map_t *m, int dir); void createborder(map_t *map, enum CELLTYPE solidtype); +void createbyhut(map_t *map, int depth, map_t *parentmap, int exitdir, object_t *entryob); void createcave(map_t *map, int depth, map_t *parentmap, int exitdir, object_t *entryob); void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_t *entryob); void createfakes(map_t *map, cell_t *cell); diff --git a/move.c b/move.c index 208e448..4a4bc38 100644 --- a/move.c +++ b/move.c @@ -3550,7 +3550,7 @@ int willmove(lifeform_t *lf, int dir, enum ERROR *error) { // for at least average iq things... if (iq >= AT_AVERAGE) { // don't move if in pain - if (move_will_hurt(lf)) { + if (move_will_hurt(lf) && !isfleeing(lf)) { if (error) *error = E_WONT; return B_FALSE; } diff --git a/objects.c b/objects.c index 8568a1b..e93585f 100644 --- a/objects.c +++ b/objects.c @@ -1573,6 +1573,13 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum lev = firstlev + i; if (lev > MAXSPELLLEV) break; oid = getrandomspellfromschool(bookcontents,lev); + // special case - paladin's always have this spell + if ((lev == 3) && (where->owner) && hassubjob(where->owner, SJ_PALADIN) && + (bookcontents == SS_LIFE)) { + while (oid == OT_S_DISRUPTUNDEAD) { + oid = getrandomspellfromschool(bookcontents,lev); + } + } if (oid != OT_NONE) { assert(addobfast(o->contents, oid)); } @@ -2497,6 +2504,10 @@ void adjustdamob(object_t *o, int *dam, enum DAMTYPE damtype) { *dam = 0; return; } + if (hasflag(o->flags, F_IMMUTABLE)) { + *dam = 0; + return; + } // immune? if (isimmuneto(o->flags, damtype, B_FALSE)) { @@ -3556,7 +3567,7 @@ objecttype_t *findotn(char *name) { modname = strrep(modname, "gems ", "gem ", NULL); modname = strrep(modname, "knives", "knife", NULL); modname = strrep(modname, "leaves", "leaf", NULL); - modname = strrep(modname, "loaves ", "load ", NULL); + modname = strrep(modname, "loaves ", "loaf ", NULL); modname = strrep(modname, "lumps ", "lump ", NULL); modname = strrep(modname, "pieces ", "piece ", NULL); modname = strrep(modname, "piles ", "pile ", NULL); @@ -3650,6 +3661,21 @@ objecttype_t *findotn(char *name) { return NULL; } +int getrustdampct(object_t *o) { + int pct = 100; + flag_t *rust; + rust = hasflag(o->flags, F_RUSTED); + if (rust) { + if (rust->val[0] >= R_TRUSTY) { + pct = 50; + } else if (rust->val[0] >= R_VRUSTY) { + pct = 75; + } else { + pct = 90; + } + } + return pct; +} int getfirearmrange(object_t *o) { flag_t *f; @@ -3819,7 +3845,7 @@ void fragments(cell_t *centre, char *what, int speed, int howfar) { // add object then fire it o = addob(centre->obpile, what); if (o) { - real_fireat(NULL, o, o->amt, dst, speed, NULL, B_FALSE, OT_NONE); + real_fireat(NULL, o, o->amt, dst, speed, NULL, B_FALSE, OT_NONE, NULL); } } else { // add object @@ -5815,9 +5841,17 @@ char *getobconditionname(object_t *o, char *buf) { iqb = AT_AVERAGE; // this should be sufficient to show everything } - if (iscorpse(o)) { + + // only show 'immutable' if this is abnormal. + if (hasflagknown(o->flags, F_IMMUTABLE) && !hasflag(o->type->flags, F_IMMUTABLE)) { + strcpy(buf, "immutable"); + } else { strcpy(buf, ""); + } + + if (iscorpse(o)) { if (hasflag(o->flags, F_PREPARED)) { + if (strlen(buf)) strcat(buf, " "); strcat(buf, "cooked"); } if (hasflag(o->flags, F_SALTED)) { @@ -5837,22 +5871,26 @@ char *getobconditionname(object_t *o, char *buf) { } } else { + char condbuf[BUFLEN]; if (iqb >= AT_LOW) { pct = getobhppct(o); - if (pct >= 85) { - strcpy(buf, ""); + strcpy(condbuf, ""); } else if (pct >= 75) { - snprintf(buf, BUFLEN, "battered"); + snprintf(condbuf, BUFLEN, "battered"); } else if (pct >= 50) { - snprintf(buf, BUFLEN, "damaged"); + snprintf(condbuf, BUFLEN, "damaged"); } else if (pct >= 25) { - snprintf(buf, BUFLEN, "very damaged"); + snprintf(condbuf, BUFLEN, "very damaged"); } else { - snprintf(buf, BUFLEN, "critically damaged"); + snprintf(condbuf, BUFLEN, "critically damaged"); } } else { - strcpy(buf, ""); + strcpy(condbuf, ""); + } + if (strlen(condbuf)) { + if (strlen(buf)) strcat(buf, " "); + strcat(buf, condbuf); } } return buf; @@ -6557,10 +6595,10 @@ int getthrowdam(object_t *o) { // non-missile objects do 25% less damage if (!hasflag(o->flags, F_THROWMISSILE)) { dam = pctof(75, dam); - } - // soft materials do less damage - if (gethardness(o->material->id) < 2) { - dam /= 2; + // soft materials do less damage + if (gethardness(o->material->id) < 2) { + dam /= 2; + } } } @@ -6573,7 +6611,7 @@ int getthrowdam(object_t *o) { } // note: damage will also be modified based on speed in fireat() - + if (dam < 0) dam = 0; return (int)ceil(dam); } @@ -7905,6 +7943,10 @@ int makeduller(object_t *o, int howmuch) { int oldbonus,newbonus; int rv = B_FALSE; + if (hasflag(o->flags, F_IMMUTABLE)) { + return B_FALSE; + } + // get object name before changing the bonus getobname(o,obname, 1); @@ -8061,20 +8103,27 @@ void makewet(object_t *o, int amt) { killflagsofid(o->flags, F_HOT); if (o->material->id == MT_METAL) { - if (amt < R_RUSTY) amt = R_RUSTY; - if (amt > R_TRUSTY) amt = R_TRUSTY; + int rustchance = 25; f = hasflag(o->flags, F_RUSTED); - if (f) { - if (f->val[0] < R_TRUSTY) { - // make more rusty - f->val[0] += amt; + if (f) rustchance += 25; + + if (pctchance(rustchance)) { + if (amt < R_RUSTY) amt = R_RUSTY; + if (amt > R_TRUSTY) amt = R_TRUSTY; + if (f) { + if (f->val[0] < R_TRUSTY) { + // make more rusty + f->val[0] += amt; + } + } else { + // rust + if (haslos(player, loc) && !isdead(player)) { + msg("^%c%s rust%s.", + (o->pile->owner && isplayer(o->pile->owner)) ? 'b' : 'n', + obnamefull,OBS1(o)); + } + f = addflag(o->flags, F_RUSTED, amt, NA, NA, NULL); } - } else { - // rust - if (haslos(player, loc) && !isdead(player)) { - msg("%s rust%s.",obnamefull,OBS1(o)); - } - f = addflag(o->flags, F_RUSTED, amt, NA, NA, NULL); } } else { if (hasflag(o->flags, F_CANGETWET)) { @@ -8096,7 +8145,6 @@ void makewet(object_t *o, int amt) { f->val[1] = TM_WETTIME; } } else { - // get wet if (!isdead(player)) { int doannounce = B_FALSE; @@ -10129,36 +10177,42 @@ int pour(lifeform_t *lf, object_t *o) { } } else if (o->type->id == OT_POT_RESTORATION) { flag_t *f, *nextf; - if (isplayer(lf)) { - msg("Your %s looks as good as new!",noprefix(dstname)); - } - // restore orig material - if (dst->material != dst->type->material) { - changemat(dst, dst->type->material->id); - } - // remove blessings/curses - setblessed(dst, B_UNCURSED); - dst->blessknown = B_TRUE; - // remove bonuses - killflagsofid(dst->flags, F_BONUS); - // remove temporary flags, obmod flags and modify some others - for (f = dst->flags->first ; f ; f = nextf) { - nextf = f->next; - if (f->lifetime > 0) { - killflag(f); - } else if (f->lifetime == FROMOBMOD) { - killflag(f); - } else if (f->id == F_FROZEN) { - killflag(f); - } else if (f->id == F_ONFIRE) { - killflag(f); - } else if (f->id == F_POISONED) { - killflag(f); - } else if (f->id == F_OBHP) { - f->val[0] = f->val[1]; - } - } + if (hasflag(dst->flags, F_IMMUTABLE)) { + if (isplayer(lf)) { + msg("For a moment, your %s looks as good as new.",noprefix(dstname)); + } + } else { + if (isplayer(lf)) { + msg("Your %s looks as good as new!",noprefix(dstname)); + } + // restore orig material + if (dst->material != dst->type->material) { + changemat(dst, dst->type->material->id); + } + // remove blessings/curses + setblessed(dst, B_UNCURSED); + dst->blessknown = B_TRUE; + // remove bonuses + killflagsofid(dst->flags, F_BONUS); + // remove temporary flags, obmod flags and modify some others + for (f = dst->flags->first ; f ; f = nextf) { + nextf = f->next; + if (f->lifetime > 0) { + killflag(f); + } else if (f->lifetime == FROMOBMOD) { + killflag(f); + } else if (f->id == F_FROZEN) { + killflag(f); + } else if (f->id == F_ONFIRE) { + killflag(f); + } else if (f->id == F_POISONED) { + killflag(f); + } else if (f->id == F_OBHP) { + f->val[0] = f->val[1]; + } + } + } // we now know what the potion was if (!isknown(o)) makeknown(o->type->id); @@ -11302,29 +11356,31 @@ int readsomething(lifeform_t *lf, object_t *o) { object_t *oo,*poss[MAXPILEOBS]; int nposs = 0; - // make a piece of armour invulnerable + // make a weapon or piece of armour invulnerable for (oo = lf->pack->first ; oo ; oo = oo->next) { - if (isequipped(oo) && !hasflag(oo->flags, F_INVULNERABLE)) { - poss[nposs++] = oo; + if (isweapon(oo) || isarmour(oo)) { + if (isequipped(oo) && !hasflag(oo->flags, F_INVULNERABLE)) { + poss[nposs++] = oo; + } } } if (nposs) { oo = poss[rnd(0,nposs-1)]; - addflag(oo->flags, F_INVULNERABLE, B_TRUE, NA, NA, NULL); - killflagsofid(oo->flags, F_DAMAGABLE); if (isplayer(lf)) { char ooname[BUFLEN]; getobname(oo, ooname, oo->amt); - msg("Your %s become%s ultra-dense!", ooname, (oo->amt == 1) ? "s" : ""); + msg("Your %s become%s ultra-dense!", noprefix(ooname), (oo->amt == 1) ? "s" : ""); } else if (cansee(player, lf)) { char lfname[BUFLEN]; char ooname[BUFLEN]; getlfname(lf, lfname); getobname(oo, ooname, oo->amt); msg("%s%s %s become%s ultra-dense!", lfname, getpossessive(lfname), - ooname, (oo->amt == 1) ? "s" : ""); + noprefix(ooname), (oo->amt == 1) ? "s" : ""); } + addflag(oo->flags, F_IMMUTABLE, B_TRUE, NA, NA, NULL); + killflagsofid(oo->flags, F_DAMAGABLE); ndone++; } // still nothing done? @@ -11495,7 +11551,7 @@ int readsomething(lifeform_t *lf, object_t *o) { } else { if (!giveskill(lf, f->val[0])) { // can't learn this skill. maybe you have f_noskill? - if (isplayer(lf)) msg("You are incapable of using this skill."); + if (isplayer(lf)) msg("You are incapable of learning this skill."); } } } @@ -12435,11 +12491,11 @@ int real_takedamage(object_t *o, int howmuch, int damtype, int wantannounce) { } int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed, object_t *firearm) { - return real_fireat(thrower, o, amt, where, speed, firearm, B_TRUE, OT_NONE); + return real_fireat(thrower, o, amt, where, speed, firearm, B_TRUE, OT_NONE, NULL); } // throw speed/2 is the damage multiplier -int real_fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed, object_t *firearm, int announcethrow, enum OBTYPE fromspell) { +int real_fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed, object_t *firearm, int announcethrow, enum OBTYPE fromspell, object_t **newobptr) { char throwername[BUFLEN]; char throwernamea[BUFLEN]; char realthrowername[BUFLEN]; @@ -12556,6 +12612,7 @@ int real_fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int sp //taketime(thrower, SPEED_THROW); // fail. reason = E_CURSED; + if (newobptr) *newobptr = o; return B_TRUE; } } @@ -12591,11 +12648,15 @@ int real_fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int sp if (thrower) { if (firearm) { if (touch(thrower, firearm)) { + if (newobptr) *newobptr = o; return B_TRUE; } } else { if (o->pile == thrower->pack) { if (touch(thrower, o)) { + if (newobptr) { + if (!isdeadob(o)) *newobptr = o; + } return B_TRUE; } } @@ -12772,6 +12833,7 @@ int real_fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int sp } } removeob(o, amt); + if (newobptr) *newobptr = NULL; return B_FALSE; } @@ -12783,6 +12845,7 @@ int real_fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int sp } moveob(o, thrower->cell->obpile, amt); + if (newobptr) *newobptr = o; return B_FALSE; } } @@ -13015,6 +13078,7 @@ int real_fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int sp targetname, isplayer(target) ? "" : "es", obname); } moveob(o, target->pack, amt); + if (newobptr) *newobptr = o; return B_FALSE; } else { int dam = 0; @@ -13224,6 +13288,7 @@ int real_fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int sp angergodmaybe(R_GODMAGIC, 10, GA_HERESY); } + if (newobptr) *newobptr = newob; return B_FALSE; } @@ -13345,20 +13410,20 @@ void timeeffectsob(object_t *o) { newc = getrandomadjcell(location, WE_NOTWALL, B_ALLOWEXPAND); if (newc) { //flag_t *inv; + object_t *newob = NULL; // make sure the object doesn't take damage //inv = addflag(o->flags, F_INVULNERABLE, B_TRUE, NA, NA, NULL); - fireat(NULL, o, o->amt, newc, 1, NULL); - if (canseeloc) { + real_fireat(NULL, o, o->amt, newc, 1, NULL, B_TRUE, OT_NONE, &newob); + if (newob && canseeloc) { // player now knows that this is blessed - o->blessknown = B_TRUE; + newob->blessknown = B_TRUE; } - // update location - //if (inv) killflag(inv); - // further effects on this object will come from its new location - location = newc; + // no other effects for the object this turn. + // (in case it died when thrown away) + return; } else { // object can't go anywhere - it disintegrates. if (owner && cansee(player, owner)) { @@ -13576,11 +13641,13 @@ void timeeffectsob(object_t *o) { } } - if (f->id == F_EXPLODEONDEATH) { - if (o->pile->where && haslos(player, o->pile->where)) { - // pass a perception check to see it sparking... - if (skillcheck(player, SC_SEARCH, 15, 0)) { - msg("^w%s sparks.^n", obname); + if (f->id == F_EXPLODEONDEATH) { + if (hasflag(o->flags, F_OBHPDRAIN)) { + if (o->pile->where && haslos(player, o->pile->where)) { + // pass a perception check to see it sparking... + if (skillcheck(player, SC_SEARCH, 15, 0)) { + msg("^w%s sparks.^n", obname); + } } } } @@ -14571,6 +14638,10 @@ int validateobs(void) { return goterror; } +// note: we don't check for F_IMMUTABLE here because we don't +// want to (for example) give away the flag on a weapon if the +// player attacks a door/wall with it, and doesn't know that +// it's immutable yet. int wepdullable(object_t *o) { enum DAMTYPE dt; diff --git a/objects.h b/objects.h index 5444e3e..01bcd39 100644 --- a/objects.h +++ b/objects.h @@ -104,6 +104,7 @@ brand_t *getrandombrandfor(objecttype_t *ot); int getrandomgrimoirelev(void); objecttype_t *getrandomobofclass(enum OBCLASS ocid, int minrarity, int maxrarity, lifeform_t *forlf); enum OBTYPE getrandomtrapforob(void); +int getrustdampct(object_t *o); int getfirearmrange(object_t *o); int getfirearmspeed(object_t *o); glyph_t *getglyph(object_t *o); @@ -280,7 +281,7 @@ object_t *splitob(object_t *o); int takedamage(object_t *o, int howmuch, int damtype); int real_takedamage(object_t *o, int howmuch, int damtype, int wantannounce); int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed, object_t *firearm); -int real_fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed, object_t *firearm, int announcethrow, enum OBTYPE fromspell); +int real_fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed, object_t *firearm, int announcethrow, enum OBTYPE fromspell, object_t **newobptr); void timeeffectsob(object_t *o); int touch_battle_spoils(object_t *o); void trapeffects(object_t *trapob, enum OBTYPE oid, cell_t *c); diff --git a/spell.c b/spell.c index 280a4d1..971a305 100644 --- a/spell.c +++ b/spell.c @@ -5618,6 +5618,22 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (ndigs == 0) { if (isplayer(caster)) nothinghappens(); } + } else if (spellid == OT_S_DISRUPTUNDEAD) { + target = targcell->lf; + if (!target || !isundead(target)) { + fizzle(caster); + return B_TRUE; + } + if (isplayer(target)) { + msg("You feel your body's essence unraveling!"); + } else if (cansee(player, target)) { + char lfname[BUFLEN]; + getlfname(target, lfname); + msg("%s convulses.", lfname); + } + // use direct damage rather than holy, because otherwise it might be increased + // due to vulnerabilities + losehp(target, roll("2d3"), DT_DIRECT, caster, "disruption"); } else if (spellid == OT_S_DISORIENT) { target = targcell->lf; @@ -6856,8 +6872,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ takedamage(o, 1, DT_COLD); donesomething = B_TRUE; } - } else if (spellid == OT_S_GREASE) { + } else if ((spellid == OT_S_GREASE) || (spellid == OT_S_CREATEWATER)) { int radius; + char createname[BUFLEN]; if (targcell->type->solid) { fizzle(caster); return B_TRUE; @@ -6865,7 +6882,19 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ radius = power/2; if (radius < 1) radius = 1; - addobburst(targcell, radius, DT_ORTH, "puddle of oil", caster, LOF_WALLSTOP); + switch (spellid) { + case OT_S_CREATEWATER: + strcpy(createname, "large puddle of water"); + break; + case OT_S_GREASE: + strcpy(createname, "puddle of oil"); + break; + default: + fizzle(caster); + return B_TRUE; + } + + addobburst(targcell, radius, DT_ORTH, createname, caster, LOF_WALLSTOP); if (haslos(player, targcell)) { char underbuf[BUFLEN]; @@ -6876,7 +6905,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } else { strcpy(underbuf, ""); } - msg("A %spool of oil appears%s!", (radius == 1) ? "" : "huge ", underbuf); + msg("A %s%s appears%s!", (radius == 1) ? "" : "huge ", createname, underbuf); if (seenbyplayer) *seenbyplayer = B_TRUE; } } else if (spellid == OT_S_HAILSTORM) { @@ -7890,42 +7919,14 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } else if (targob->type->obclass->id == OC_POTION) { newcelltype = CT_WALLGLASS; } else { - switch (targob->type->id) { - case OT_ASH: newoid = OT_DUSTCLOUD; break; - case OT_ASHCONCEAL: newoid = OT_DUSTCLOUD; break; - case OT_ASHEXPLODE: newoid = OT_DUSTCLOUD; break; - case OT_ASHSLEEP: newoid = OT_DUSTCLOUD; break; - case OT_BAGOFHOLDING: newoid = OT_BAGOFHOLDINGLARGE; break; - case OT_BAGOFHOLDINGLARGE: newoid = OT_BAGOFHOLDINGHUGE; break; - case OT_BED: newoid = OT_DOORWOOD; break; - case OT_BUCKLER: newoid = OT_SHIELD; break; - case OT_CLOVER: newoid = OT_SHRUB; break; - case OT_DOORIRON: newcelltype = CT_WALLMETAL; break; - case OT_DOORWOOD: newcelltype = CT_WALLWOOD; break; - case OT_FENCEWOOD: newcelltype = CT_WALLWOOD; break; - case OT_FIRESMALL: newoid = OT_FIREMED; break; - case OT_FIREMED: newoid = OT_FIRELARGE; break; - case OT_FIREPLACE: newoid = OT_FIRELARGE; break; - case OT_FLOWER: newoid = OT_SHRUB; break; - case OT_FOUNTAIN: newoid = OT_WATERDEEP; break; - case OT_GATEIRON: newcelltype = CT_WALLMETAL; break; - case OT_GATEWOOD: newcelltype = CT_WALLWOOD; break; - case OT_ICESHEET: newoid = OT_ICICLE; break; - case OT_LEAF: newoid = OT_SHRUB; break; - case OT_MISTLETOE: newoid = OT_SHRUB; break; - case OT_NUT: newoid = OT_TREE; break; - case OT_SACK: newoid = OT_SACKLARGE; break; - case OT_SACKLARGE: newoid = OT_SACKHUGE; break; - case OT_SHIELDHIDE: newoid = OT_SHIELD; break; - case OT_SHIELD: newoid = OT_SHIELDLARGE; break; - case OT_SHIELDLARGE: newoid = OT_SHIELDTOWER; break; - case OT_SHRUB: newoid = OT_TREE; break; - case OT_STUMP: newoid = OT_TREE; break; - case OT_TREE: newcelltype = CT_WALLTREE; break; - case OT_WOODENBARREL: newoid = OT_DOORWOOD; break; - case OT_WOODENSTOOL: newoid = OT_WOODENTABLE; break; - case OT_WOODENTABLE: newoid = OT_DOORWOOD; break; - default: break; + flag_t *f; + f = hasflag(targob->flags, F_GROWSTO); + if (f) { + if (f->val[1] == VT_OB) { + newoid = f->val[0]; + } else { // ie. cell + newcelltype = f->val[0]; + } } } @@ -7965,6 +7966,102 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } else { if (seen) msg("%s shudders for a moment.", obname); } + } else if (spellid == OT_S_OBJECTSHRINK) { + enum OBTYPE newoid = OT_NONE; + char obtocreate[BUFLEN]; + enum LFSIZE newsize = SZ_ANY; + enum CELLTYPE newcelltype = CT_NONE; + skill_t *obsk = SK_NONE; + char obname[BUFLEN],newobname[BUFLEN]; + int seen; + + if (targcell->obpile->first) { + targob = doaskobject(targcell->obpile, "Target which object", NULL, NULL, B_TRUE, B_FALSE, B_FALSE, '\0', NULL, MT_NOTHING, AO_NONE, F_NONE); + } + strcpy(obtocreate, ""); + + if (!targob) { + fizzle(caster); + return B_TRUE; + } + + targcell = getoblocation(targob); + if (haslos(player, targcell)) { + seen = B_TRUE; + if (seenbyplayer) *seenbyplayer = B_TRUE; + } + getobname(targob, obname, 1); + obsk = getobskill(targob->flags); + if (isweapon(targob) && (obsk->id == SK_LONGBLADES)) { + newoid = OT_DAGGER; + } else if (isweapon(targob) && (obsk->id == SK_SHORTBLADES)) { + newoid = OT_KNIFE; + } else if (isweapon(targob) && (obsk->id == SK_CLUBS)) { + newoid = OT_STICK; + } else if (isweapon(targob) && (obsk->id == SK_AXES)) { + newoid = OT_KNIFE; + } else if ((targob->type->obclass->id == OC_ARMOUR) && + hasflag(targob->flags, F_MULTISIZE) && + (getarmoursize(targob) > SZ_TINY)) { + newsize = getarmoursize(targob) - 1; + } else if (targob->type->obclass->id == OC_POTION) { + newoid = OT_BROKENGLASS; + } else { + flag_t *f; + f = hasflag(targob->flags, F_SHRINKSTO); + if (f) { + if (f->val[1] == VT_OB) { + if (strlen(f->text)) { + strcpy(obtocreate, f->text); + } else { + newoid = f->val[0]; + } + } else { // ie. cell + newcelltype = f->val[0]; + } + } + } + + if (newsize != SZ_ANY) { + resizeobject(targob, newsize); + getobname(targob, newobname, 1); + getobname(targob, newobname, 1); + if (seen) msg("%s shrinks into %s!", obname, newobname); + } else if (newcelltype != CT_NONE) { + cell_t *where; + if (seen) { + celltype_t *ct; + ct = findcelltype(newcelltype); + msg("%s shrinks into %s %s!", obname, needan(ct->name) ? "an" : "a", ct->name); + } + where = getoblocation(targob); + killob(targob); + setcelltype(where, newcelltype); + } else if (newoid == targob->id) { + if (seen) msg("%s shudders for a moment.", obname); + } else if (strlen(obtocreate) || (newoid != OT_NONE)) { + obpile_t *op; + op = targob->pile; + killob(targob); + if (strlen(obtocreate)) { + targob = addob(op, obtocreate); + } else { + targob = addobfast(op, newoid); + } + if (targob) { + getobname(targob, newobname, 1); + if (seen) msg("%s shrinks into %s!", obname, newobname); + if (targob->type->id == OT_WATERDEEP) { + cell_t *where; + where = getoblocation(targob); + setcelltype(where, CT_LOWFLOOR); // lower floor so water doesn't spread + } + } else { + if (seen) msg("%s shudders then implodes!", obname); + } + } else { + if (seen) msg("%s shudders for a moment.", obname); + } } else if ((spellid == OT_S_ACCELMETAL) || (spellid == OT_S_PROPELMISSILE)) { char oidbuf[BUFLEN]; char obname[BUFLEN]; @@ -8016,7 +8113,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ killflagsofid(caster->flags, F_THROWING); // 5 is the same as AT_VHIGH strength - real_fireat(caster, targob, 1, targcell, 5, NULL, B_TRUE, spellid); + real_fireat(caster, targob, 1, targcell, 5, NULL, B_TRUE, spellid, NULL); } else if (spellid == OT_S_TRAVEL) { regionthing_t *poss[MAXCANDIDATES],*rt; region_t *srcregion = NULL; @@ -9178,6 +9275,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ f = addtempflag(caster->flags, F_GRAVLESSENED, power, NA, NA, NULL, FROMSPELL); f->obfrom = spellid; } else if (spellid == OT_S_GUSTOFWIND) { + int pen = 0; obpile_t *op; object_t *o, *nexto; object_t *poss[MAXPILEOBS],*blowob[MAXPILEOBS]; @@ -9241,9 +9339,20 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } - // easyish save to avoid falling - if (target && !skillcheck(target, SC_FALL, 12 + (power*2), 0)) { + switch (getlfsize(target)) { + case SZ_MEDIUM: + pen = -3; break; + case SZ_SMALL: + pen = -5; break; + case SZ_TINY: + pen = -7; break; + case SZ_MINI: + pen = -9; break; + break; + default: pen = 0; break; + } + if (target && !skillcheck(target, SC_FALL, 12 + (power*2), pen)) { fall(target, NULL, B_TRUE); } needredraw = B_TRUE; @@ -9305,6 +9414,18 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ strcpy(fullobname, ""); } + f = hasflag(o->flags, F_IMMUTABLE); + if (f) { + if (isplayer(caster)) { + char obname[BUFLEN]; + real_getobname(o, obname, o->amt, B_PREMODS, B_NOCONDITION, B_BLINDADJUST, B_BLESSINGS, B_NOUSED, B_NOSHOWALL); + msg("For some reason, %s is unaffected!", fullobname); + } + f->known = B_TRUE; + return B_FALSE; + } + + f = hasflag(o->flags, F_OBHP); if (f) { if (blessed == B_CURSED) { @@ -10238,6 +10359,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } else if (spellid == OT_S_SHATTER) { char buf[BUFLEN]; + if (targcell->lf && isplayer(targcell->lf)) { + msg("Ultra-sonic vibrations ring through your body!"); + } snprintf(buf, BUFLEN, "%s%s shatter spell", castername, getpossessive(castername)); if (!shattercell(targcell, caster, buf)) { fizzle(caster); @@ -10318,6 +10442,11 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ return B_TRUE; } + + if (isplayer(target)) { + msg("A sudden feeling of drowsiness washes over you!"); + } + if (spellresisted(target, caster, spellid, power, seenbyplayer, B_FALSE)) { // 1st skill check passed. make another one. if (spellresisted(target, caster, spellid, power, seenbyplayer, B_FALSE)) { @@ -10691,7 +10820,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ sprintf(dambuf, "%dd3", power); f->text = strdup(dambuf); } - real_fireat(caster, o, 1, targcell, 6, NULL, B_FALSE, OT_S_SPIKEVOLLEY); + real_fireat(caster, o, 1, targcell, 6, NULL, B_FALSE, OT_S_SPIKEVOLLEY, NULL); } else if (spellid == OT_S_STENCH) { int howlong; @@ -11302,7 +11431,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ // otherwise throw it there - but speed is based on // caster's INTELLIGENCE, not strength like normal. addflag(caster->flags, F_TKTHROW, A_IQ, SK_SS_MENTAL, NA, NULL); - real_fireat(caster, targob, targob->amt, targcell, power, NULL, B_TRUE, spellid); + real_fireat(caster, targob, targob->amt, targcell, power, NULL, B_TRUE, spellid, NULL); killflagsofid(caster->flags, F_TKTHROW); // note that we use fireat() rather than throwat() to avoid // calling taketime() twice. @@ -11857,7 +11986,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ // weilded weapons/armour for (o = targcell->lf->pack->first ; o ; o = nexto) { nexto = o->next; - if (o->type->material->id == MT_WOOD) { + if ((o->type->material->id == MT_WOOD) || (o->type->material->id == MT_DRAGONWOOD)) { if (isequipped(o)) { int dam; f = hasflag(o->flags, F_OBHP); @@ -11879,7 +12008,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ for (o = targcell->obpile->first ; o ; o = nexto) { nexto = o->next; - if (o->type->material->id == MT_WOOD) { + if ((o->type->material->id == MT_WOOD) || (o->type->material->id == MT_DRAGONWOOD)) { int dam; f = hasflag(o->flags, F_OBHP); if (f) { diff --git a/text.c b/text.c index 3561962..2a4b5ce 100644 --- a/text.c +++ b/text.c @@ -914,6 +914,8 @@ char *getdirname(int dir) { return "West"; case DC_NW: return "Northwest"; + case D_IN: + return "into"; } return "?errordir?"; } @@ -1407,6 +1409,9 @@ char *getregionname(char *buf, map_t *m, region_t *r, enum REGIONNAMEFORMAT how) case RG_STOMACH: snprintf(buf, BUFLEN, "a stomach"); break; + case RG_BABAYAGAHUT: + snprintf(buf, BUFLEN, "baba yaga's hut"); + break; } } else if ((how == RF_LONG) && m) { switch (r->rtype->id) { @@ -1434,6 +1439,9 @@ char *getregionname(char *buf, map_t *m, region_t *r, enum REGIONNAMEFORMAT how) case RG_STOMACH: snprintf(buf, BUFLEN, "inside a worm's stomach"); // TODO: " in a stomach of of xxx" break; + case RG_BABAYAGAHUT: + snprintf(buf, BUFLEN, "in baba yaga's hut"); + break; } } else { // ie. RF_SHORT switch (r->rtype->id) { @@ -1461,6 +1469,9 @@ char *getregionname(char *buf, map_t *m, region_t *r, enum REGIONNAMEFORMAT how) case RG_STOMACH: snprintf(buf, BUFLEN, "a stomach"); break; + case RG_BABAYAGAHUT: + snprintf(buf, BUFLEN, "baba yaga's hut"); + break; } } return buf; diff --git a/vault.c b/vault.c index 39fe72e..f29f676 100644 --- a/vault.c +++ b/vault.c @@ -878,7 +878,10 @@ int handleline(vault_t *v, char *line) { if (streq(command, "@id")) { if (!v->id) { if (nargs == 1) { - if (findvault(arg[0])) { + if (strchr(arg[0], ' ')) { + dblog("Vault names may not contain spaces: '%s'.", arg[0]); + return B_TRUE; + } else if (findvault(arg[0])) { dblog("Duplicate vault id %s", arg[0]); return B_TRUE; }