ranged attack in repertoire might not be used

Commit 22884522, ported (from Sporkhack, Evilhack), added the ability
for monsters to maintain awareness of player resistances that they
observed.

Since they will refrain from using a ranged attack that they deem
futile, take the specific monster's seen_resistance field into consideration
when choosing code paths based on the availability of ranged attacks.

Resolves #1307
This commit is contained in:
nhmall
2024-11-03 09:03:04 -05:00
parent 70a5b06c45
commit 9a42d70901
3 changed files with 64 additions and 2 deletions

View File

@@ -1485,6 +1485,11 @@ extern int gazemu(struct monst *, struct attack *) NONNULLARG12;
extern void mdamageu(struct monst *, int) NONNULLARG1;
extern int could_seduce(struct monst *, struct monst *, struct attack *) NONNULLARG12;
extern int doseduce(struct monst *) NONNULLARG1;
extern boolean mon_avoiding_this_attack(struct monst *, int) NONNULLARG1;
/* extern boolean ranged_attk_assessed(struct monst *mtmp,
boolean (*assessfunct)(struct monst *, int)) NONNULLARG1;
*/
extern boolean ranged_attk_available(struct monst *mtmp) NONNULLARG1;
/* ### minion.c ### */

View File

@@ -2305,6 +2305,62 @@ assess_dmg(struct monst *mtmp, int tmp)
return M_ATTK_HIT;
}
#if 0
/* returns True if monster has a range attack in its repertoire
that it will actually utilize. Caller provides the assessment
callback (optional). Callback returns 0 if the attack is
active */
boolean ranged_attk_assessed(
struct monst *mtmp,
boolean (*assessfunc)(struct monst *, int))
{
int i;
struct permonst *ptr = mtmp->data;
for (i = 0; i < NATTK; i++)
if (DISTANCE_ATTK_TYPE(ptr->mattk[i].aatyp)) {
if (!assessfunc || (*assessfunc)(mtmp, i) == 0)
return TRUE;
}
return FALSE;
}
#endif
/* can be used as ranged_attk_assessed() callback.
Returns TRUE if monster is avoiding use of this attack */
boolean
mon_avoiding_this_attack(struct monst *mtmp, int attkidx)
{
struct permonst *ptr = mtmp->data;
int typ = -1;
if (attkidx >= 0
&& (typ = get_atkdam_type(ptr->mattk[attkidx].adtyp)) >= 0
&& m_seenres(mtmp, cvt_adtyp_to_mseenres(typ)))
return TRUE;
return FALSE;
}
/*
* This would be equivalent to:
* ranged_attk_assessed(mtmp, mon_avoiding_this_attack)
* but without the added assessment function call overhead.
*/
boolean ranged_attk_available(struct monst *mtmp)
{
int i, typ = -1;
struct permonst *ptr = mtmp->data;
for (i = 0; i < NATTK; i++) {
if (DISTANCE_ATTK_TYPE(ptr->mattk[i].aatyp)
&& (typ = get_atkdam_type(ptr->mattk[i].adtyp)) >= 0
&& m_seenres(mtmp, cvt_adtyp_to_mseenres(typ)) == 0)
return TRUE;
}
return FALSE;
}
/* FIXME:
* sequencing issue: a monster's attack might cause poly'd hero
* to revert to normal form. The messages for passive counterattack

View File

@@ -910,7 +910,8 @@ dochug(struct monst *mtmp)
return 0;
/* Monsters can move and then shoot on same turn;
our hero can't. Is that fair? */
if (!nearby && (ranged_attk(mdat)
if (!nearby
&& (ranged_attk_available(mtmp)
|| attacktype(mdat, AT_WEAP)
|| find_offensive(mtmp)))
break;
@@ -1159,7 +1160,7 @@ m_balks_at_approaching(struct monst *mtmp)
return TRUE;
/* can attack from distance, and hp loss or attack not used */
if (ranged_attk(mtmp->data)
if (ranged_attk_available(mtmp)
&& ((mtmp->mhp < (mtmp->mhpmax+1) / 3)
|| !mtmp->mspec_used))
return TRUE;