partly fix issue #1336 - pets vs floating eyes

Issue reported by ars3niy:  pets with reflection or ranged attacks
would only attack floating eyes when rolling the 10% random chance
that other pets have even though they could have always safely
attacked.

This fixes the situation for melee attacks by pets who have
reflection.

dog_move() is too complicated for my feeble brain to cope with the
ranged attack aspect.  Pets still won't use ranged attacks against
floating eyes.

With the fix for reflection, I discovered that silver dragons
would be subjected to floating eyes' passive paralysis even when
their breath attack was suppressed.  (It wouldn't impact them, due
to reflection, but the message about the floating eye being hit by
its reflected gaze was being delivered without being preceded by
any message since no attack had taken place yet.)  This fixes that.

\#1336 is still open
This commit is contained in:
PatR
2024-12-11 12:38:28 -08:00
parent e08bd9ef8a
commit aedb24d343
3 changed files with 41 additions and 27 deletions

View File

@@ -968,7 +968,7 @@ dog_move(
struct obj *obj = (struct obj *) 0;
xint16 otyp;
boolean cursemsg[9], do_eat = FALSE;
boolean better_with_displacing = FALSE;
boolean better_with_displacing = FALSE, ranged_only;
coordxy nix, niy; /* position mtmp is (considering) moving to */
coordxy nx, ny; /* temporary coordinates */
xint16 cnt, uncursedcnt, chcnt;
@@ -1081,6 +1081,8 @@ dog_move(
if (!edog && (j = distu(nx, ny)) > 16 && j >= udist)
continue;
ranged_only = FALSE;
if ((info[i] & ALLOW_M) && MON_AT(nx, ny)) {
int mstatus;
struct monst *mtmp2 = m_at(nx, ny);
@@ -1101,16 +1103,28 @@ dog_move(
int balk = mtmp->m_lev + ((5 * mtmp->mhp) / mtmp->mhpmax) - 2;
if ((int) mtmp2->m_lev >= balk
|| (mtmp2->data == &mons[PM_FLOATING_EYE] && rn2(10)
&& mtmp->mcansee && haseyes(mtmp->data) && mtmp2->mcansee
&& (perceives(mtmp->data) || !mtmp2->minvis))
|| (mtmp2->data == &mons[PM_GELATINOUS_CUBE] && rn2(10))
|| (mtmp2->mtame && mtmp->mtame && !Conflict)
|| (max_passive_dmg(mtmp2, mtmp) >= mtmp->mhp)
|| ((mtmp->mhp * 4 < mtmp->mhpmax
|| mtmp2->data->msound == MS_GUARDIAN
|| mtmp2->data->msound == MS_LEADER) && mtmp2->mpeaceful
&& !Conflict)
|| (touch_petrifies(mtmp2->data) && !resists_ston(mtmp)))
|| mtmp2->data->msound == MS_LEADER)
&& mtmp2->mpeaceful && !Conflict)) {
continue;
}
if ((mtmp2->data == &mons[PM_FLOATING_EYE] && rn2(10)
&& mtmp->mcansee && haseyes(mtmp->data) && mtmp2->mcansee
&& (!mtmp2->minvis || perceives(mtmp->data))
&& !mon_reflects(mtmp, (char *) NULL))
|| (mtmp2->data == &mons[PM_GELATINOUS_CUBE] && rn2(10))
|| (touch_petrifies(mtmp2->data) && !resists_ston(mtmp))) {
/* only skip this foe if a ranged attack isn't viable */
if (dist2(mtmp->mx, mtmp->my, mtmp2->mx, mtmp2->my) <= 2
|| best_target(mtmp) != mtmp2)
continue;
ranged_only = TRUE;
}
/** FIXME: 'ranged_only' isn't used as intended yet **/
if (ranged_only)
continue;
if (after)
@@ -1183,6 +1197,7 @@ dog_move(
/* (minion isn't interested; `cursemsg' stays FALSE) */
if (edog) {
boolean can_reach_food = could_reach_item(mtmp, nx, ny);
for (obj = svl.level.objects[nx][ny]; obj; obj = obj->nexthere) {
if (obj->cursed) {
cursemsg[i] = TRUE;

View File

@@ -485,7 +485,7 @@ mattackm(
case AT_EXPL:
/* D: Prevent explosions from a distance */
if (distmin(magr->mx,magr->my,mdef->mx,mdef->my) > 1)
if (distmin(magr->mx, magr->my, mdef->mx, mdef->my) > 1)
continue;
res[i] = explmm(magr, mdef, mattk);
@@ -525,25 +525,20 @@ mattackm(
break;
case AT_BREA:
if (!monnear(magr, mdef->mx, mdef->my)) {
strike = (breamm(magr, mattk, mdef) == M_ATTK_MISS) ? 0 : 1;
/* We don't really know if we hit or not; pretend we did. */
if (strike)
res[i] |= M_ATTK_HIT;
if (DEADMONSTER(mdef))
res[i] = M_ATTK_DEF_DIED;
if (DEADMONSTER(magr))
res[i] |= M_ATTK_AGR_DIED;
}
else
strike = 0;
break;
case AT_SPIT:
/*
* Ranged attacks aren't allowed at point blank range.
*
* That impacts pet use of ranged attacks. It's rather arbitrary
* but various parts of the code assume it to be the case, not to
* mention a part of player strategy when fighting dragons.
*/
if (!monnear(magr, mdef->mx, mdef->my)) {
strike = (spitmm(magr, mattk, mdef) == M_ATTK_MISS) ? 0 : 1;
int mmtmp = ((mattk->aatyp == AT_BREA)
? breamm(magr, mattk, mdef)
: spitmm(magr, mattk, mdef));
strike = (mmtmp == M_ATTK_MISS) ? 0 : 1;
/* We don't really know if we hit or not; pretend we did. */
if (strike)
res[i] |= M_ATTK_HIT;
@@ -551,6 +546,9 @@ mattackm(
res[i] = M_ATTK_DEF_DIED;
if (DEADMONSTER(magr))
res[i] |= M_ATTK_AGR_DIED;
} else {
strike = 0;
attk = 0;
}
break;