fix #K4331 - sticking from distance

Stop attacking if target isn't there anymore.  Already handled for
two-weapon in normal form, not for multi-attacks in poly'd form and
for multi-attack monster vs hero or monster vs other monster.

I didn't attempt to reproduce the reported problem.  This fix is
based on code inspection.

Also prevent monsters that have hug or engulf attacks from knocking
target back with other attacks since that prohibits the grab/engulf
from being able to hit.
This commit is contained in:
PatR
2025-06-03 22:13:22 -07:00
parent 28af1d6410
commit 45f751989a
3 changed files with 35 additions and 10 deletions

View File

@@ -5203,7 +5203,7 @@ mhitm_knockback(
boolean u_def = (mdef == &gy.youmonst);
boolean was_u = FALSE, dismount = FALSE;
struct obj *wep = weapon_used ? (u_agr ? uwep : MON_WEP(magr))
: (struct obj *)0;
: (struct obj *) 0;
if (wep && is_art(wep, ART_OGRESMASHER))
chance = 2;
@@ -5211,6 +5211,20 @@ mhitm_knockback(
if (rn2(chance))
return FALSE;
/* only certain attacks qualify for knockback */
if (!((mattk->adtyp == AD_PHYS)
&& (mattk->aatyp == AT_CLAW
|| mattk->aatyp == AT_KICK
|| mattk->aatyp == AT_BUTT
|| mattk->aatyp == AT_WEAP)))
return FALSE;
/* don't knockback if attacker also wants to grab or engulf */
if (attacktype(magr->data, AT_ENGL)
|| attacktype(magr->data, AT_HUGS)
|| sticks(magr->data))
return FALSE;
/* decide where the first step will place the target; not accurate
for being knocked out of saddle but doesn't need to be; used for
test_move() and for message before actual hurtle */
@@ -5257,14 +5271,6 @@ mhitm_knockback(
if (wep && (is_flimsy(wep) || !is_blunt_weapon(wep)))
return FALSE;
/* only certain attacks qualify for knockback */
if (!((mattk->adtyp == AD_PHYS)
&& (mattk->aatyp == AT_CLAW
|| mattk->aatyp == AT_KICK
|| mattk->aatyp == AT_BUTT
|| mattk->aatyp == AT_WEAP)))
return FALSE;
/* needs a solid physical hit */
if (unsolid(magr->data))
return FALSE;
@@ -5388,6 +5394,14 @@ hmonas(struct monst *mon)
for (i = 0; i < NATTK; i++) {
/* sum[i] = M_ATTK_MISS; -- now done above */
/* target might have been knocked back so no longer in range, or an
engulfing vampshifted fog cloud killed and reverted to vampire
that's placed at another spot (hero occupies mon's first spot) */
if (i > 0 && (m_at(gb.bhitpos.x, gb.bhitpos.y) != mon
|| DEADMONSTER(mon)))
continue;
mattk = getmattk(&gy.youmonst, mon, i, sum, &alt_attk);
if (gs.skipdrin && mattk->aatyp == AT_TENT && mattk->adtyp == AD_DRIN)
continue;