]> granicus.if.org Git - nethack/commitdiff
Unify ad_dren
authorPasi Kallinen <paxed@alt.org>
Mon, 30 Nov 2020 17:32:53 +0000 (19:32 +0200)
committerPasi Kallinen <paxed@alt.org>
Fri, 4 Dec 2020 07:30:14 +0000 (09:30 +0200)
include/extern.h
src/mhitm.c
src/mhitu.c
src/uhitm.c

index e45fcdbd32c20fa47a6047fbae8e2009c2b1749e..cf5f18597efde67e09150126658577ba47d47be8 100644 (file)
@@ -2758,6 +2758,7 @@ E boolean FDECL(shade_miss, (struct monst *, struct monst *, struct obj *,
 E void FDECL(mhitm_ad_rust, (struct monst *, struct attack *, struct monst *, struct mhitm_data *));
 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 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,
index 875884b3779b089db8c2c4ae1e185407410fae74..90cf855e8dfae7b8d36b070ba1f2761d19dea69d 100644 (file)
@@ -1364,10 +1364,9 @@ int dieroll;
         mhm.damage = 0;
         break;
     case AD_DREN:
-        if (!cancelled && !rn2(4))
-            xdrainenergym(mdef, (boolean) (g.vis && canspotmon(mdef)
-                                           && mattk->aatyp != AT_ENGL));
-        mhm.damage = 0;
+        mhitm_ad_dren(magr, mattk, mdef, &mhm);
+        if (mhm.done)
+            return mhm.hitflags;
         break;
     case AD_DRST:
     case AD_DRDX:
index ec898880704c7c00573e02467c4afa94d96066f2..c8567e1142c35bcd548a416f148946da1a66c88a 100644 (file)
@@ -1611,10 +1611,9 @@ register struct attack *mattk;
             u_slow_down();
         break;
     case AD_DREN:
-        hitmsg(mtmp, mattk);
-        if (uncancelled && !rn2(4)) /* 25% chance */
-            drain_en(mhm.damage);
-        mhm.damage = 0;
+        mhitm_ad_dren(mtmp, mattk, &g.youmonst, &mhm);
+        if (mhm.done)
+            return mhm.hitflags;
         break;
     case AD_CONF:
         hitmsg(mtmp, mattk);
index 859122d6fd52e9f292c12a7e161d4d11629db0c1..7bd27ee0a0b8c19ad5c28eb8a600c0339b1e5822 100644 (file)
@@ -1832,6 +1832,50 @@ struct mhitm_data *mhm;
     }
 }
 
+void
+mhitm_ad_dren(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(4))
+            xdrainenergym(mdef, TRUE);
+        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);
+
+        hitmsg(magr, mattk);
+        if (uncancelled && !rn2(4)) /* 25% chance */
+            drain_en(mhm->damage);
+        mhm->damage = 0;
+    } else {
+        /* mhitm */
+        /* cancellation factor is the same as when attacking the hero */
+        int armpro = magic_negation(mdef);
+        boolean cancelled = magr->mcan || !(rn2(10) >= 3 * armpro);
+
+        if (!cancelled && !rn2(4))
+            xdrainenergym(mdef, (boolean) (g.vis && canspotmon(mdef)
+                                           && mattk->aatyp != AT_ENGL));
+        mhm->damage = 0;
+    }
+}
+
 /* Template for monster hits monster for AD_FOO.
    - replace "break" with return
    - replace "return" with mhm->done = TRUE
@@ -2125,9 +2169,9 @@ int specialdmg; /* blessed and/or silver bonus against various things */
             return mhm.hitflags;
         break;
     case AD_DREN:
-        if (!negated && !rn2(4))
-            xdrainenergym(mdef, TRUE);
-        mhm.damage = 0;
+        mhitm_ad_dren(&g.youmonst, mattk, mdef, &mhm);
+        if (mhm.done)
+            return mhm.hitflags;
         break;
     case AD_DRST:
     case AD_DRDX: