diff --git a/data.c b/data.c index 5046545..211708c 100644 --- a/data.c +++ b/data.c @@ -3155,6 +3155,10 @@ void initobjects(void) { addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL); addflag(lastot->flags, F_RANGE, 2, NA, NA, NULL); + addot(OT_S_SHAPEMETAL, "shape metal", "Completely repair any metal item.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addflag(lastot->flags, F_SPELLSCHOOL, SS_ALLOMANCY, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); + addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL); // l4 addot(OT_S_EXPLODEMETAL, "explode metal", "Causes all metal objects in a location explode.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_ALLOMANCY, NA, NA, NULL); @@ -3162,6 +3166,10 @@ void initobjects(void) { addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL); addflag(lastot->flags, F_TARGETTEDSPELL, TT_OBJECT, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); + addot(OT_S_HONEMETAL, "hone metal", "Temporarily sharpen any metal weapon, increasing its armour penetration.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addflag(lastot->flags, F_SPELLSCHOOL, SS_ALLOMANCY, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); + addflag(lastot->flags, F_MAXPOWER, 3, NA, NA, NULL); // l5 addot(OT_S_ANIMATEMETAL, "command metal", "Imbues a metallic weapon with temporary life, enabling it to fight on its own.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_ALLOMANCY, NA, NA, NULL); @@ -4048,6 +4056,8 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 3, 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); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_NEED, NA, NULL); // l4 addot(OT_S_DIG, "dig", "Blasts away earth to create passages.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); @@ -5730,7 +5740,7 @@ void initobjects(void) { addflag(lastot->flags, F_RODSHAPED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_ARMOURPIERCE, B_TRUE, NA, NA, ""); - addot(OT_LASERSWORD, "lasersword", "A metal handle capable of extending out a blade of pure energy.", MT_METAL, 1, OC_TECH, SZ_SMALL); + addot(OT_LASERSWORD, "laserblade", "A metal handle capable of extending out a blade of pure energy.", MT_METAL, 1, OC_TECH, SZ_SMALL); addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_RARE, NULL); addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 75, NA, NA, NULL); @@ -9020,6 +9030,69 @@ void initrace(void) { 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_PETE, "Pete", 60, '@', C_RED, MT_FLESH, RC_HUMANOID, "A human attired from head to toe in what appears to be a red bodysuit."); + setbodytype(lastrace, BT_HUMANOID); + addflag(lastrace->flags, F_NAME, NA, NA, NA, "Pete"); + addflag(lastrace->flags, F_UNIQUE, 33, BH_MAINDUNGEON, 1, "5-7"); + addflag(lastrace->flags, F_HOSTILE, NA, NA, NA, NULL); + addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); + addflag(lastrace->flags, F_HITDICE, 5, NA, NA, NULL); + addflag(lastrace->flags, F_TR, 6, NA, NA, NULL); + //addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); + //addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, NULL); + addflag(lastrace->flags, F_HASATTACK, OT_FISTS, 3, NA, NULL); + addflag(lastrace->flags, F_HASATTACK, OT_FISTS, 3, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_STR, AT_HIGH, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_AGI, AT_EXHIGH, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_IQ, AT_GTAVERAGE, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_WIS, AT_AVERAGE, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_CON, AT_HIGH, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_CHA, AT_AVERAGE, NA, NULL); + addflag(lastrace->flags, F_FLEEONHPPCT, 40, NA, NA, NULL); + addflag(lastrace->flags, F_STARTSKILL, SK_UNARMED, PR_ADEPT, NA, NULL); + addflag(lastrace->flags, F_CASTWITHOUTIQ, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_CANCAST, OT_S_WEB, 3, 3, "pw:8;range:5;"); + addflag(lastrace->flags, F_CANWILL, OT_A_JUMP, NA, NA, "stamcost:0;"); + addflag(lastrace->flags, F_CANWILL, OT_A_CLIMB, NA, NA, "pw:10;"); + addflag(lastrace->flags, F_DODGES, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_SPIDERCLIMB, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_SPELLCASTTEXT, OT_S_WEB, NA, B_APPENDYOU, "points his wrist"); + addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); + + addrace(R_RATTUS, "Rattus", 45, '@', C_BROWN, MT_FLESH, RC_HUMANOID, "A scruffy, long whiskered human."); + setbodytype(lastrace, BT_HUMANOID); + addflag(lastrace->flags, F_NAME, NA, NA, NA, "Rattus"); + addflag(lastrace->flags, F_UNIQUE, 33, BH_MAINDUNGEON, 1, "2-4"); + addflag(lastrace->flags, F_HOSTILE, NA, NA, NA, NULL); + addflag(lastrace->flags, F_HITDICE, 4, NA, NA, NULL); + addflag(lastrace->flags, F_TR, 4, NA, NA, NULL); + addflag(lastrace->flags, F_HASATTACK, OT_FISTS, 3, NA, NULL); + addflag(lastrace->flags, F_MINIONS, 100, 2, 3, "giant rat"); + addflag(lastrace->flags, F_STARTATT, A_STR, AT_LOW, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_AGI, AT_LOW, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_IQ, AT_LOW, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_WIS, AT_LOW, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_CON, AT_AVERAGE, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_CHA, AT_LOW, NA, NULL); + addflag(lastrace->flags, F_MATVULN, MT_SILVER, 200, 6, NULL); + addflag(lastrace->flags, F_SEEINDARK, 7, NA, NA, NULL); + addflag(lastrace->flags, F_CANCAST, OT_S_SHAPESHIFT, 3, 3, "pw:1;race:plague rat;"); + addflag(lastrace->flags, F_CANCAST, OT_S_SUMMONANIMALSSM, 2, 2, "pw:5;race:giant rat;count:2;"); + addflag(lastrace->flags, F_STARTSKILL, SK_PERCEPTION, PR_SKILLED, NA, NULL); + addflag(lastrace->flags, F_STARTSKILL, SK_THIEVERY, PR_BEGINNER, NA, NULL); + addflag(lastrace->flags, F_AISPELLTARGETOVERRIDE, OT_S_SHAPESHIFT, F_AICASTTOFLEE, ST_SELF, "100"); + addflag(lastrace->flags, F_ENHANCESMELL, 3, NA, NA, NULL); + addflag(lastrace->flags, F_CASTCHANCE, 75, NA, NA, NULL); + addflag(lastrace->flags, F_WANTS, OT_POT_RUM, NA, NA, NULL); + addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "golden crown"); + addflag(lastrace->flags, F_SPELLCASTTEXT, OT_NONE, NA, NA, "twitches his nose"); + addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_LYCANTHROPE, -1, NA, NA, "dire rat"); + addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_HITCONFER, F_POISONED, SC_POISON, 100, NULL); + addflag(lastrace->flags, F_HITCONFERVALS, P_LYCANTHROPY, -1, PERMENANT, "10^dire rat"); + addflag(lastrace->flags, F_FILLPOT, OT_POT_LYCANTHROPY, NA, NA, NULL); + 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"); @@ -9213,7 +9286,7 @@ void initrace(void) { addflag(lastrace->flags, F_STARTSKILL, SK_LISTEN, PR_NOVICE, NA, NULL); addflag(lastrace->flags, F_CANWILL, OT_A_JUMP, NA, NA, NULL); addflag(lastrace->flags, F_STABILITY, B_TRUE, NA, NA, NULL); - addflag(lastrace->flags, F_SEEINDARK, 2, NA, NA, NULL); + addflag(lastrace->flags, F_SEEINDARK, 6, NA, NA, NULL); addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL); // penalties addbonustext(lastrace->flags, F_PENDESC, "Slightly low Hit Points."); @@ -9254,7 +9327,7 @@ void initrace(void) { addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_FLEEONHPPCT, 50, NA, NA, NULL); // bonuses - addflag(lastrace->flags, F_SEEINDARK, 3, NA, NA, NULL); + addflag(lastrace->flags, F_SEEINDARK, 7, NA, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_CARTOGRAPHY, PR_NOVICE, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_METALWORK, PR_NOVICE, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_SS_ALLOMANCY, PR_NOVICE, NA, NULL); @@ -9372,7 +9445,7 @@ void initrace(void) { addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_FLEEONHPPCT, 50, NA, NA, NULL); // bonuses - addflag(lastrace->flags, F_SEEINDARK, 2, NA, NA, NULL); + addflag(lastrace->flags, F_SEEINDARK, 5, NA, NA, NULL); addflag(lastrace->flags, F_MEDITATES, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_MPMOD, 3, NA, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_RANGED, PR_NOVICE, NA, NULL); @@ -9415,7 +9488,7 @@ void initrace(void) { addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_FLEEONHPPCT, 50, NA, NA, NULL); // bonuses - addflag(lastrace->flags, F_SEEINDARK, 2, NA, NA, NULL); + addflag(lastrace->flags, F_SEEINDARK, 6, NA, NA, NULL); addflag(lastrace->flags, F_MEDITATES, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_MPMOD, 3, NA, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_SS_DEATH, PR_NOVICE, NA, NULL); diff --git a/data/hiscores.db b/data/hiscores.db index 453fd69..ec1e184 100644 Binary files a/data/hiscores.db and b/data/hiscores.db differ diff --git a/defs.h b/defs.h index f77ee6d..38f0a23 100644 --- a/defs.h +++ b/defs.h @@ -1031,9 +1031,11 @@ enum RACE { R_NONE = 0, R_RANDOM, R_SPECIFIED, // unique monstesr - R_JAILER, R_BABAYAGAHUT, R_BABAYAGA, + R_JAILER, + R_PETE, + R_RATTUS, // playable races R_ASHKARI, R_AVIAD, @@ -1608,9 +1610,11 @@ enum OBTYPE { OT_S_ANIMATEMETAL, OT_S_EXPLODEMETAL, OT_S_HEATMETAL, + OT_S_HONEMETAL, OT_S_PULLMETAL, OT_S_MAGSHIELD, OT_S_METALHEAL, + OT_S_SHAPEMETAL, // -- death magic / necromency OT_S_ANIMATEDEAD, OT_S_BLIGHT, @@ -2584,6 +2588,9 @@ enum FLAG { F_THROWNBY, // this object was thrown by lifeform id v0. F_CANHOME, // this object can have the 'homing' flag F_UNIQUE, // only one may appear + // if v0 > 0, it means the % chance of this lf appearing. + // v1 = branch id to appear in (ie. BH_xxx) + // text = "min-max" (depth to appear at) F_GLYPH, // override the glyph with f->val[1] // v0 is either NA (white) or colourid (C_xxx). // OPTIONAL v2: if you lorelev for this race is less diff --git a/io.c b/io.c index a96d65b..0037758 100644 --- a/io.c +++ b/io.c @@ -2822,6 +2822,10 @@ int announceobflaggain(object_t *o, flag_t *f) { switch (f->id) { + case F_ARMOURPIERCE: + donesomething = B_TRUE; + if (o->birthtime != curtime) msg("%s suddenly become%s razor-sharp!",prefix, OB1(o, "s", "")); + break; case F_ONFIRE: donesomething = B_TRUE; if (o->birthtime != curtime) msg("%s catch%s on fire.",prefix, OB1(o, "es", "")); @@ -2879,6 +2883,9 @@ void announceobflagloss(object_t *o, flag_t *f) { } switch (f->id) { + case F_ARMOURPIERCE: + if (o->birthtime != curtime) msg("%s %s no longer razor-sharp!",prefix, OB1(o, "is", "are")); + break; case F_ONFIRE: // replace "the flaming xxx is no longer on fire" // with "the xxx is no longer on fire" @@ -4986,7 +4993,11 @@ void docomms_areadangers(char *who, flagpile_t *fp, lifeform_t *lf) { if (showit) { char lfname[BUFLEN]; real_getlfnamea(c->lf, lfname, NULL, B_SHOWALL, B_REALRACE); - msg("\"There is %s living nearby...\"", lfname); more(); + if (lfhasflag(c->lf, F_NAME)) { + msg("\"%s is living nearby...\"", lfname); more(); + } else { + msg("\"There is %s living nearby...\"", lfname); more(); + } ndone++; } } diff --git a/map.c b/map.c index f2d1b24..31eff12 100644 --- a/map.c +++ b/map.c @@ -4054,6 +4054,9 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex // be created on this map. map->nfixedrooms++; break; + case RT_LF: + if (db) dblog(" (lifeform)"); + break; default: break; } @@ -4083,7 +4086,7 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex map->nrooms = 0; // reset room counts // place forced vaults. - if (db) dblog(" adding forced vaults first..."); + if (db) dblog(" adding forced things first..."); for (i = 0; i < nthings ;i++) { vault_t *v = NULL; @@ -6606,6 +6609,14 @@ regionoutline_t *findoutline(int id) { return NULL; } +regionoutline_t *findoutlineforbranch(enum BRANCH bid) { + regionoutline_t *ro; + for (ro = firstregionoutline ;ro ; ro = ro->next) { + if (ro->rtype->id == bid) return ro; + } + return NULL; +} + branch_t *findrandombranchwithname(char *name) { branch_t *rt,*poss[MAXCANDIDATES]; int nposs = 0; @@ -7401,8 +7412,23 @@ void initmaplayout(void) { int i; int lastlevel; branch_t *rt; + race_t *r; + flagpile_t *uniquelfs = NULL; + flag_t *f; // MAPMAPMAPMAP + + // make a list of unique monsters which will appear + uniquelfs = addflagpile(NULL, NULL); + for (r = firstrace ; r ; r = r->next) { + f = hasflag(r->flags, F_UNIQUE); + if (f && (f->val[0] > 0) && pctchance(f->val[0])) { + addflag(uniquelfs, f->id, f->val[0], f->val[1], r->id, f->text); + } + } + + + rt = findbranch(BH_MAINDUNGEON); lastlevel = rt->maxdepth; // region definitions (outlines) @@ -7486,6 +7512,24 @@ void initmaplayout(void) { // add initial regions addregion(BH_WORLDMAP, NULL, -1, 0, -1); addregion(BH_HEAVEN, NULL, -1, 0, -1); + + // add remembered unique lfs + for (f = uniquelfs->first ; f ; f = f->next) { + regionoutline_t *ro; + ro = findoutlineforbranch(f->val[1]); + if (ro) { + race_t *r; + int wantdepth; + wantdepth = parserange(f->text); + r = findrace(f->val[2]); + if (r) { + addregionthing(ro, wantdepth, NA, NA, RT_LF, 1, r->name); + } + } + + } + + killflagpile(uniquelfs); } int isadjacent(cell_t *src, cell_t *dst) { diff --git a/map.h b/map.h index bbe7ad0..57898a0 100644 --- a/map.h +++ b/map.h @@ -113,6 +113,7 @@ cell_t *findmapentrypoint(map_t *m, int side, lifeform_t *lf); object_t *findobidinmap(map_t *m, long id); cell_t *findobinmap(map_t *m, enum OBTYPE oid); regionoutline_t *findoutline(int id); +regionoutline_t *findoutlineforbranch(enum BRANCH bid); branch_t *findrandombranchwithname(char *name); region_t *findregion(int regionid); region_t *findregionbytype(enum BRANCH rtid); diff --git a/nexus.c b/nexus.c index ef8876a..f3d0ba0 100644 --- a/nexus.c +++ b/nexus.c @@ -2073,8 +2073,8 @@ void timeeffectsworld(map_t *map, int updategametime) { if (h == 0) { cell_t *c; // lunar gate appears in a random spot on the player's level - //c = getrandomroomcell(map, ANYROOM, WE_WALKABLE); - c = getrandomadjcell(player->cell, WE_WALKABLE, B_ALLOWEXPAND); + c = getrandomroomcell(map, ANYROOM, WE_WALKABLE); + //c = getrandomadjcell(player->cell, WE_WALKABLE, B_ALLOWEXPAND); if (c) { o = addobfast(c->obpile, OT_LUNARGATE); if (o) { diff --git a/objects.c b/objects.c index 64f2f7d..99affef 100644 --- a/objects.c +++ b/objects.c @@ -728,6 +728,10 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum addflag(wantflags, F_HOT, 3, NA, NA, "1d4"); p += strlen("red-hot "); donesomething = B_TRUE; + } else if (strstarts(p, "vorpal ")) { + addflag(wantflags, F_ARMOURPIERCE, 10, NA, NA, NULL); + p += strlen("vorpal "); + donesomething = B_TRUE; // generic linkflags } else if (strstarts(p, "linkrace:")) { char racename[BUFLEN]; @@ -5671,6 +5675,10 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan if (hasflagknown(o->flags, F_HOT)) { strcat(localbuf, "red-hot "); } + + if (hasflagknown(o->flags, F_ARMOURPIERCE) && !hasflag(o->type->flags, F_ARMOURPIERCE)) { + strcat(localbuf, "vorpal "); + } } // enchantments diff --git a/spell.c b/spell.c index 7d41f17..425967d 100644 --- a/spell.c +++ b/spell.c @@ -7610,6 +7610,81 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ msg("%s glows for a moment.",buf); if (seenbyplayer) *seenbyplayer = B_TRUE; } + } else if (spellid == OT_S_HONEMETAL) { + object_t *o; + int donesomething = B_FALSE; + flag_t *f; + char fullobname[BUFLEN]; + char obname[BUFLEN]; + + if (targob) { + o = targob; + } else { + // ask for an object + o = doaskobject(caster->pack, "Hone which metal weapon", NULL, NULL, B_FALSE, B_FALSE, B_FALSE, '\0', NULL, SA_NONE, MT_METAL, AO_WEILDABLE, F_NONE); + } + if (!o) { + fizzle(caster); + return B_TRUE; + } + + if (!wepdullable(o)) { + fizzle(caster); + return B_TRUE; + } + + getobname(o, obname, o->amt); + + if (isplayer(caster)) { + snprintf(fullobname, BUFLEN, "Your %s", noprefix(obname)); + } else if (cansee(player, caster)) { + snprintf(fullobname, BUFLEN, "%s%s %s", castername, getpossessive(castername), noprefix(obname)); + } else { + strcpy(fullobname, ""); + } + + f = hasflag(o->flags, F_IMMUTABLE); + if (!f) { + f = hasflag(o->flags, F_ARMOURPIERCE); + } + 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 = addtempflag(o->flags, F_ARMOURPIERCE, 5+power, NA, NA, NULL, (power == 3) ? PERMENANT : 20*power); + if (f) { + donesomething = B_TRUE; + } + + // fix rust and dulled weapons + if (isweapon(o)) { + f = hasflag(o->flags, F_BONUS); + if (f && (f->val[0] < 0)) { + killflag(f); + if (isplayer(caster) || cansee(player, caster)) msg("%s seems more effective!", fullobname); + donesomething = B_TRUE; + } + } + if (killflagsofid(o->flags, F_RUSTED)) { + if (isplayer(caster) || cansee(player, caster)) msg("%s is no longer rusted!", fullobname); + donesomething = B_TRUE; + } + + if (donesomething) { + if (strlen(fullobname)) { + if (seenbyplayer) *seenbyplayer = B_TRUE; + } + } else { + if (isplayer(caster)) nothinghappens(); + return B_TRUE; + } } else if (spellid == OT_S_HUNGER) { target = targcell->lf; if (!target) { @@ -9846,11 +9921,13 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ // fix rust and dulled weapons if (!iscursed(o)) { - f = hasflag(o->flags, F_BONUS); - if (f && (f->val[0] < 0)) { - killflag(f); - if (isplayer(caster) || cansee(player, caster)) msg("%s seems more effective!", fullobname); - donesomething = B_TRUE; + if (isweapon(o)) { + f = hasflag(o->flags, F_BONUS); + if (f && (f->val[0] < 0)) { + killflag(f); + if (isplayer(caster) || cansee(player, caster)) msg("%s seems more effective!", fullobname); + donesomething = B_TRUE; + } } if (killflagsofid(o->flags, F_RUSTED)) { if (isplayer(caster) || cansee(player, caster)) msg("%s is no longer rusted!", fullobname); @@ -10730,6 +10807,79 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ f = addtempflag(caster->flags, F_SEEINVIS, B_TRUE, NA, NA, NULL, FROMSPELL); f->obfrom = spellid; + } else if (spellid == OT_S_SHAPEMETAL) { + object_t *o; + int donesomething = B_FALSE; + flag_t *f; + char fullobname[BUFLEN]; + char obname[BUFLEN]; + + if (targob) { + o = targob; + } else { + // ask for an object + o = doaskobject(caster->pack, "Repair which metal object", NULL, NULL, B_FALSE, B_FALSE, B_FALSE, '\0', NULL, SA_NONE, MT_METAL, AO_NONE, F_NONE); + } + if (!o) { + fizzle(caster); + return B_TRUE; + } + + getobname(o, obname, o->amt); + + if (isplayer(caster)) { + snprintf(fullobname, BUFLEN, "Your %s", noprefix(obname)); + } else if (cansee(player, caster)) { + snprintf(fullobname, BUFLEN, "%s%s %s", castername, getpossessive(castername), noprefix(obname)); + } else { + 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 (isdamaged(o)) { + f->val[0] = f->val[1]; + + if (isplayer(caster) || cansee(player, caster)) msg("%s is completely repaired!", fullobname); + donesomething = B_TRUE; + } + + } + + // fix rust and dulled weapons + if (isweapon(o)) { + f = hasflag(o->flags, F_BONUS); + if (f && (f->val[0] < 0)) { + killflag(f); + if (isplayer(caster) || cansee(player, caster)) msg("%s seems more effective!", fullobname); + donesomething = B_TRUE; + } + } + if (killflagsofid(o->flags, F_RUSTED)) { + if (isplayer(caster) || cansee(player, caster)) msg("%s is no longer rusted!", fullobname); + donesomething = B_TRUE; + } + + if (donesomething) { + if (strlen(fullobname)) { + if (seenbyplayer) *seenbyplayer = B_TRUE; + } + } else { + if (isplayer(caster)) nothinghappens(); + return B_TRUE; + } } else if (spellid == OT_S_SHARDSHOT) { cell_t *retcell[MAXRETCELLS]; int nretcells; diff --git a/text.c b/text.c index a222cd4..a1e6d8b 100644 --- a/text.c +++ b/text.c @@ -2241,6 +2241,18 @@ char *numtotext(int num, char *buf) { return buf; } +// returns a value in the range specified by rangetext ("xx-yy") +int parserange(char *rangetext) { + int min,max; + char buf[BUFLEN]; + char *p; + p = readuntil(buf, rangetext, '-'); + min = atoi(buf); + readuntil(buf, p, '^'); // really EOL + max = atoi(buf); + return rnd(min,max); +} + // returns posiiton AFTER end of copied text, or NULL on failure. char *readuntil(char *retbuf, char *src, char delim) { char *bp,*p; diff --git a/text.h b/text.h index a6b3600..885c172 100644 --- a/text.h +++ b/text.h @@ -64,6 +64,7 @@ char *makewearstringsingle(lifeform_t *lf, flag_t *f, char *yourbuf, char *posbu int needses(char *text); char *noprefix(char *obname); char *numtotext(int num, char *buf); +int parserange(char *rangetext); char *readuntil(char *retbuf, char *src, char delim); char *roman(int num); int speedtokph(int speed);