fix #K3925 - u.ustuck of long worm tail

Don't allow stick/wrap/engulf attacks directed at long worm tails
to succeed.  Achieved by making sure that 'notonhead' is up do date
in a bunch of places and utilizing the fairly recent can't-{stick,wrap,
engulf}-unsolid-monsters code.

Should prevent a 'sanity_check' warning about being too far from
u.ustuck that would happen when holding the tail while the head was
not adjacent to the hero.

Also don't let pet ranged attacks from choosing a long worm's tail
as target.  They'll still be able to target long worms provided that
the head is lined up and not shielded by tail segment(s).
This commit is contained in:
PatR
2023-05-20 15:34:32 -07:00
parent f176318c45
commit 9052bd5099
6 changed files with 99 additions and 47 deletions

View File

@@ -139,9 +139,8 @@ fightm(register struct monst *mtmp)
}
/* mtmp can be killed */
gb.bhitpos.x = mon->mx;
gb.bhitpos.y = mon->my;
gn.notonhead = 0;
gb.bhitpos.x = mon->mx, gb.bhitpos.y = mon->my;
gn.notonhead = FALSE;
result = mattackm(mtmp, mon);
if (result & M_ATTK_AGR_DIED)
@@ -161,7 +160,8 @@ fightm(register struct monst *mtmp)
mon->movement -= NORMAL_SPEED;
else
mon->movement = 0;
gn.notonhead = 0;
gb.bhitpos.x = mtmp->mx, gb.bhitpos.y = mtmp->my;
gn.notonhead = FALSE;
(void) mattackm(mon, mtmp); /* return attack */
}
@@ -177,8 +177,10 @@ fightm(register struct monst *mtmp)
* returns same results as mattackm().
*/
int
mdisplacem(register struct monst *magr, register struct monst *mdef,
boolean quietly)
mdisplacem(
struct monst *magr,
struct monst *mdef,
boolean quietly)
{
struct permonst *pa, *pd;
int tx, ty, fx, fy;
@@ -286,7 +288,9 @@ mdisplacem(register struct monst *magr, register struct monst *mdef,
* In the case of exploding monsters, the monster dies as well.
*/
int
mattackm(register struct monst *magr, register struct monst *mdef)
mattackm(
register struct monst *magr,
register struct monst *mdef)
{
int i, /* loop counter */
tmp, /* armor class difference */
@@ -569,14 +573,15 @@ mattackm(register struct monst *magr, register struct monst *mdef)
return (struck ? M_ATTK_HIT : M_ATTK_MISS);
}
/* can't hold an unsolid target (ghosts, lights, vortices, most elementals) */
/* can't hold an unsolid target (ghosts, lights, vortices, most elementals)
or a long worm tail */
boolean
failed_grab(
struct monst *magr,
struct monst *mdef,
struct attack *mattk)
{
if (unsolid(mdef->data)
if ((unsolid(mdef->data) || gn.notonhead)
/* hug attack: most holders (owlbear, python, pit fiend, &c);
wrap damage: eel grabbing, trapper/lurker-above engulfing;
stick-to damage: mimic, lichen;
@@ -586,21 +591,30 @@ failed_grab(
if ((gv.vis && canspotmon(mdef)) /* mon-vs-mon */
|| magr == &gy.youmonst || mdef == &gy.youmonst) {
char magrnam[BUFSZ], mdefnam[BUFSZ];
boolean tailmiss = gn.notonhead;
const char *verb = (mattk->adtyp == AD_DGST) ? "gulp"
: (mattk->adtyp == AD_STCK) ? "adhere"
: "grab";
/* beware of "Foo's grab passes through Bar's ghost";
mon_nam(x_monnam) calls s_suffix() for named ghosts and
s_suffix() uses a single static buffer; make copies of
both names to overcome that */
s_suffix() uses a single static buffer; make copies of both
names to overcome that [note: comment predates 'tailmiss'] */
Strcpy(magrnam, (magr == &gy.youmonst) ? "Your"
: s_suffix(Monnam(magr)));
Strcpy(mdefnam, (mdef == &gy.youmonst) ? "you" : mon_nam(mdef));
/* this is actually somewhat iffy--how come ordinary attacks
don't also pass right through? */
pline("%.99s %s attempt passes right through %.99s!",
magrnam, verb, mdefnam);
if (!tailmiss) {
Strcpy(mdefnam, (mdef == &gy.youmonst) ? "you"
: mon_nam(mdef));
} else {
/* hero poly'd into long worm can't grow tail
so no 'youmonst' handling is needed here */
Sprintf(mdefnam, "%s tail", s_suffix(some_mon_nam(mdef)));
}
/* unsolid grab misses are actually somewhat iffy--how come
ordinary attacks don't also pass right through? */
pline("%.99s %s attempt %s %.99s!", magrnam, verb,
!tailmiss ? "passes right through" : "fails to hold",
mdefnam);
}
return TRUE;
}
@@ -972,8 +986,12 @@ explmm(struct monst *magr, struct monst *mdef, struct attack *mattk)
* See comment at top of mattackm(), for return values.
*/
static int
mdamagem(struct monst *magr, struct monst *mdef,
struct attack *mattk, struct obj *mwep, int dieroll)
mdamagem(
struct monst *magr,
struct monst *mdef,
struct attack *mattk,
struct obj *mwep,
int dieroll)
{
struct permonst *pa = magr->data, *pd = mdef->data;
struct mhitm_data mhm;
@@ -1247,11 +1265,15 @@ mswingsm(
* handled above. Returns same values as mattackm.
*/
static int
passivemm(register struct monst *magr, register struct monst *mdef,
boolean mhitb, int mdead, struct obj *mwep)
passivemm(
struct monst *magr,
struct monst *mdef,
boolean mhitb,
int mdead,
struct obj *mwep)
{
register struct permonst *mddat = mdef->data;
register struct permonst *madat = magr->data;
struct permonst *mddat = mdef->data;
struct permonst *madat = magr->data;
char buf[BUFSZ];
int i, tmp;
int mhit = mhitb ? M_ATTK_HIT : M_ATTK_MISS;