Skip to content

Allies frequently die to invulnerable monsters #802

@brturn

Description

@brturn

Reported by Bentwing on Discord

Allies will often die to invulnerable monsters (Revnants, Warden) in otherwise avoidable ways. Two specific cases include stepping too near an invulnerable monster, and blinking next to an invulnerable monster.

ANALYSIS

CASE 1: Ally too close to invulnerable monster

Allies will flee from monsters in some cases, as defined by allyFlees():

static boolean allyFlees(creature *ally, creature *closestEnemy) {

In particular, an ally will flee from any monster if monsterFleesFrom() returns true:

if (monsterFleesFrom(ally, closestEnemy)) {

Invulnerable monsters are one of the cases in which monsters will flee, but only if they are within 3 spaces of the enemy:

BrogueCE/src/brogue/Monsters.c

Lines 2955 to 2964 in 1ba4240

if (distanceBetween((pos){x, y}, defender->loc) >= 4) {
return false;
}
if ((defender->info.flags & (MONST_IMMUNE_TO_WEAPONS | MONST_INVULNERABLE))
&& !(defender->info.flags & MONST_IMMOBILE)) {
// Don't charge if the monster is damage-immune and is NOT immobile;
// i.e., keep distance from revenants and stone guardians but not mirror totems.
return true;
}

This is not enough distance to avoid being hit by the invulnerable monster when maneuvering in close quarters.

CASE 2: Ally blinks next to invulnerable monster

If there is an enemy nearby, an ally will move toward it. This occurs in moveAlly(), and correctly checks that the enemy is not invulnerable:

BrogueCE/src/brogue/Monsters.c

Lines 3153 to 3156 in 1ba4240

if (closestMonster
&& (distanceBetween((pos){x, y}, player.loc) < leashLength || (monst->bookkeepingFlags & MB_DOES_NOT_TRACK_LEADER))
&& !(monst->info.flags & MONST_MAINTAINS_DISTANCE)
&& !attackWouldBeFutile(monst, closestMonster)) {

But if the ally has the ability to blink, a new map of potential destinations is built, ignoring the invulnerable status of all monsters (including the closest one), and that map is used to decide where to blink.

BrogueCE/src/brogue/Monsters.c

Lines 3182 to 3188 in 1ba4240

if (target != monst
&& (!(target->bookkeepingFlags & MB_SUBMERGED) || (monst->bookkeepingFlags & MB_SUBMERGED))
&& monsterWillAttackTarget(monst, target)
&& distanceBetween((pos){x, y}, target->loc) < shortestDistance
&& traversiblePathBetween(monst, target->loc.x, target->loc.y)
&& (!monsterAvoids(monst, target->loc) || (target->info.flags & MONST_ATTACKABLE_THRU_WALLS))
&& (!target->status[STATUS_INVISIBLE] || ((monst->info.flags & MONST_ALWAYS_USE_ABILITY) || rand_percent(33)))) {

This means that blink-enabled allies will not take invulnerability into consideration when choosing a blink target.

RECOMMENDED FIX:

CASE 1 - swap the order of the distance check and invulnerable check. Add an arbitrary distance, greater than 4, to the invulnerable check. I recommend at least 6 spaces.

CASE 2 - Insert a check for attackWouldBeFutile() when building the blink map.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions