]> granicus.if.org Git - nethack/commitdiff
Unify ad_phys
authorPasi Kallinen <paxed@alt.org>
Tue, 1 Dec 2020 07:07:44 +0000 (09:07 +0200)
committerPasi Kallinen <paxed@alt.org>
Fri, 4 Dec 2020 07:30:19 +0000 (09:30 +0200)
include/extern.h
include/monattk.h
src/mhitm.c
src/mhitu.c
src/uhitm.c

index 4f4b9a2a3c87fa3a3f9e5265a80c89947c543df1..59982f23042b6e7a121450eff1937a42a02b79b6 100644 (file)
@@ -2785,6 +2785,9 @@ E void FDECL(mhitm_ad_famn, (struct monst *, struct attack *, struct monst *, st
 E void FDECL(mhitm_ad_pest, (struct monst *, struct attack *, struct monst *, struct mhitm_data *));
 E void FDECL(mhitm_ad_deth, (struct monst *, struct attack *, struct monst *, struct mhitm_data *));
 E void FDECL(mhitm_ad_halu, (struct monst *, struct attack *, struct monst *, struct mhitm_data *));
+E void FDECL(mhitm_ad_phys, (struct monst *, struct attack *, struct monst *, struct mhitm_data *));
+E boolean FDECL(do_stone_u, (struct monst *));
+E void FDECL(do_stone_mon, (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 0ea507b211d07fb70c219503056846984c558b6e..b78ec6fe6796fb1acc159c44ab40c6dd9ac23ea3 100644 (file)
@@ -91,6 +91,8 @@ struct mhitm_data {
     int hitflags; /* MM_DEF_DIED | MM_AGR_DIED | ... */
     boolean done;
     boolean permdmg;
+    int specialdmg;
+    int dieroll;
 };
 
 /*
index 9c9e89bec7f726104c639cbc2e87b08880d7faed..d7f9a6dbe438da3e5b089694596a318eb30d3a2b 100644 (file)
@@ -864,6 +864,8 @@ int dieroll;
     mhm.damage = d((int) mattk->damn, (int) mattk->damd);
     mhm.hitflags = MM_MISS;
     mhm.permdmg = 0;
+    mhm.specialdmg = 0;
+    mhm.dieroll = dieroll;
 
     if ((touch_petrifies(pd) /* or flesh_petrifies() */
          || (mattk->adtyp == AD_DGST && pd == &mons[PM_MEDUSA]))
@@ -965,56 +967,9 @@ int dieroll;
     case AD_HEAL:
     case AD_PHYS:
  physical:
-        if (mattk->aatyp != AT_WEAP && mattk->aatyp != AT_CLAW)
-            mwep = 0;
-
-        if (shade_miss(magr, mdef, mwep, FALSE, TRUE)) {
-            mhm.damage = 0;
-        } else if (mattk->aatyp == AT_KICK && thick_skinned(pd)) {
-            /* [no 'kicking boots' check needed; monsters with kick attacks
-               can't wear boots and monsters that wear boots don't kick] */
-            mhm.damage = 0;
-        } else if (mwep) { /* non-Null 'mwep' implies AT_WEAP || AT_CLAW */
-            struct obj *marmg;
-
-            if (mwep->otyp == CORPSE
-                && touch_petrifies(&mons[mwep->corpsenm]))
-                goto do_stone;
-
-            mhm.damage += dmgval(mwep, mdef);
-            if ((marmg = which_armor(magr, W_ARMG)) != 0
-                && marmg->otyp == GAUNTLETS_OF_POWER)
-                mhm.damage += rn1(4, 3); /* 3..6 */
-            if (mhm.damage < 1) /* is this necessary?  mhitu.c has it... */
-                mhm.damage = 1;
-            if (mwep->oartifact) {
-                /* when magr's weapon is an artifact, caller suppressed its
-                   usual 'hit' message in case artifact_hit() delivers one;
-                   now we'll know and might need to deliver skipped message
-                   (note: if there's no message there'll be no auxilliary
-                   damage so the message here isn't coming too late) */
-                if (!artifact_hit(magr, mdef, mwep, &mhm.damage, dieroll)) {
-                    if (g.vis)
-                        pline("%s hits %s.", Monnam(magr),
-                              mon_nam_too(mdef, magr));
-                }
-                /* artifact_hit updates 'tmp' but doesn't inflict any
-                   damage; however, it might cause carried items to be
-                   destroyed and they might do so */
-                if (DEADMONSTER(mdef))
-                    return (MM_DEF_DIED
-                            | (grow_up(magr, mdef) ? 0 : MM_AGR_DIED));
-            }
-            if (mhm.damage)
-                rustm(mdef, mwep);
-        } else if (pa == &mons[PM_PURPLE_WORM] && pd == &mons[PM_SHRIEKER]) {
-            /* hack to enhance mm_aggression(); we don't want purple
-               worm's bite attack to kill a shrieker because then it
-               won't swallow the corpse; but if the target survives,
-               the subsequent engulf attack should accomplish that */
-            if (mhm.damage >= mdef->mhp && mdef->mhp > 1)
-                mhm.damage = mdef->mhp - 1;
-        }
+        mhitm_ad_phys(magr, mattk, mdef, &mhm);
+        if (mhm.done)
+            return mhm.hitflags;
         break;
     case AD_FIRE:
         mhitm_ad_fire(magr, mattk, mdef, &mhm);
@@ -1054,27 +1009,9 @@ int dieroll;
     case AD_STON:
         if (magr->mcan)
             break;
- do_stone:
-        /* may die from the acid if it eats a stone-curing corpse */
-        if (munstone(mdef, FALSE))
-            goto post_stone;
-        if (poly_when_stoned(pd)) {
-            mon_to_stone(mdef);
-            mhm.damage = 0;
-            break;
-        }
-        if (!resists_ston(mdef)) {
-            if (g.vis && canseemon(mdef))
-                pline("%s turns to stone!", Monnam(mdef));
-            monstone(mdef);
- post_stone:
-            if (!DEADMONSTER(mdef))
-                return 0;
-            else if (mdef->mtame && !g.vis)
-                You(brief_feeling, "peculiarly sad");
-            return (MM_DEF_DIED | (grow_up(magr, mdef) ? 0 : MM_AGR_DIED));
-        }
-        mhm.damage = (mattk->adtyp == AD_STON ? 0 : 1);
+        do_stone_mon(magr, mattk, mdef, &mhm);
+        if (mhm.done)
+            return mhm.hitflags;
         break;
     case AD_TLPT:
         mhitm_ad_tlpt(magr, mattk, mdef, &mhm);
index 614b3d9dec37777b36dfbdb7a8e09ee8e07710b7..5a3e69e42e869b32af80932b6207e5e55c2a6ce2 100644 (file)
@@ -974,6 +974,7 @@ register struct attack *mattk;
     struct mhitm_data mhm;
     mhm.hitflags = MM_MISS;
     mhm.permdmg = 0;
+    mhm.specialdmg = 0;
 
     if (!canspotmon(mtmp))
         map_invisible(mtmp->mx, mtmp->my);
@@ -1016,79 +1017,9 @@ register struct attack *mattk;
     /*  Now, adjust damages via resistances or specific attacks */
     switch (mattk->adtyp) {
     case AD_PHYS:
-        if (mattk->aatyp == AT_HUGS && !sticks(g.youmonst.data)) {
-            if (!u.ustuck && rn2(2)) {
-                if (u_slip_free(mtmp, mattk)) {
-                    mhm.damage = 0;
-                } else {
-                    set_ustuck(mtmp);
-                    pline("%s grabs you!", Monnam(mtmp));
-                }
-            } else if (u.ustuck == mtmp) {
-                exercise(A_STR, FALSE);
-                You("are being %s.", (mtmp->data == &mons[PM_ROPE_GOLEM])
-                                         ? "choked"
-                                         : "crushed");
-            }
-        } else { /* hand to hand weapon */
-            struct obj *otmp = mon_currwep;
-
-            if (mattk->aatyp == AT_WEAP && otmp) {
-                struct obj *marmg;
-                int tmp;
-
-                if (otmp->otyp == CORPSE
-                    && touch_petrifies(&mons[otmp->corpsenm])) {
-                    mhm.damage = 1;
-                    pline("%s hits you with the %s corpse.", Monnam(mtmp),
-                          mons[otmp->corpsenm].mname);
-                    if (!Stoned)
-                        goto do_stone;
-                }
-                mhm.damage += dmgval(otmp, &g.youmonst);
-                if ((marmg = which_armor(mtmp, W_ARMG)) != 0
-                    && marmg->otyp == GAUNTLETS_OF_POWER)
-                    mhm.damage += rn1(4, 3); /* 3..6 */
-                if (mhm.damage <= 0)
-                    mhm.damage = 1;
-                if (!(otmp->oartifact && artifact_hit(mtmp, &g.youmonst, otmp,
-                                                      &mhm.damage, g.mhitu_dieroll)))
-                    hitmsg(mtmp, mattk);
-                if (!mhm.damage)
-                    break;
-                if (objects[otmp->otyp].oc_material == SILVER
-                    && Hate_silver) {
-                    pline_The("silver sears your flesh!");
-                    exercise(A_CON, FALSE);
-                }
-                /* this redundancy necessary because you have
-                   to take the damage _before_ being cloned;
-                   need to have at least 2 hp left to split */
-                tmp = mhm.damage;
-                if (u.uac < 0)
-                    tmp -= rnd(-u.uac);
-                if (tmp < 1)
-                    tmp = 1;
-                if (u.mh - tmp > 1
-                    && (objects[otmp->otyp].oc_material == IRON
-                        /* relevant 'metal' objects are scalpel and tsurugi */
-                        || objects[otmp->otyp].oc_material == METAL)
-                    && (u.umonnum == PM_BLACK_PUDDING
-                        || u.umonnum == PM_BROWN_PUDDING)) {
-                    if (tmp > 1)
-                        exercise(A_STR, FALSE);
-                    /* inflict damage now; we know it can't be fatal */
-                    u.mh -= tmp;
-                    g.context.botl = 1;
-                    mhm.damage = 0; /* don't inflict more damage below */
-                    if (cloneu())
-                        You("divide as %s hits you!", mon_nam(mtmp));
-                }
-                rustm(&g.youmonst, otmp);
-            } else if (mattk->aatyp != AT_TUCH || mhm.damage != 0
-                       || mtmp != u.ustuck)
-                hitmsg(mtmp, mattk);
-        }
+        mhitm_ad_phys(mtmp, mattk, &g.youmonst, &mhm);
+        if (mhm.done)
+            return mhm.hitflags;
         break;
     case AD_DISE:
         hitmsg(mtmp, mattk);
@@ -1193,22 +1124,8 @@ register struct attack *mattk;
                     You_hear("%s hissing!", s_suffix(mon_nam(mtmp)));
                 if (!rn2(10)
                     || (flags.moonphase == NEW_MOON && !have_lizard())) {
- do_stone:
-                    if (!Stoned && !Stone_resistance
-                        && !(poly_when_stoned(g.youmonst.data)
-                             && polymon(PM_STONE_GOLEM))) {
-                        int kformat = KILLED_BY_AN;
-                        const char *kname = mtmp->data->mname;
-
-                        if (mtmp->data->geno & G_UNIQ) {
-                            if (!type_is_pname(mtmp->data))
-                                kname = the(kname);
-                            kformat = KILLED_BY;
-                        }
-                        make_stoned(5L, (char *) 0, kformat, kname);
-                        return 1;
-                        /* done_in_by(mtmp, STONING); */
-                    }
+                    if (do_stone_u(mtmp))
+                        return MM_HIT;
                 }
             }
         }
index 3213c8ff5a2dec2de1dbd473512b1afa240a2516..b377a5f355a033db95f56a272196340be6f3b008 100644 (file)
@@ -3348,6 +3348,258 @@ struct mhitm_data *mhm;
     }
 }
 
+boolean
+do_stone_u(mtmp)
+struct monst *mtmp;
+{
+    if (!Stoned && !Stone_resistance
+        && !(poly_when_stoned(g.youmonst.data)
+             && polymon(PM_STONE_GOLEM))) {
+        int kformat = KILLED_BY_AN;
+        const char *kname = mtmp->data->mname;
+
+        if (mtmp->data->geno & G_UNIQ) {
+            if (!type_is_pname(mtmp->data))
+                kname = the(kname);
+            kformat = KILLED_BY;
+        }
+        make_stoned(5L, (char *) 0, kformat, kname);
+        return 1;
+        /* done_in_by(mtmp, STONING); */
+    }
+    return 0;
+}
+
+void
+do_stone_mon(magr, mattk, mdef, mhm)
+struct monst *magr;
+struct attack *mattk;
+struct monst *mdef;
+struct mhitm_data *mhm;
+{
+    struct permonst *pa = magr->data;
+    struct permonst *pd = mdef->data;
+
+    /* may die from the acid if it eats a stone-curing corpse */
+    if (munstone(mdef, FALSE))
+        goto post_stone;
+    if (poly_when_stoned(pd)) {
+        mon_to_stone(mdef);
+        mhm->damage = 0;
+        return;
+    }
+    if (!resists_ston(mdef)) {
+        if (g.vis && canseemon(mdef))
+            pline("%s turns to stone!", Monnam(mdef));
+        monstone(mdef);
+ post_stone:
+        if (!DEADMONSTER(mdef)) {
+            mhm->hitflags = MM_MISS;
+            mhm->done = TRUE;
+            return;
+        }
+        else if (mdef->mtame && !g.vis)
+            You(brief_feeling, "peculiarly sad");
+        mhm->hitflags = (MM_DEF_DIED | (grow_up(magr, mdef) ? 0 : MM_AGR_DIED));
+        mhm->done = TRUE;
+        return;
+    }
+    mhm->damage = (mattk->adtyp == AD_STON ? 0 : 1);
+}
+
+void
+mhitm_ad_phys(magr, mattk, mdef, mhm)
+struct monst *magr;
+struct attack *mattk;
+struct monst *mdef;
+struct mhitm_data *mhm;
+{
+    struct permonst *pa = magr->data;
+    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 (pd == &mons[PM_SHADE]) {
+            mhm->damage = 0;
+            if (!mhm->specialdmg)
+                impossible("bad shade attack function flow?");
+        }
+        mhm->damage += mhm->specialdmg;
+
+        if (mattk->aatyp == AT_WEAP) {
+            /* hmonas() uses known_hitum() to deal physical damage,
+               then also damageum() for non-AD_PHYS; don't inflict
+               extra physical damage for unusual damage types */
+            mhm->damage = 0;
+        } else if (mattk->aatyp == AT_KICK
+                   || mattk->aatyp == AT_CLAW
+                   || mattk->aatyp == AT_TUCH
+                   || mattk->aatyp == AT_HUGS) {
+            if (thick_skinned(pd))
+                mhm->damage = (mattk->aatyp == AT_KICK) ? 0 : (mhm->damage + 1) / 2;
+            /* add ring(s) of increase damage */
+            if (u.udaminc > 0) {
+                /* applies even if damage was 0 */
+                mhm->damage += u.udaminc;
+            } else if (mhm->damage > 0) {
+                /* ring(s) might be negative; avoid converting
+                   0 to non-0 or positive to non-positive */
+                mhm->damage += u.udaminc;
+                if (mhm->damage < 1)
+                    mhm->damage = 1;
+            }
+        }
+    } else if (mdef == &g.youmonst) {
+        /* mhitu */
+        int armpro = magic_negation(mdef);
+        boolean uncancelled = !magr->mcan && (rn2(10) >= 3 * armpro);
+
+        if (mattk->aatyp == AT_HUGS && !sticks(pd)) {
+            if (!u.ustuck && rn2(2)) {
+                if (u_slip_free(magr, mattk)) {
+                    mhm->damage = 0;
+                } else {
+                    set_ustuck(magr);
+                    pline("%s grabs you!", Monnam(magr));
+                }
+            } else if (u.ustuck == magr) {
+                exercise(A_STR, FALSE);
+                You("are being %s.", (magr->data == &mons[PM_ROPE_GOLEM])
+                                         ? "choked"
+                                         : "crushed");
+            }
+        } else { /* hand to hand weapon */
+            struct obj *otmp = MON_WEP(magr);
+
+            if (mattk->aatyp == AT_WEAP && otmp) {
+                struct obj *marmg;
+                int tmp;
+
+                if (otmp->otyp == CORPSE
+                    && touch_petrifies(&mons[otmp->corpsenm])) {
+                    mhm->damage = 1;
+                    pline("%s hits you with the %s corpse.", Monnam(magr),
+                          mons[otmp->corpsenm].mname);
+                    if (!Stoned) {
+                        if (do_stone_u(magr)) {
+                            mhm->hitflags = MM_HIT;
+                            mhm->done = 1;
+                            return;
+                        }
+                    }
+                }
+                mhm->damage += dmgval(otmp, mdef);
+                if ((marmg = which_armor(magr, W_ARMG)) != 0
+                    && marmg->otyp == GAUNTLETS_OF_POWER)
+                    mhm->damage += rn1(4, 3); /* 3..6 */
+                if (mhm->damage <= 0)
+                    mhm->damage = 1;
+                if (!(otmp->oartifact && artifact_hit(magr, mdef, otmp,
+                                                      &mhm->damage, g.mhitu_dieroll)))
+                    hitmsg(magr, mattk);
+                if (!mhm->damage)
+                    return;
+                if (objects[otmp->otyp].oc_material == SILVER
+                    && Hate_silver) {
+                    pline_The("silver sears your flesh!");
+                    exercise(A_CON, FALSE);
+                }
+                /* this redundancy necessary because you have
+                   to take the damage _before_ being cloned;
+                   need to have at least 2 hp left to split */
+                tmp = mhm->damage;
+                if (u.uac < 0)
+                    tmp -= rnd(-u.uac);
+                if (tmp < 1)
+                    tmp = 1;
+                if (u.mh - tmp > 1
+                    && (objects[otmp->otyp].oc_material == IRON
+                        /* relevant 'metal' objects are scalpel and tsurugi */
+                        || objects[otmp->otyp].oc_material == METAL)
+                    && (u.umonnum == PM_BLACK_PUDDING
+                        || u.umonnum == PM_BROWN_PUDDING)) {
+                    if (tmp > 1)
+                        exercise(A_STR, FALSE);
+                    /* inflict damage now; we know it can't be fatal */
+                    u.mh -= tmp;
+                    g.context.botl = 1;
+                    mhm->damage = 0; /* don't inflict more damage below */
+                    if (cloneu())
+                        You("divide as %s hits you!", mon_nam(magr));
+                }
+                rustm(&g.youmonst, otmp);
+            } else if (mattk->aatyp != AT_TUCH || mhm->damage != 0
+                       || magr != u.ustuck)
+                hitmsg(magr, mattk);
+        }
+    } else {
+        /* mhitm */
+        int armpro = magic_negation(mdef);
+        boolean cancelled = magr->mcan || !(rn2(10) >= 3 * armpro);
+        struct obj *mwep = MON_WEP(magr);
+
+        if (mattk->aatyp != AT_WEAP && mattk->aatyp != AT_CLAW)
+            mwep = 0;
+
+        if (shade_miss(magr, mdef, mwep, FALSE, TRUE)) {
+            mhm->damage = 0;
+        } else if (mattk->aatyp == AT_KICK && thick_skinned(pd)) {
+            /* [no 'kicking boots' check needed; monsters with kick attacks
+               can't wear boots and monsters that wear boots don't kick] */
+            mhm->damage = 0;
+        } else if (mwep) { /* non-Null 'mwep' implies AT_WEAP || AT_CLAW */
+            struct obj *marmg;
+
+            if (mwep->otyp == CORPSE
+                && touch_petrifies(&mons[mwep->corpsenm])) {
+                do_stone_mon(magr, mattk, mdef, mhm);
+                if (mhm->done)
+                    return;
+            }
+
+            mhm->damage += dmgval(mwep, mdef);
+            if ((marmg = which_armor(magr, W_ARMG)) != 0
+                && marmg->otyp == GAUNTLETS_OF_POWER)
+                mhm->damage += rn1(4, 3); /* 3..6 */
+            if (mhm->damage < 1) /* is this necessary?  mhitu.c has it... */
+                mhm->damage = 1;
+            if (mwep->oartifact) {
+                /* when magr's weapon is an artifact, caller suppressed its
+                   usual 'hit' message in case artifact_hit() delivers one;
+                   now we'll know and might need to deliver skipped message
+                   (note: if there's no message there'll be no auxilliary
+                   damage so the message here isn't coming too late) */
+                if (!artifact_hit(magr, mdef, mwep, &mhm->damage, mhm->dieroll)) {
+                    if (g.vis)
+                        pline("%s hits %s.", Monnam(magr),
+                              mon_nam_too(mdef, magr));
+                }
+                /* artifact_hit updates 'tmp' but doesn't inflict any
+                   damage; however, it might cause carried items to be
+                   destroyed and they might do so */
+                if (DEADMONSTER(mdef)) {
+                    mhm->hitflags = (MM_DEF_DIED | (grow_up(magr, mdef) ? 0 : MM_AGR_DIED));
+                    mhm->done = TRUE;
+                    return;
+                }
+            }
+            if (mhm->damage)
+                rustm(mdef, mwep);
+        } else if (pa == &mons[PM_PURPLE_WORM] && pd == &mons[PM_SHRIEKER]) {
+            /* hack to enhance mm_aggression(); we don't want purple
+               worm's bite attack to kill a shrieker because then it
+               won't swallow the corpse; but if the target survives,
+               the subsequent engulf attack should accomplish that */
+            if (mhm->damage >= mdef->mhp && mdef->mhp > 1)
+                mhm->damage = mdef->mhp - 1;
+        }
+    }
+}
+
 /* Template for monster hits monster for AD_FOO.
    - replace "break" with return
    - replace "return" with mhm->done = TRUE
@@ -3396,6 +3648,7 @@ int specialdmg; /* blessed and/or silver bonus against various things */
     mhm.damage = d((int) mattk->damn, (int) mattk->damd);
     mhm.hitflags = MM_MISS;
     mhm.permdmg = 0;
+    mhm.specialdmg = specialdmg;
 
     armpro = magic_negation(mdef);
     /* since hero can't be cancelled, only defender's armor applies */
@@ -3426,36 +3679,9 @@ int specialdmg; /* blessed and/or silver bonus against various things */
     case AD_HEAL: /* likewise */
     case AD_PHYS:
  physical:
-        if (pd == &mons[PM_SHADE]) {
-            mhm.damage = 0;
-            if (!specialdmg)
-                impossible("bad shade attack function flow?");
-        }
-        mhm.damage += specialdmg;
-
-        if (mattk->aatyp == AT_WEAP) {
-            /* hmonas() uses known_hitum() to deal physical damage,
-               then also damageum() for non-AD_PHYS; don't inflict
-               extra physical damage for unusual damage types */
-            mhm.damage = 0;
-        } else if (mattk->aatyp == AT_KICK
-                   || mattk->aatyp == AT_CLAW
-                   || mattk->aatyp == AT_TUCH
-                   || mattk->aatyp == AT_HUGS) {
-            if (thick_skinned(pd))
-                mhm.damage = (mattk->aatyp == AT_KICK) ? 0 : (mhm.damage + 1) / 2;
-            /* add ring(s) of increase damage */
-            if (u.udaminc > 0) {
-                /* applies even if damage was 0 */
-                mhm.damage += u.udaminc;
-            } else if (mhm.damage > 0) {
-                /* ring(s) might be negative; avoid converting
-                   0 to non-0 or positive to non-positive */
-                mhm.damage += u.udaminc;
-                if (mhm.damage < 1)
-                    mhm.damage = 1;
-            }
-        }
+        mhitm_ad_phys(&g.youmonst, mattk, mdef, &mhm);
+        if (mhm.done)
+            return mhm.hitflags;
         break;
     case AD_FIRE:
         mhitm_ad_fire(&g.youmonst, mattk, mdef, &mhm);