From 8ed4b9aca0dcd28b4ccc70c9f53dc18dfcfe7e46 Mon Sep 17 00:00:00 2001 From: Rob Pearce Date: Tue, 31 May 2016 12:23:39 +1000 Subject: [PATCH] - new l2 death spell: "field of decay" - damage objects / lfs made from organic material - If not in battle, praying to Hecta will restore stamina / mana, and sometimes cast field of decay --- data.c | 11 +++++++- defs.h | 1 + god.c | 81 ++++++++++++++++++++++++++++++++++--------------------- objects.c | 17 ++++++++++++ objects.h | 1 + spell.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 6 files changed, 158 insertions(+), 32 deletions(-) diff --git a/data.c b/data.c index 01037e1..e85821b 100644 --- a/data.c +++ b/data.c @@ -4057,7 +4057,7 @@ void initobjects(void) { // death magic / necromancy /////////////////// // l1 - addot(OT_S_BLIGHT, "blight", "Covers the target location with a miasma of decay, tainting food and damaging living beings.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addot(OT_S_BLIGHT, "blight", "Covers the target location with a miasma of sickness, tainting food and damaging living beings.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines damage and amount of food affected."); addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); @@ -4094,6 +4094,15 @@ void initobjects(void) { addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); + addot(OT_S_DECAYFIELD, "field of decay", "Emits a circular field unnatural deterioration, causing damage to all organic matter.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines size of area affected."); + addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Deals ^bpower * 3^n damage to objects, half that to creatures."); + addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); + addflag(lastot->flags, F_MAXPOWER, 10, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL); + addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); + addflag(lastot->flags, F_PLEASESGOD, R_GODDEATH, 2, NA, NULL); addot(OT_S_COMMANDUNDEAD, "command undead", "Compels an undead creature to follow a single simple command.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines resistability."); addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); diff --git a/defs.h b/defs.h index 0113365..2d8d2f3 100644 --- a/defs.h +++ b/defs.h @@ -1926,6 +1926,7 @@ enum OBTYPE { OT_S_BLIGHT, OT_S_COMMANDUNDEAD, OT_S_CURSE, + OT_S_DECAYFIELD, OT_S_DEATHKEEN, OT_S_DRAINLIFE, OT_S_FEAR, diff --git a/god.c b/god.c index 648783a..7f8f5d7 100644 --- a/god.c +++ b/god.c @@ -2354,9 +2354,6 @@ int prayto(lifeform_t *lf, lifeform_t *god) { } } - // turn undead TODO: move this to 'life' god - castspell(god, OT_S_TURNUNDEAD, lf, NULL, NULL, NULL, NULL); - // remove all temporary bad status effects getflags(player->flags, retflag, &nretflags, F_BLIND, F_CONFUSED, F_DEAF, F_CAFFEINATED, F_DRUNK, F_FROZEN, F_GRABBEDBY, F_NAUSEATED, F_PAIN, F_POISONED, F_SLOWACT, F_SLOWMOVE, F_SLOWACTMOVE, F_NONE); @@ -2428,39 +2425,60 @@ int prayto(lifeform_t *lf, lifeform_t *god) { } break; case R_GODDEATH: - msg("\"Behold, the power of death!\""); - n = OT_NONE; - switch (rnd(0,1)) { - case 0: n = OT_S_FLAYFLESH; break; - case 1: n = OT_S_HECTASSERVANT; break; - } - for (i = 1; i < lf->nlos; i++) { - lifeform_t *who; - who = lf->los[i]->lf; - if (who && !areallies(lf, who)) { - if (isundead(who)) { - makepeaceful(who, god); - } else if (gettr(who) <= 5) { - // instakill - who->lastdamtype = DT_NECROTIC; - setlastdam(who, "Hecta's finger of death."); - who->hp = 0; - } else if (n != OT_NONE) { - if (n == OT_S_HECTASSERVANT) { - c = getrandomadjcell(player->cell, &ccwalkable, B_ALLOWEXPAND); - if (c) { - castspell(god, n, player, NULL, c, NULL, NULL); + if (isinbattle(lf, B_INCLUDEDISTANT, B_FALSE)) { + msg("\"Behold, the power of death!\""); + n = OT_NONE; + switch (rnd(0,1)) { + case 0: n = OT_S_FLAYFLESH; break; + case 1: n = OT_S_HECTASSERVANT; break; + } + + for (i = 1; i < lf->nlos; i++) { + lifeform_t *who; + who = lf->los[i]->lf; + if (who && !areallies(lf, who)) { + if (isundead(who)) { + makepeaceful(who, god); + } else if (gettr(who) <= 5) { + // instakill + who->lastdamtype = DT_NECROTIC; + setlastdam(who, "Hecta's finger of death."); + who->hp = 0; + } else if (n != OT_NONE) { + if (n == OT_S_HECTASSERVANT) { + c = getrandomadjcell(player->cell, &ccwalkable, B_ALLOWEXPAND); + if (c) { + castspell(god, n, player, NULL, c, NULL, NULL); + } + n = OT_S_DRAINLIFE; + } else { + dospelleffects(god, n, 20, who, NULL, who->cell, B_UNCURSED, NULL, B_FALSE, NULL); } - n = OT_S_DRAINLIFE; - } else { - dospelleffects(god, n, 20, who, NULL, who->cell, B_UNCURSED, NULL, B_FALSE, NULL); + break; } - break; } } + // animate dead + dospelleffects(god, OT_S_ANIMATEDEAD, 10, lf, NULL, lf->cell, B_UNCURSED, NULL, B_TRUE, NULL); + } else { + // restore mana or stamina + if (lf->mp < getmaxmp(lf)) { + gainmp(lf, getmaxmp(lf)); + msg("An unholy energy revitalises your mind!"); + } else if (getstamina(player) <= getmaxstamina(player)) { + setstamina(player, getmaxstamina(player)); + msg("An unholy energy revitalises your muscles!"); + } + + if (rnd(1,2) == 1) { + // kill trees / decay wooden objects around you + dospelleffects(god, OT_S_DECAYFIELD, 10, NULL, NULL, lf->cell, B_UNCURSED, NULL, B_FALSE, NULL); + } + + // animate dead + dospelleffects(god, OT_S_ANIMATEDEAD, 10, lf, NULL, lf->cell, B_UNCURSED, NULL, B_TRUE, NULL); } - dospelleffects(god, OT_S_ANIMATEDEAD, 10, lf, NULL, lf->cell, B_UNCURSED, NULL, B_TRUE, NULL); break; case R_GODFIRE: // restore frozen weapons @@ -2515,6 +2533,9 @@ int prayto(lifeform_t *lf, lifeform_t *god) { statdirty = B_TRUE; } if (isinbattle(lf, B_INCLUDEDISTANT, B_FALSE)) { + // turn undead + castspell(god, OT_S_TURNUNDEAD, lf, NULL, NULL, NULL, NULL); + if (plev >= PL_INDIFFERENT) { int pow; pow = plev + 1; diff --git a/objects.c b/objects.c index 8d980d8..6ba7301 100644 --- a/objects.c +++ b/objects.c @@ -8225,6 +8225,23 @@ int istempobpile(obpile_t *op) { return B_FALSE; } +int isorganicmat(enum MATERIAL mat) { + int organic = B_FALSE; + switch (mat) { + case MT_FLESH: + case MT_WOOD: + case MT_LEATHER: + case MT_PLANT: + organic = B_TRUE; + break; + default: + organic = B_FALSE; + break; + } + return organic; +} + + int isthrowmissile(object_t *o) { if (hasflag(o->flags, F_THROWMISSILE)) { return B_TRUE; diff --git a/objects.h b/objects.h index 3211b22..c7b8be3 100644 --- a/objects.h +++ b/objects.h @@ -215,6 +215,7 @@ int ismagicalobtype(objecttype_t *ot); int ismagical(object_t *o); int ismeleeweapon(object_t *o); int ismetal(enum MATERIAL mat); +int isorganicmat(enum MATERIAL mat); int isthrowmissile(object_t *o); int isvalidoverridemat(enum MATERIAL mat); int isinroof(object_t *o); diff --git a/spell.c b/spell.c index ba62078..a7c9694 100644 --- a/spell.c +++ b/spell.c @@ -4948,7 +4948,6 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } else { strcpy(damstr, "a blight spell."); } - losehp(targcell->lf, dam, DT_DECAY, caster, damstr); if (isplayer(targcell->lf)) { msg("^%cA blight courses through your veins!", getlfcol(targcell->lf, CC_BAD)); } else if (cansee(player, targcell->lf)) { @@ -4956,6 +4955,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ getlfname(targcell->lf, tname); msg("%s looks unwell.", tname); } + losehp(targcell->lf, dam, DT_DECAY, caster, damstr); } } else { op = targcell->obpile; @@ -6326,6 +6326,83 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ msg("A cloud of darkness descends on you!"); if (seenbyplayer) *seenbyplayer = B_TRUE; } + } else if (spellid == OT_S_DECAYFIELD) { + obpile_t *op; + object_t *o,*nexto; + int range = 0, ncells,i,lfdam,obdam,walldam; + cell_t *cell[MAXCANDIDATES]; + + // default to radiating out from the caster's cell + if (!targcell) { + if (caster) { + targcell = caster->cell; + } else { + // fail + return B_TRUE; + } + } + + // determine damage (will do double this to object) + lfdam = (power*3)/2; + obdam = power*3; + walldam = power*5; + + // determine radius + range = (power/2)+1; + + // announce + if (caster && (targcell == caster->cell)) { + sprintf(buf, "%s radiate%s a field of decay!",castername,isplayer(caster) ? "" : "s"); + } else { + sprintf(buf, "A field of decay radiates outwards!"); + } + animradial(targcell, range, '}', C_INDIGO, DT_ORTH, buf, "Something radiates a field of decay!"); + + // don't affect centre cell + getradiuscells(targcell, range, DT_COMPASS, B_FALSE, LOF_DONTNEED, B_FALSE, cell, &ncells, B_FALSE); + for (i = 0; i < ncells; i++) { + if (seenbyplayer) { + if (haslos(player, targcell)) { + *seenbyplayer = B_TRUE; + } + } + + if (cell[i]->lf && isorganicmat(getlfmaterial(cell[i]->lf))) { + char damstr[BUFLEN]; + if (caster) { + char cname[BUFLEN]; + real_getlfnamea(caster, cname, NULL, B_SHOWALL, B_REALRACE); + sprintf(damstr, "%s%s field of decay spell.", cname, getpossessive(cname)); + } else { + strcpy(damstr, "a field of decay spell."); + } + if (isplayer(cell[i]->lf)) { + msg("^%cPieces of your body decay away!", getlfcol(cell[i]->lf, CC_BAD)); + } else if (cansee(player, cell[i]->lf)) { + char tname[BUFLEN]; + getlfname(targcell->lf, tname); + msg("Pieces of %s decay away!", tname); + } + losehp(cell[i]->lf, lfdam, DT_DECAY, caster, damstr); + } + op = cell[i]->obpile; + // damage all organic objects here + for (o = op->first ; o ; o = nexto) { + nexto = o->next; + if (isorganicmat(o->material->id)) { + if (!cell[i]->lf && haslos(player, cell[i])) { + char obname[BUFLEN]; + getobname(o, obname, o->amt); + msg("%s decays!", obname); + } + takedamage(o, obdam, DT_DECAY, caster); + } + } + // damage all organic walls here + if (isorganicmat(cell[i]->type->material->id)) { + damagecell(cell[i], walldam, DT_DECAY, caster); + } + } } else if (spellid == OT_S_DEATHKEEN) { if (!isnighttime()) { fizzle(caster);