fix #H7454 - Cleaver vs long worm tails
Cleaver's ability to hit up to three adjacent targets could kill a long worm and then try to cut it in two. When this was first reported I was unable to reproduce it, but this time I've managed to do so. But not reliably, so it's hard to claim that it's now fixed. However, the new report's explanation of why it happens and suggested fix was a big help. I had been trying to hit three tail segments, but you need to attack a segment next to the head, then have Cleaver hit and kill the head first (50:50 chance depending upon whether current swing is clockwise or counter). Worm cutting would be looking at the location of the targetted segment but there won't be any monster there when the head dies. (Cleaver's attack itself already copes the situation where its 2nd and/or 3rd potential targets aren't there any more by the time it's ready to try to hit them.)
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
$NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.282 $ $NHDT-Date: 1553480403 2019/03/25 02:20:03 $
|
$NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.283 $ $NHDT-Date: 1553644725 2019/03/26 23:58:45 $
|
||||||
|
|
||||||
This fixes36.2 file is here to capture information about updates in the 3.6.x
|
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,
|
lineage following the release of 3.6.1 in April 2018. Please note, however,
|
||||||
@@ -396,6 +396,8 @@ status lines' dungeon location field in the elemental planes now shows Earth
|
|||||||
or Air or Fire or Water instead of generic End Game
|
or Air or Fire or Water instead of generic End Game
|
||||||
avoid spurious status refresh when hero gains experience while 'showexp' and
|
avoid spurious status refresh when hero gains experience while 'showexp' and
|
||||||
'showscore' options are off
|
'showscore' options are off
|
||||||
|
using Cleaver to attack a worm tail segment but kill adjacent head first would
|
||||||
|
result in an impossible warning from cutworm
|
||||||
|
|
||||||
|
|
||||||
Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository
|
Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository
|
||||||
|
|||||||
20
src/uhitm.c
20
src/uhitm.c
@@ -1,4 +1,4 @@
|
|||||||
/* NetHack 3.6 uhitm.c $NHDT-Date: 1548209742 2019/01/23 02:15:42 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.203 $ */
|
/* NetHack 3.6 uhitm.c $NHDT-Date: 1553644725 2019/03/26 23:58:45 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.206 $ */
|
||||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||||
/*-Copyright (c) Robert Patrick Rankin, 2012. */
|
/*-Copyright (c) Robert Patrick Rankin, 2012. */
|
||||||
/* NetHack may be freely redistributed. See license for details. */
|
/* NetHack may be freely redistributed. See license for details. */
|
||||||
@@ -481,7 +481,7 @@ int dieroll;
|
|||||||
if (!*mhit) {
|
if (!*mhit) {
|
||||||
missum(mon, uattk, (rollneeded + armorpenalty > dieroll));
|
missum(mon, uattk, (rollneeded + armorpenalty > dieroll));
|
||||||
} else {
|
} else {
|
||||||
int oldhp = mon->mhp, x = u.ux + u.dx, y = u.uy + u.dy;
|
int oldhp = mon->mhp;
|
||||||
long oldweaphit = u.uconduct.weaphit;
|
long oldweaphit = u.uconduct.weaphit;
|
||||||
|
|
||||||
/* KMH, conduct */
|
/* KMH, conduct */
|
||||||
@@ -490,7 +490,7 @@ int dieroll;
|
|||||||
|
|
||||||
/* we hit the monster; be careful: it might die or
|
/* we hit the monster; be careful: it might die or
|
||||||
be knocked into a different location */
|
be knocked into a different location */
|
||||||
notonhead = (mon->mx != x || mon->my != y);
|
notonhead = (mon->mx != bhitpos.x || mon->my != bhitpos.y);
|
||||||
malive = hmon(mon, weapon, HMON_MELEE, dieroll);
|
malive = hmon(mon, weapon, HMON_MELEE, dieroll);
|
||||||
if (malive) {
|
if (malive) {
|
||||||
/* monster still alive */
|
/* monster still alive */
|
||||||
@@ -510,7 +510,7 @@ int dieroll;
|
|||||||
u.uconduct.weaphit = oldweaphit;
|
u.uconduct.weaphit = oldweaphit;
|
||||||
}
|
}
|
||||||
if (mon->wormno && *mhit)
|
if (mon->wormno && *mhit)
|
||||||
cutworm(mon, x, y, slice_or_chop);
|
cutworm(mon, bhitpos.x, bhitpos.y, slice_or_chop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return malive;
|
return malive;
|
||||||
@@ -530,6 +530,7 @@ struct attack *uattk; /* ... but we don't enforce that here; Null works ok */
|
|||||||
simulation attempt a bit */
|
simulation attempt a bit */
|
||||||
static boolean clockwise = FALSE;
|
static boolean clockwise = FALSE;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
coord save_bhitpos;
|
||||||
int count, umort, x = u.ux, y = u.uy;
|
int count, umort, x = u.ux, y = u.uy;
|
||||||
|
|
||||||
/* find the direction toward primary target */
|
/* find the direction toward primary target */
|
||||||
@@ -546,6 +547,7 @@ struct attack *uattk; /* ... but we don't enforce that here; Null works ok */
|
|||||||
to primary target */
|
to primary target */
|
||||||
i = (i + (clockwise ? 6 : 2)) % 8;
|
i = (i + (clockwise ? 6 : 2)) % 8;
|
||||||
umort = u.umortality; /* used to detect life-saving */
|
umort = u.umortality; /* used to detect life-saving */
|
||||||
|
save_bhitpos = bhitpos;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Three attacks: adjacent to primary, primary, adjacent on other
|
* Three attacks: adjacent to primary, primary, adjacent on other
|
||||||
@@ -576,6 +578,7 @@ struct attack *uattk; /* ... but we don't enforce that here; Null works ok */
|
|||||||
&attknum, &armorpenalty);
|
&attknum, &armorpenalty);
|
||||||
dieroll = rnd(20);
|
dieroll = rnd(20);
|
||||||
mhit = (tmp > dieroll);
|
mhit = (tmp > dieroll);
|
||||||
|
bhitpos.x = tx, bhitpos.y = ty; /* normally set up by attack() */
|
||||||
(void) known_hitum(mtmp, uwep, &mhit, tmp, armorpenalty,
|
(void) known_hitum(mtmp, uwep, &mhit, tmp, armorpenalty,
|
||||||
uattk, dieroll);
|
uattk, dieroll);
|
||||||
(void) passive(mtmp, uwep, mhit, !DEADMONSTER(mtmp), AT_WEAP, !uwep);
|
(void) passive(mtmp, uwep, mhit, !DEADMONSTER(mtmp), AT_WEAP, !uwep);
|
||||||
@@ -587,6 +590,8 @@ struct attack *uattk; /* ... but we don't enforce that here; Null works ok */
|
|||||||
}
|
}
|
||||||
/* set up for next time */
|
/* set up for next time */
|
||||||
clockwise = !clockwise; /* alternate */
|
clockwise = !clockwise; /* alternate */
|
||||||
|
bhitpos = save_bhitpos; /* in case somebody relies on bhitpos
|
||||||
|
* designating the primary target */
|
||||||
|
|
||||||
/* return False if primary target died, True otherwise; note: if 'target'
|
/* return False if primary target died, True otherwise; note: if 'target'
|
||||||
was nonNull upon entry then it's still nonNull even if *target died */
|
was nonNull upon entry then it's still nonNull even if *target died */
|
||||||
@@ -616,6 +621,7 @@ struct attack *uattk;
|
|||||||
|
|
||||||
if (tmp > dieroll)
|
if (tmp > dieroll)
|
||||||
exercise(A_DEX, TRUE);
|
exercise(A_DEX, TRUE);
|
||||||
|
/* bhitpos is set up by caller */
|
||||||
malive = known_hitum(mon, uwep, &mhit, tmp, armorpenalty, uattk, dieroll);
|
malive = known_hitum(mon, uwep, &mhit, tmp, armorpenalty, uattk, dieroll);
|
||||||
if (wepbefore && !uwep)
|
if (wepbefore && !uwep)
|
||||||
wep_was_destroyed = TRUE;
|
wep_was_destroyed = TRUE;
|
||||||
@@ -2285,13 +2291,14 @@ register struct monst *mon;
|
|||||||
struct attack *mattk, alt_attk;
|
struct attack *mattk, alt_attk;
|
||||||
struct obj *weapon, **originalweapon;
|
struct obj *weapon, **originalweapon;
|
||||||
boolean altwep = FALSE, weapon_used = FALSE, odd_claw = TRUE;
|
boolean altwep = FALSE, weapon_used = FALSE, odd_claw = TRUE;
|
||||||
int i, tmp, armorpenalty, sum[NATTK] = { 0 }, nsum = 0, dhit = 0, attknum = 0;
|
int i, tmp, armorpenalty, sum[NATTK], nsum = 0, dhit = 0, attknum = 0;
|
||||||
int dieroll, multi_claw = 0;
|
int dieroll, multi_claw = 0;
|
||||||
|
|
||||||
/* with just one touch/claw/weapon attack, both rings matter;
|
/* with just one touch/claw/weapon attack, both rings matter;
|
||||||
with more than one, alternate right and left when checking
|
with more than one, alternate right and left when checking
|
||||||
whether silver ring causes successful hit */
|
whether silver ring causes successful hit */
|
||||||
for (i = 0; i < NATTK; i++) {
|
for (i = 0; i < NATTK; i++) {
|
||||||
|
sum[i] = 0;
|
||||||
mattk = getmattk(&youmonst, mon, i, sum, &alt_attk);
|
mattk = getmattk(&youmonst, mon, i, sum, &alt_attk);
|
||||||
if (mattk->aatyp == AT_WEAP
|
if (mattk->aatyp == AT_WEAP
|
||||||
|| mattk->aatyp == AT_CLAW || mattk->aatyp == AT_TUCH)
|
|| mattk->aatyp == AT_CLAW || mattk->aatyp == AT_TUCH)
|
||||||
@@ -2300,7 +2307,7 @@ register struct monst *mon;
|
|||||||
multi_claw = (multi_claw > 1); /* switch from count to yes/no */
|
multi_claw = (multi_claw > 1); /* switch from count to yes/no */
|
||||||
|
|
||||||
for (i = 0; i < NATTK; i++) {
|
for (i = 0; i < NATTK; i++) {
|
||||||
sum[i] = 0;
|
/* sum[i] = 0; -- now done above */
|
||||||
mattk = getmattk(&youmonst, mon, i, sum, &alt_attk);
|
mattk = getmattk(&youmonst, mon, i, sum, &alt_attk);
|
||||||
weapon = 0;
|
weapon = 0;
|
||||||
switch (mattk->aatyp) {
|
switch (mattk->aatyp) {
|
||||||
@@ -2357,6 +2364,7 @@ register struct monst *mon;
|
|||||||
&armorpenalty);
|
&armorpenalty);
|
||||||
dieroll = rnd(20);
|
dieroll = rnd(20);
|
||||||
dhit = (tmp > dieroll || u.uswallow);
|
dhit = (tmp > dieroll || u.uswallow);
|
||||||
|
/* caller must set bhitpos */
|
||||||
if (!known_hitum(mon, weapon, &dhit, tmp,
|
if (!known_hitum(mon, weapon, &dhit, tmp,
|
||||||
armorpenalty, mattk, dieroll)) {
|
armorpenalty, mattk, dieroll)) {
|
||||||
/* enemy dead, before any special abilities used */
|
/* enemy dead, before any special abilities used */
|
||||||
|
|||||||
Reference in New Issue
Block a user