]> granicus.if.org Git - nethack/commitdiff
fix #H7980 - multiple weapon attacks when poly'd
authorPatR <rankin@nethack.org>
Fri, 18 Jan 2019 21:22:43 +0000 (13:22 -0800)
committerPatR <rankin@nethack.org>
Fri, 18 Jan 2019 21:22:43 +0000 (13:22 -0800)
This fixes the weapon related aspects of #H7980:  having an alternate
weapon be used in cases where it shouldn't when polymorphed into a
monster form with multiple weapon attacks.  The most egregious was
using an off-hand artifact, but it would also use off-hand two-handed
weapon, off-hand silver weapon when in silver-hating form, or any
reasonable off-hand weapon when wearing a shield.  That last is iffy
whether or not to allow, since you'll still get the extra attacks
whether it switches to secondary weapon or stays with the primary.
I've made it re-use the primary since two-weapon mode doesn't allow
a shield.  The other oddity was being able to use the secondary
weapon on the second swing even if the first swing was weaponless.
I went with ingoring the secondary weapon if there's no primary one
or if the primary is two-handed.

Report included "cursed secondary doesn't weld" but that has nothing
to do with polymorph attacking.  I've changed that to drop the weapon
if you attack with it when it's cursed, similar to what happens when
secondary weapon becomes cursed while two-weaponing.

It also included "marilith's attacks beyond the second don't use any
weapon and can hit cockatrices without touching them".  A marilith has
two weapon attacks and then four claw attacks.  Claw attacks only use
the weapon if it hasn't been used yet, so marilith hits with primary,
secondary (or primary a second time if no secondary), claw, claw,
claw, claw and that's the intended behavior.  It is able to hit
cockatrices if wielding anything at all, same as a monster with just
a single attack.  Since it is impossible to wield six weapons or three
pairs of gloves, that has to be intended behavior too.  Playability
trumps realism even if it is silly to hit without a 3rd through 6th
weapon and be safe from touching the target due to the 1st weapon or
one pair of gloves.  [Situation is different from having no control
over unsafely biting something after making a safe weapon or claw
attack; perhaps a better solution would be to refrain from using the
four claw attacks when attacking something that is fatal to touch.]

doc/fixes36.2
src/uhitm.c

index d796f3260172801a40b5b0985a357e8dbf69cdbd..4cc91f5a5101d5a3acdf9e8c4d7111e0257febac 100644 (file)
@@ -1,4 +1,4 @@
-$NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.230 $ $NHDT-Date: 1547680081 2019/01/16 23:08:01 $
+$NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.231 $ $NHDT-Date: 1547846557 2019/01/18 21:22:37 $
 
 This fixes36.2 file is here to capture information about updates in the 3.6.x
 lineage following the release of 3.6.1 in April 2018. Please note, however,
@@ -337,6 +337,11 @@ entering Ft.Ludios with a lit candle lit up the entire entry room except for
        to prevent those wall spots from showing so soon
 boulder dropped or launched by a monster onto a monster trapped in a pit and
        killing it credited/blamed the hero and might trigger a deltrap panic
+the simulation of dual weapon combat when polymorphed into a form with more
+       than one weapon attack allowed off-hand artifact to be used; it also
+       used seconary weapon even when wearing a shield, or if it was silver
+       even when current shape couldn't handle silver, or if it was cursed;
+       cursed is allowed but weapon will be dropped, just like in two-weapon
 
 
 Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository
index 986f9c3bd85fb7ca199bffafc6d6d4325ba6326e..7b4ca1a84d4a9daf66fa30d848aaa8bb5acaaeb1 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 uhitm.c $NHDT-Date: 1547680084 2019/01/16 23:08:04 $  $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.199 $ */
+/* NetHack 3.6 uhitm.c $NHDT-Date: 1547846557 2019/01/18 21:22:37 $  $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.200 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /*-Copyright (c) Robert Patrick Rankin, 2012. */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -2275,7 +2275,7 @@ boolean wouldhavehit;
         wakeup(mdef, TRUE);
 }
 
-/* attack monster as a monster. */
+/* attack monster as a monster; returns True if mon survives */
 STATIC_OVL boolean
 hmonas(mon)
 register struct monst *mon;
@@ -2293,6 +2293,12 @@ register struct monst *mon;
         switch (mattk->aatyp) {
         case AT_WEAP:
  use_weapon:
+            /* if we've already hit with a two-handed weapon, we don't
+               get to make another weapon attack (note:  monsters who
+               use weapons do not have this restriction, but they also
+               never have the opportunity to use two weapons) */
+            if (weapon_used && sum[i - 1] && uwep && bimanual(uwep))
+                continue;
             /* Certain monsters don't use weapons when encountered as enemies,
              * but players who polymorph into them have hands or claws and
              * thus should be able to use weapons.  This shouldn't prohibit
@@ -2309,11 +2315,23 @@ register struct monst *mon;
                be Null, and we want to track that for passive() */
             originalweapon = (altwep && uswapwep) ? &uswapwep : &uwep;
             if (uswapwep /* set up 'altwep' flag for next iteration */
+                /* only consider seconary when wielding one-handed primary */
+                && uwep && !bimanual(uwep)
+                /* only switch if not wearing shield and not at artifact;
+                   shield limitation is iffy since still get extra swings
+                   if polyform has them, but it matches twoweap behavior;
+                   twoweap also only allows primary to be an artifact, so
+                   if alternate weapon is one, don't use it */
+                && !uarms && !uswapwep->oartifact
                 /* only switch to uswapwep if it's a weapon */
                 && (uswapwep->oclass == WEAPON_CLASS || is_weptool(uswapwep))
                 /* only switch if uswapwep is not bow, arrows, or darts */
                 && !(is_launcher(uswapwep) || is_ammo(uswapwep)
-                     || is_missile(uswapwep))) /* dart, shuriken, boomerang */
+                     || is_missile(uswapwep)) /* dart, shuriken, boomerang */
+                /* and not two-handed and not incapable of being wielded */
+                && !bimanual(uswapwep)
+                && !(objects[uswapwep->otyp].oc_material == SILVER
+                     && Hate_silver))
                 altwep = !altwep; /* toggle for next attack */
             weapon = *originalweapon;
             if (!weapon) /* no need to go beyond no-gloves to rings; not ...*/
@@ -2323,9 +2341,9 @@ register struct monst *mon;
                                    &armorpenalty);
             dieroll = rnd(20);
             dhit = (tmp > dieroll || u.uswallow);
-            /* Enemy dead, before any special abilities used */
             if (!known_hitum(mon, weapon, &dhit, tmp,
                              armorpenalty, mattk, dieroll)) {
+                /* enemy dead, before any special abilities used */
                 sum[i] = 2;
                 break;
             } else
@@ -2334,12 +2352,13 @@ register struct monst *mon;
                now be empty if the weapon was destroyed during the hit;
                passive(,weapon,...) won't call passive_obj() in that case */
             weapon = *originalweapon; /* might receive passive erosion */
-            /* might be a worm that gets cut in half */
-            if (m_at(u.ux + u.dx, u.uy + u.dy) != mon)
-                return (boolean) (nsum != 0);
-            /* Do not print "You hit" message, since known_hitum
-             * already did it.
-             */
+            /* might be a worm that gets cut in half; if so, early return */
+            if (m_at(u.ux + u.dx, u.uy + u.dy) != mon) {
+                i = NATTK; /* skip additional attacks */
+                /* proceed with uswapwep->cursed check, then exit loop */
+                goto passivedone;
+            }
+            /* Do not print "You hit" message; known_hitum already did it. */
             if (dhit && mattk->adtyp != AD_SPEL && mattk->adtyp != AD_PHYS)
                 sum[i] = damageum(mon, mattk);
             break;
@@ -2481,17 +2500,34 @@ register struct monst *mon;
         }
         if (sum[i] == 2) {
             /* defender dead */
-            return (boolean) passive(mon, weapon, 1, 0, mattk->aatyp, FALSE);
+            (void) passive(mon, weapon, 1, 0, mattk->aatyp, FALSE);
+            nsum = 0; /* return value below used to be 'nsum > 0' */
         } else {
             (void) passive(mon, weapon, sum[i], 1, mattk->aatyp, FALSE);
             nsum |= sum[i];
         }
+
+        /* don't use sum[i] beyond this point;
+           'i' will be out of bounds if we get here via 'goto' */
+ passivedone:
+        /* when using dual weapons, cursed secondary weapon doesn't weld,
+           it gets dropped; do the same when multiple AT_WEAP attacks
+           simulate twoweap */
+        if (uswapwep && weapon == uswapwep && weapon->cursed) {
+            drop_uswapwep();
+            break; /* don't proceed with additional attacks */
+        }
+        /* stop attacking if defender has died;
+           needed to defer this until after uswapwep->cursed check */
+        if (DEADMONSTER(mon))
+            break;
         if (!Upolyd)
             break; /* No extra attacks if no longer a monster */
         if (multi < 0)
             break; /* If paralyzed while attacking, i.e. floating eye */
     }
-    return (boolean) (nsum != 0);
+    /* return value isn't used, but make it match hitum()'s */
+    return !DEADMONSTER(mon);
 }
 
 /*      Special (passive) attacks on you by monsters done here.