Class AggressionDispatcher
Routes combat events to the one NPC that cares about them, instead of broadcasting every event to every NPC in the scene.
public static class AggressionDispatcher
- Inheritance
-
AggressionDispatcher
- Inherited Members
Remarks
The problem this replaces. Each AggressionState used to subscribe individually to the global damage, heal and kill events. That meant a single sword swing invoked one delegate per NPC in the scene — a thousand NPCs, a thousand calls, of which exactly one was for the NPC actually being hit and 999 returned immediately from a reference comparison. At a busy raid boss with a few hundred hits per second the wasted work is measured in hundreds of thousands of calls per second, all to deliver a handful of events.
What it does instead. One subscription for the whole process. Damage is the hot path and is dispatched by dictionary lookup on the defender — O(1) regardless of how many NPCs exist. Heal and kill still have to consider several NPCs (a heal matters to anyone tracking either party), but they walk a plain list and skip anyone whose threat table is empty with a field read, which is what almost every NPC in a scene is at any moment.
Server-side only. Registration happens when an NPC's aggression state is built and is released when it is destroyed.
Properties
RegisteredCount
Number of NPCs currently registered. Diagnostics.
public static int RegisteredCount { get; }
Property Value
Methods
Clear()
Drops all registrations. Call on server shutdown.
public static void Clear()
LinkPet(ICharacter, ICharacter)
Declares pet to be owner's pet for the purpose of
threat: from now on damage to either is threat against both.
public static void LinkPet(ICharacter pet, ICharacter owner)
Parameters
petICharacterThe pet.
ownerICharacterIts owner.
Remarks
A pet and its owner are one target as far as hate is concerned. Hit the owner and the pet answers; hit the pet and the owner answers — an NPC with a brain by engaging the aggressor through its own aggression state, a player through whatever it chooses to do. Without this a pet's attackers were invisible to its owner and an owner's attackers invisible to the pet, so an NPC with a summon stood and watched it being killed.
Any owner, not only a player: the link is keyed on characters, so an NPC that is ever
given a pet gets the same behaviour with no further wiring. Kept here rather than on
Pet because the dispatcher is where a damage event is turned into threat, and the
lookup has to be one dictionary read on the hot path.
Register(ICharacter, AggressionState)
Registers an NPC's threat state to receive combat events.
public static void Register(ICharacter character, AggressionState state)
Parameters
characterICharacterThe NPC that owns the state.
stateAggressionStateThe threat state.
TryFindHighestThreatAgainst(ICharacter, Predicate<ICharacter>, out ICharacter)
Finds the registered NPC holding the most threat against subject.
public static bool TryFindHighestThreatAgainst(ICharacter subject, Predicate<ICharacter> accept, out ICharacter best)
Parameters
subjectICharacterThe character the threat is measured against.
acceptPredicate<ICharacter>Optional rule an NPC must pass to be considered.
bestICharacterThe NPC with the most threat against the subject.
Returns
- bool
True when one was found.
Remarks
"Whatever is attacking me and hates me most." An NPC's threat toward a character accumulates from that character's hits on it — and, since a pet's hits are credited to its owner, from the pet's hits too — so the highest entry is the thing the subject and its pet have attacked the most. That is the pet attack command's third choice, after the owner's pinned and hovered targets.
A scan of every registered table, so it is for a click, not a tick. The caller's
accept applies its own rules — alive, in range, hostile — before an
entry can win, so a distant grudge does not send the pet across the map.
TryGetPetOwner(ICharacter, out ICharacter)
The owner a pet is linked to, if any.
public static bool TryGetPetOwner(ICharacter pet, out ICharacter owner)
Parameters
petICharacterownerICharacter
Returns
UnlinkPet(ICharacter)
Removes pet's threat link, if it has one.
public static void UnlinkPet(ICharacter pet)
Parameters
petICharacterThe pet.
Unregister(ICharacter)
Stops routing events to an NPC's threat state.
public static void Unregister(ICharacter character)
Parameters
characterICharacterThe NPC that owns the state.