Files
healer-man/docs/HOSTILE_NPC_THREAT_BOUNDARY_2026-10-06.md
2026-10-06 22:25:34 -04:00

4.5 KiB

Hostile NPC threat boundary audit — 2026-10-06

Decision

The hostile-NPC outgoing threat item in ACTIVE_CLASS_MECHANICS_BACKLOG.md is not a missing consumer for the current hostile-mob combat path. HealerMan stores each hostile mob's incoming target threat on that mob, keyed by the player, party, online-player, or summon actors that the mob can currently attack. Its enemy target selector has no hostile mob candidates, and the enemy-hit path does not write threat into the attacking mob's table. The current model has no NPC-versus-NPC target boundary to port.

Keep this source-parity item scoped as a future boundary. If hostile creatures later attack other threat-list-capable creatures, record the attacker in the recipient creature's threat list after checking that recipient's eligibility. Do not add outgoing threat to the source mob's own target table.

AzerothCore holder and direction rules

The read-only behavior reference is AzerothCore HEAD e822d718322289dd036fb2daf8867ba41283bf9a. Its ThreatManager.cpp SHA-256 is 5f8ee4d9c8d9e6d41896b29769f0df315f62d789f2defa29df0a9912002f537b; its Unit.cpp SHA-256 is b7c0c68daee09ec1f863f9a8d6c4972c1adbe35fa5ec230a8887399395db1ed5.

ThreatManager::CanHaveThreatList requires a creature. It excludes pets, totems, triggers, and player-summoned minions or guardians. Unit::CanHaveThreatList also rejects dead units and vehicles in battlegrounds or arenas. Players therefore do not own creature threat lists. These are rules about the list holder, not about who may appear as a target in a creature's list: a hostile creature can still track threat against a player or pet.

In Unit.cpp:1276, damage to a non-player victim calls victim->AddThreat(attacker, damage, ...). Unit::AddThreat checks the recipient (victim) with CanHaveThreatList() and adds the attacker to that recipient's threat manager. ThreatManager::CalculateModifiedThreat applies the threat aura multiplier from the threat target passed to that manager, which is the damage source in this call. Thus damage threat belongs to the recipient list and is scaled by source-side threat modifiers.

Current HealerMan path

MobCombatState carries threatByActor, targetActorId, and forcedTarget. eligibleAggroActorIds builds candidates from the living local player, living PartyMember records, live online-player actors, and living combat summons; each must have a position within the hostile mob's leash. actorPosition resolves positions from those same actor sources. The candidate builder does not enumerate other MobCombatState records.

Party records are playable-character builds with class, specialization, role, level, gear, and talent data. companionActorFromMember projects them as kind: "companion", and advanceDungeonPartyCombat runs their combat actions. They are managed party actors, not unowned AzerothCore creature AI instances. CombatSummon records likewise carry an ownerActorId and a pet, totem, or summon kind. They are valid hostile-mob targets here; that does not make them threat-list holders.

When a party actor damages a mob, damageMobInWork adds threat under the source actor ID to that damaged mob's threatByActor. Healing adds source threat to each engaged living mob's table. The local threat aura lookup uses the source actor's aura set before the value is added. advanceMobCombat prunes each mob table to the eligible actors above and resolves that mob's target from those entries. Enemy attacks then resolve against that selected actor. The hit handling updates damage, health, and presentation state; it does not add threat to the attacking mob's own table.

Hostile NPC helpers are also stored as MobCombatState entries, distinct from player or party CombatSummon entries. A helper spawn records summonedBy; call-for-help seeds the helper's own table with the same selected party target. This preserves the current party-versus-hostile-mob model without adding a mob-to-mob target path.

Backlog boundary

The current backlog phrase should remain future-facing or be narrowed when the backlog is next edited: source-side outgoing threat is only relevant to an enemy-versus-enemy consumer if that consumer models a living recipient creature with a threat list and a real target relationship. At that point, threat goes on the recipient and the holder gate applies there. Do not model it by inverting signs, mutating the attacker mob's table, or treating a playable party build as an ordinary unowned creature.

No runtime code, catalog, or backlog file was changed for this audit.