From: Pasi Kallinen Date: Mon, 30 Nov 2020 17:43:16 +0000 (+0200) Subject: Unify ad_drli X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cfd819f1c178bdb622307329b821ef26cfc267c5;p=nethack Unify ad_drli --- diff --git a/include/extern.h b/include/extern.h index cf5f18597..2607c69b0 100644 --- a/include/extern.h +++ b/include/extern.h @@ -2759,6 +2759,7 @@ E void FDECL(mhitm_ad_rust, (struct monst *, struct attack *, struct monst *, st E void FDECL(mhitm_ad_corr, (struct monst *, struct attack *, struct monst *, struct mhitm_data *)); E void FDECL(mhitm_ad_dcay, (struct monst *, struct attack *, struct monst *, struct mhitm_data *)); E void FDECL(mhitm_ad_dren, (struct monst *, struct attack *, struct monst *, struct mhitm_data *)); +E void FDECL(mhitm_ad_drli, (struct monst *, struct attack *, struct monst *, struct mhitm_data *)); E int FDECL(damageum, (struct monst *, struct attack *, int)); E void FDECL(missum, (struct monst *, struct attack *, BOOLEAN_P)); E int FDECL(passive, (struct monst *, struct obj *, BOOLEAN_P, int, diff --git a/src/mhitm.c b/src/mhitm.c index 90cf855e8..4850e3195 100644 --- a/src/mhitm.c +++ b/src/mhitm.c @@ -1286,26 +1286,9 @@ int dieroll; } break; case AD_DRLI: /* drain life */ - if (!cancelled && !rn2(3) && !resists_drli(mdef)) { - mhm.damage = d(2, 6); /* Stormbringer uses monhp_per_lvl(usually 1d8) */ - if (g.vis && canspotmon(mdef)) - pline("%s becomes weaker!", Monnam(mdef)); - if (mdef->mhpmax - mhm.damage > (int) mdef->m_lev) { - mdef->mhpmax -= mhm.damage; - } else { - /* limit floor of mhpmax reduction to current m_lev + 1; - avoid increasing it if somehow already less than that */ - if (mdef->mhpmax > (int) mdef->m_lev) - mdef->mhpmax = (int) mdef->m_lev + 1; - } - if (mdef->m_lev == 0) /* automatic kill if drained past level 0 */ - mhm.damage = mdef->mhp; - else - mdef->m_lev--; - - /* unlike hitting with Stormbringer, wounded attacker doesn't - heal any from the drained life */ - } + mhitm_ad_drli(magr, mattk, mdef, &mhm); + if (mhm.done) + return mhm.hitflags; break; case AD_SSEX: case AD_SITM: /* for now these are the same */ diff --git a/src/mhitu.c b/src/mhitu.c index c8567e114..0c4dde885 100644 --- a/src/mhitu.c +++ b/src/mhitu.c @@ -1242,13 +1242,9 @@ register struct attack *mattk; } break; case AD_DRLI: /* drain life */ - hitmsg(mtmp, mattk); - if (uncancelled && !rn2(3) && !Drain_resistance) { - losexp("life drainage"); - - /* unlike hitting with Stormbringer, wounded attacker doesn't - heal any from the drained life */ - } + mhitm_ad_drli(mtmp, mattk, &g.youmonst, &mhm); + if (mhm.done) + return mhm.hitflags; break; case AD_LEGS: { long side = rn2(2) ? RIGHT_SIDE : LEFT_SIDE; diff --git a/src/uhitm.c b/src/uhitm.c index 7bd27ee0a..88ce1958b 100644 --- a/src/uhitm.c +++ b/src/uhitm.c @@ -1852,10 +1852,6 @@ struct mhitm_data *mhm; mhm->damage = 0; } else if (mdef == &g.youmonst) { /* mhitu */ - /* Next a cancellation factor. - * Use uncancelled when cancellation factor takes into account certain - * armor's special magic protection. Otherwise just use !mtmp->mcan. - */ int armpro = magic_negation(mdef); boolean uncancelled = !magr->mcan && (rn2(10) >= 3 * armpro); @@ -1876,6 +1872,87 @@ struct mhitm_data *mhm; } } +void +mhitm_ad_drli(magr, mattk, mdef, mhm) +struct monst *magr; +struct attack *mattk; +struct monst *mdef; +struct mhitm_data *mhm; +{ + struct permonst *pd = mdef->data; + + if (magr == &g.youmonst) { + /* uhitm */ + int armpro = magic_negation(mdef); + /* since hero can't be cancelled, only defender's armor applies */ + boolean negated = !(rn2(10) >= 3 * armpro); + + if (!negated && !rn2(3) && !resists_drli(mdef)) { + mhm->damage = d(2, 6); /* Stormbringer uses monhp_per_lvl(usually 1d8) */ + pline("%s becomes weaker!", Monnam(mdef)); + if (mdef->mhpmax - mhm->damage > (int) mdef->m_lev) { + mdef->mhpmax -= mhm->damage; + } else { + /* limit floor of mhpmax reduction to current m_lev + 1; + avoid increasing it if somehow already less than that */ + if (mdef->mhpmax > (int) mdef->m_lev) + mdef->mhpmax = (int) mdef->m_lev + 1; + } + mdef->mhp -= mhm->damage; + /* !m_lev: level 0 monster is killed regardless of hit points + rather than drop to level -1; note: some non-living creatures + (golems, vortices) are subject to life-drain */ + if (DEADMONSTER(mdef) || !mdef->m_lev) { + pline("%s %s!", Monnam(mdef), + nonliving(mdef->data) ? "expires" : "dies"); + xkilled(mdef, XKILL_NOMSG); + } else + mdef->m_lev--; + mhm->damage = 0; /* damage has already been inflicted */ + + /* unlike hitting with Stormbringer, wounded hero doesn't + heal any from the drained life */ + } + } else if (mdef == &g.youmonst) { + /* mhitu */ + int armpro = magic_negation(mdef); + boolean uncancelled = !magr->mcan && (rn2(10) >= 3 * armpro); + + hitmsg(magr, mattk); + if (uncancelled && !rn2(3) && !Drain_resistance) { + losexp("life drainage"); + + /* unlike hitting with Stormbringer, wounded attacker doesn't + heal any from the drained life */ + } + } else { + /* mhitm */ + int armpro = magic_negation(mdef); + boolean cancelled = magr->mcan || !(rn2(10) >= 3 * armpro); + + if (!cancelled && !rn2(3) && !resists_drli(mdef)) { + mhm->damage = d(2, 6); /* Stormbringer uses monhp_per_lvl(usually 1d8) */ + if (g.vis && canspotmon(mdef)) + pline("%s becomes weaker!", Monnam(mdef)); + if (mdef->mhpmax - mhm->damage > (int) mdef->m_lev) { + mdef->mhpmax -= mhm->damage; + } else { + /* limit floor of mhpmax reduction to current m_lev + 1; + avoid increasing it if somehow already less than that */ + if (mdef->mhpmax > (int) mdef->m_lev) + mdef->mhpmax = (int) mdef->m_lev + 1; + } + if (mdef->m_lev == 0) /* automatic kill if drained past level 0 */ + mhm->damage = mdef->mhp; + else + mdef->m_lev--; + + /* unlike hitting with Stormbringer, wounded attacker doesn't + heal any from the drained life */ + } + } +} + /* Template for monster hits monster for AD_FOO. - replace "break" with return - replace "return" with mhm->done = TRUE @@ -2126,32 +2203,9 @@ int specialdmg; /* blessed and/or silver bonus against various things */ mhm.damage = 0; break; case AD_DRLI: /* drain life */ - if (!negated && !rn2(3) && !resists_drli(mdef)) { - mhm.damage = d(2, 6); /* Stormbringer uses monhp_per_lvl(usually 1d8) */ - pline("%s becomes weaker!", Monnam(mdef)); - if (mdef->mhpmax - mhm.damage > (int) mdef->m_lev) { - mdef->mhpmax -= mhm.damage; - } else { - /* limit floor of mhpmax reduction to current m_lev + 1; - avoid increasing it if somehow already less than that */ - if (mdef->mhpmax > (int) mdef->m_lev) - mdef->mhpmax = (int) mdef->m_lev + 1; - } - mdef->mhp -= mhm.damage; - /* !m_lev: level 0 monster is killed regardless of hit points - rather than drop to level -1; note: some non-living creatures - (golems, vortices) are subject to life-drain */ - if (DEADMONSTER(mdef) || !mdef->m_lev) { - pline("%s %s!", Monnam(mdef), - nonliving(mdef->data) ? "expires" : "dies"); - xkilled(mdef, XKILL_NOMSG); - } else - mdef->m_lev--; - mhm.damage = 0; /* damage has already been inflicted */ - - /* unlike hitting with Stormbringer, wounded hero doesn't - heal any from the drained life */ - } + mhitm_ad_drli(&g.youmonst, mattk, mdef, &mhm); + if (mhm.done) + return mhm.hitflags; break; case AD_RUST: mhitm_ad_rust(&g.youmonst, mattk, mdef, &mhm);