Class AbilityController
Partial class for AbilityController handling network payload serialization and client-side broadcast registration for abilities and knowledge.
public class AbilityController : CharacterBehaviour, IAbilityController, IAbilityKnowledgeController, ICharacterBehaviour, IPredictableController
- Inheritance
-
ObjectComponentBehaviourMonoBehaviourNetworkBehaviourAbilityController
- Implements
- Inherited Members
-
NetworkBehaviour.IsSpawnedNetworkBehaviour.ComponentIndexNetworkBehaviour.NetworkObjectNetworkBehaviour.MAXIMUM_NETWORKBEHAVIOURSNetworkBehaviour.UNSET_NETWORKBEHAVIOUR_IDNetworkBehaviour.ToString()NetworkBehaviour.Reset()NetworkBehaviour.OnValidate()NetworkBehaviour.IsBehaviourReconcilingNetworkBehaviour.ClearReplicateCache()NetworkBehaviour.CreateReconcile()NetworkBehaviour.Reconcile_Reader<T>(PooledReader, ref T)NetworkBehaviour.OnStartServerCalledNetworkBehaviour.OnStartClientCalledNetworkBehaviour.OnStartServer()NetworkBehaviour.OnStopServer()NetworkBehaviour.OnOwnershipServer(NetworkConnection)NetworkBehaviour.OnSpawnServer(NetworkConnection)NetworkBehaviour.OnDespawnServer(NetworkConnection)NetworkBehaviour.OnStartClient()NetworkBehaviour.OnStopClient()NetworkBehaviour.OnOwnershipClient(NetworkConnection)NetworkBehaviour.ClearBuffedRpcs()NetworkBehaviour.ExcludeOwnerFromUnbufferedObserversRpcsNetworkBehaviour.IsClientOnlyNetworkBehaviour.IsServerOnlyNetworkBehaviour.IsHostNetworkBehaviour.IsClientNetworkBehaviour.IsServerNetworkBehaviour.IsDeinitializingNetworkBehaviour.NetworkManagerNetworkBehaviour.ServerManagerNetworkBehaviour.ClientManagerNetworkBehaviour.ObserverManagerNetworkBehaviour.TransportManagerNetworkBehaviour.TimeManagerNetworkBehaviour.SceneManagerNetworkBehaviour.PredictionManagerNetworkBehaviour.RollbackManagerNetworkBehaviour.NetworkObserverNetworkBehaviour.IsClientInitializedNetworkBehaviour.IsClientStartedNetworkBehaviour.IsClientOnlyInitializedNetworkBehaviour.IsClientOnlyStartedNetworkBehaviour.IsServerInitializedNetworkBehaviour.IsServerStartedNetworkBehaviour.IsServerOnlyInitializedNetworkBehaviour.IsServerOnlyStartedNetworkBehaviour.IsHostInitializedNetworkBehaviour.IsHostStartedNetworkBehaviour.IsOfflineNetworkBehaviour.IsNetworkedNetworkBehaviour.GetIsNetworked()NetworkBehaviour.IsManagerReconcilingNetworkBehaviour.ObserversNetworkBehaviour.IsOwnerNetworkBehaviour.IsControllerNetworkBehaviour.HasAuthorityNetworkBehaviour.OwnerNetworkBehaviour.OwnerIdNetworkBehaviour.ObjectIdNetworkBehaviour.LocalConnectionNetworkBehaviour.OwnerMatches(NetworkConnection)NetworkBehaviour.Despawn(GameObject, DespawnType?)NetworkBehaviour.Despawn(NetworkObject, DespawnType?)NetworkBehaviour.Despawn(DespawnType?)NetworkBehaviour.Spawn(GameObject, NetworkConnection, Scene)NetworkBehaviour.Spawn(NetworkObject, NetworkConnection, Scene)NetworkBehaviour.RemoveOwnership()NetworkBehaviour.GiveOwnership(NetworkConnection)NetworkBehaviour.GetInstance<T>()NetworkBehaviour.TryRegisterInstance<T>(T)NetworkBehaviour.UnregisterInstance<T>()NetworkBehaviour.CanLog(LoggingType)MonoBehaviour.IsInvoking()MonoBehaviour.CancelInvoke()MonoBehaviour.StopCoroutine(Coroutine)MonoBehaviour.StopAllCoroutines()MonoBehaviour.destroyCancellationTokenMonoBehaviour.useGUILayoutMonoBehaviour.didStartMonoBehaviour.didAwakeMonoBehaviour.runInEditModeBehaviour.enabledBehaviour.isActiveAndEnabledComponent.GetComponent<T>()Component.TryGetComponent<T>(out T)Component.GetComponentInChildren<T>()Component.GetComponentsInChildren<T>()Component.GetComponentInParent<T>()Component.GetComponentsInParent<T>()Component.GetComponents<T>()Component.GetComponentIndex()Component.CompareTag(TagHandle)Component.transformComponent.transformHandleComponent.gameObjectComponent.tagObject.GetEntityId()Object.GetInstanceID()Object.GetHashCode()Object.InstantiateAsync<T>(T)Object.InstantiateAsync<T>(T, Transform)Object.InstantiateAsync<T>(T, Vector3, Quaternion)Object.InstantiateAsync<T>(T, Transform, Vector3, Quaternion)Object.Instantiate(Object, Vector3, Quaternion)Object.Instantiate(Object, Vector3, Quaternion, Transform)Object.Instantiate(Object)Object.Instantiate(Object, Scene)Object.Instantiate<T>(T, InstantiateParameters)Object.Instantiate<T>(T, Vector3, Quaternion, InstantiateParameters)Object.Instantiate(Object, Transform)Object.Instantiate<T>(T)Object.Instantiate<T>(T, Vector3, Quaternion)Object.Instantiate<T>(T, Vector3, Quaternion, Transform)Object.Instantiate<T>(T, Transform)Object.Destroy(Object)Object.DestroyImmediate(Object)Object.DontDestroyOnLoad(Object)Object.DestroyObject(Object)Object.FindObjectsOfType<T>()Object.FindObjectsByType<T>(FindObjectsSortMode)Object.FindObjectsByType<T>(FindObjectsInactive, FindObjectsSortMode)Object.FindObjectOfType<T>()Object.FindFirstObjectByType<T>()Object.FindAnyObjectByType<T>()Object.FindFirstObjectByType<T>(FindObjectsInactive)Object.FindAnyObjectByType<T>(FindObjectsInactive)Object.FindObjectsByType<T>()Object.FindObjectsByType<T>(FindObjectsInactive)Object.nameObject.hideFlags
Fields
AbilitySpawner
Transform used as the spawn point for ability objects (e.g., projectiles).
public Transform AbilitySpawner
Field Value
- Transform
AttackSpeedReductionTemplate
Attribute template for attack speed reduction (physical abilities).
public CharacterAttributeTemplate AttackSpeedReductionTemplate
Field Value
BloodResourceConversionTemplate
Ability event template for converting blood resource (e.g., health for mana).
public AbilityEvent BloodResourceConversionTemplate
Field Value
CastSpeedReductionTemplate
Attribute template for cast speed reduction (magical abilities).
public CharacterAttributeTemplate CastSpeedReductionTemplate
Field Value
ChanneledTemplate
Ability event template for channeled abilities.
public AbilityEvent ChanneledTemplate
Field Value
ChargedTemplate
Ability event template for charged abilities.
public AbilityEvent ChargedTemplate
Field Value
CooldownReductionTemplate
Attribute template for cooldown reduction.
public CharacterAttributeTemplate CooldownReductionTemplate
Field Value
NO_ABILITY
Constant representing no active ability.
public const long NO_ABILITY = 0
Field Value
ObserverPredictionWindowTicks
Maximum tick difference for observer held-state prediction. At high RTT (e.g., 200ms at 30 tick/s = 6+ ticks of buffered data), a window of 1 causes channeled beams/charges to visually stutter on observers. Widen to match expected RTT in ticks.
public uint ObserverPredictionWindowTicks
Field Value
Properties
AbilityQueued
True if an ability is queued to activate after the current one.
public bool AbilityQueued { get; }
Property Value
IsActivating
True if an ability is currently being activated.
public bool IsActivating { get; }
Property Value
KnownAbilities
All known abilities for this character, indexed by ability ID.
public SortedDictionary<long, Ability> KnownAbilities { get; }
Property Value
Remarks
SECURITY: This dictionary must only be populated via server-authoritative code paths (WritePayload / ReadPayload). All activation methods (Activate(long, bool), CanActivate(long, uint, out Ability)) gate on membership in this dictionary, so a desync or bug that adds an unearned ability would let the character activate it. Ensure no client-only code path can insert entries.
KnownAbilityEvents
All known ability event template IDs for this character.
public HashSet<int> KnownAbilityEvents { get; }
Property Value
KnownAbilityOnDestroyEvents
All known OnDestroy event template IDs for this character.
public HashSet<int> KnownAbilityOnDestroyEvents { get; }
Property Value
KnownAbilityOnHitEvents
All known OnHit event template IDs for this character.
public HashSet<int> KnownAbilityOnHitEvents { get; }
Property Value
KnownAbilityOnPreSpawnEvents
All known OnPreSpawn event template IDs for this character.
public HashSet<int> KnownAbilityOnPreSpawnEvents { get; }
Property Value
KnownAbilityOnSpawnEvents
All known OnSpawn event template IDs for this character.
public HashSet<int> KnownAbilityOnSpawnEvents { get; }
Property Value
KnownAbilityOnTickEvents
All known OnTick event template IDs for this character.
public HashSet<int> KnownAbilityOnTickEvents { get; }
Property Value
KnownBaseAbilities
All known base ability template IDs for this character.
public HashSet<int> KnownBaseAbilities { get; }
Property Value
LongestKnownAbilityRange
The longest range among this character's known abilities — how far it can reach, and so how far out its observer needs tick-exact transforms for lag compensation to be honest.
public float LongestKnownAbilityRange { get; }
Property Value
Remarks
Recomputed only when the known set changes, because it is read per observer per LOD
evaluation. Note Ability.Range is Speed * LifeTime and no ability template
currently authors a Speed, so this is 0 for all present content and
ObserverStreamingPolicy.EngagementRange's floor is what applies.
OnAbilityActivateTriggers
Triggers invoked on the server when an ability activation begins (non-replay).
public List<Trigger> OnAbilityActivateTriggers { get; }
Property Value
OnAbilityCompleteTriggers
Triggers invoked on the server when an ability activation completes (non-replay).
public List<Trigger> OnAbilityCompleteTriggers { get; }
Property Value
Order
Execution order for this controller during the prediction tick. Lower values run first. Movement should run before abilities so that camera/position state is fresh for ability aiming.
public int Order { get; }
Property Value
RemainingActivationTime
The remaining activation time for the current ability, or 0 if no ability is active. Converts internal tick count back to seconds for UI and NPC AI consumers.
public float RemainingActivationTime { get; }
Property Value
Methods
Activate(long, bool)
Attempts to activate an ability by reference ID and held state, if all conditions are met.
public void Activate(long referenceID, bool isHeld)
Parameters
referenceIDlongThe ability reference ID to activate.
isHeldboolWhether the activation key is held.
ActivateConsumable(Item)
Queues a consumable item for activation through the replicate pipeline. Sets the IsConsumable flag and stores the consumable template ID in the ability queue. Validates that the consumable can be used before queuing.
public void ActivateConsumable(Item item)
Parameters
itemItemThe consumable item to activate.
CalculateSpeedReduction(CharacterAttributeTemplate)
Calculates the speed reduction factor for ability activation based on the given attribute.
public float CalculateSpeedReduction(CharacterAttributeTemplate attribute)
Parameters
attributeCharacterAttributeTemplateThe attribute template to use for calculation.
Returns
- float
The speed reduction multiplier (1.0 = no reduction).
Remarks
DESYNC RISK: This method reads live attribute values from
ICharacterAttributeController. During prediction replay,
the attribute controller may have reconciled in a different order than
the ability controller. If a buff/debuff modifies cast/attack speed
mid-cast, the remainingTicks computed here during prediction may
differ from the server's value. This is corrected by the reconcile data
which includes RemainingTicks — the
desync is limited to the prediction window.
CanManipulate()
Checks if the character is in a valid state to manipulate abilities (not teleporting, not despawned, etc).
public bool CanManipulate()
Returns
- bool
True if the character can manipulate abilities, false otherwise.
Cancel()
Cancels the current ability activation and resets all related state. Unlocks the consumable inventory slot if one was locked. Clears persistent flags from both local input and replicated state.
public void Cancel()
GetActivationAttributeTemplate(Ability)
Gets the appropriate attribute template for activation speed reduction based on the ability type. Physical variants (including None) use AttackSpeedReductionTemplate; all other variants use CastSpeedReductionTemplate.
public CharacterAttributeTemplate GetActivationAttributeTemplate(Ability ability)
Parameters
abilityAbilityThe ability to check.
Returns
- CharacterAttributeTemplate
The attribute template for speed reduction.
GetCurrentAbilityType()
Gets the current ability type, considering any type override.
public AbilityType GetCurrentAbilityType()
Returns
- AbilityType
The current AbilityType if an ability is active, otherwise None.
Interrupt(ICharacter)
Interrupts the current ability: through the input stream where this peer writes it, and directly where it does not.
public void Interrupt(ICharacter attacker)
Parameters
attackerICharacterThe character causing the interrupt (not used).
Remarks
The queued half only works for the peer that produces this character's input.
localInputFlags is read by HandleCharacterInput, which runs only from
PopulateInput, which CharacterPredictionController invokes only
where HasInputAuthority — the owning client for a player, the server for an AI
character or a pet. That covers a player interrupting itself and every server-side AI
call site, and it is the better path for them: the cancel then happens inside the
deterministic replicate and is reconciled like any other predicted state.
It did nothing at all for the case the mechanic exists for.
InterruptAction is server-only and its target is normally a PLAYER — which is
neither server-driven nor owned by the server, so the bit was set on a peer that never
reads it, never cleared (only HandleCharacterInput clears it), and the cast simply
ran to completion. Cast interruption worked against NPCs and pets and failed silently
against players.
So the server cancels directly when it is not the peer that writes this character's
input. It is authoritative for the activation either way — currentAbilityID,
remainingTicks, chargedHoldTicks and replicatedFlags all ride
CharacterReconcileData — so the owner's next reconcile carries the cleared
state and its prediction is corrected by the same machinery that corrects a denied
activation. The owner's cast bar is cleared by ReconcilePredictedHistory, which
already fires OnCancel when it predicted an ability the server does not have.
No cooldown is added, matching ProcessInterrupt(AbilityActivationReplicateData, ReplicateState): an interrupted cast is
lost, not put on cooldown. OnCancel is suppressed for the reason it is suppressed
there too — OnInterrupt is the event UI subscribers pair with, and firing both
makes a cast bar flicker.
KnowsAbility(int)
Checks if the controller knows a base ability with the given template ID.
public bool KnowsAbility(int templateID)
Parameters
templateIDintThe base ability template ID to check.
Returns
- bool
True if the base ability is known, false otherwise.
KnowsAbilityEvent(int)
Checks if the controller knows the specified ability event by event ID.
public bool KnowsAbilityEvent(int eventID)
Parameters
eventIDintThe event template ID to check.
Returns
- bool
True if the event is known, false otherwise.
KnowsLearnedAbility(int)
Checks if the controller knows an ability instance with the given template ID. Uses the FishMMO.Shared.AbilityController.templateToAbilityID reverse index for O(1) lookups.
public bool KnowsLearnedAbility(int templateID)
Parameters
templateIDintThe template ID to check.
Returns
- bool
True if the ability is known, false otherwise.
LearnAbility(Ability, float)
Adds the given ability to the known abilities set, and applies any remaining cooldown if specified.
public void LearnAbility(Ability ability, float remainingCooldown = 0)
Parameters
abilityAbilityThe ability to learn.
remainingCooldownfloatOptional remaining cooldown to apply to the ability.
Remarks
SECURITY: This method is public because it implements LearnAbility(Ability, float). All current call sites are server-authoritative:
- AbilityController.Networking.cs — ReadPayload/WritePayload (server sync).
- NPC.cs — server-side NPC initialisation.
- CharacterSystem.Loading.cs — server-side character loading from DB.
- InteractableSystem.AbilityCraft.cs — server-side ability crafting.
If a new call site is added that is reachable from client-controlled input (e.g., a broadcast handler), it MUST perform its own server-side validation before calling this method. An attacker with a crafted packet could otherwise grant themselves arbitrary abilities.
LearnAbilityEvent(AbilityEvent)
Adds a single ability event to the known event sets without allocating a list.
public bool LearnAbilityEvent(AbilityEvent abilityEvent)
Parameters
abilityEventAbilityEventThe ability event to learn.
Returns
- bool
True if the event was learned, false if input is null.
LearnAbilityEvents(List<AbilityEvent>)
Adds the provided ability events to the known event sets, categorizing them by event type.
public bool LearnAbilityEvents(List<AbilityEvent> abilityEvents = null)
Parameters
abilityEventsList<AbilityEvent>List of ability events to learn.
Returns
- bool
True if any events were learned, false if input is null.
LearnBaseAbilities(List<BaseAbilityTemplate>)
Adds the provided base ability templates to the known base abilities set.
public bool LearnBaseAbilities(List<BaseAbilityTemplate> abilityTemplates = null)
Parameters
abilityTemplatesList<BaseAbilityTemplate>List of base ability templates to learn.
Returns
- bool
True if any templates were learned, false if input is null.
LearnBaseAbility(BaseAbilityTemplate)
Adds a single base ability template to the known base abilities set without allocating a list.
public bool LearnBaseAbility(BaseAbilityTemplate template)
Parameters
templateBaseAbilityTemplateThe base ability template to learn.
Returns
- bool
True if the template was learned, false if input is null.
OnAwake()
Unity Awake callback. Initialises all known-ability and event collections.
public override void OnAwake()
OnCreateReconcile(ref CharacterReconcileData)
Writes this controller's authoritative state into the reconcile data (server only). Called once per tick after OnReplicate(ref CharacterReplicateData, ReplicateState, Channel).
public void OnCreateReconcile(ref CharacterReconcileData reconcileData)
Parameters
reconcileDataCharacterReconcileData
OnReconcile(CharacterReconcileData, Channel)
Restores this controller's state from the server's authoritative reconcile data.
public void OnReconcile(CharacterReconcileData rd, Channel channel)
Parameters
rdCharacterReconcileDatachannelChannel
OnReplicate(ref CharacterReplicateData, ReplicateState, Channel)
Executes this controller's simulation for the current tick.
May modify input for observer prediction.
public void OnReplicate(ref CharacterReplicateData input, ReplicateState state, Channel channel)
Parameters
inputCharacterReplicateDatastateReplicateStatechannelChannel
OnStartCharacter()
Called when the character starts. On the owning client, registers network broadcast handlers for learning abilities and events, then fires OnReset and OnAddAbility for all known abilities.
public override void OnStartCharacter()
OnStartNetwork()
FishNet OnStartNetwork callback. Resolves component caches and initialises the ability seed generator.
public override void OnStartNetwork()
OnStopCharacter()
Called when the character stops. On the owning client, unregisters all network broadcast handlers for abilities and events.
public override void OnStopCharacter()
OnStopNetwork()
FishNet OnStopNetwork callback. Releases component caches and clears events.
public override void OnStopNetwork()
PopulateInput(ref CharacterReplicateData)
Populates this controller's portion of the unified input data (owner only). Called once per tick before OnReplicate(ref CharacterReplicateData, ReplicateState, Channel).
public void PopulateInput(ref CharacterReplicateData input)
Parameters
inputCharacterReplicateData
ReadPayload(NetworkConnection, Reader)
Reads the ability controller's state from the network payload, including ability RNG seed, known abilities, and cooldowns.
public override void ReadPayload(NetworkConnection conn, Reader reader)
Parameters
connNetworkConnectionThe network connection.
readerReaderThe network reader to read from.
RegisterObservedAbility(long, AbilityTemplate, List<int>)
Files an ability this peer was told about because it OBSERVES the caster.
public void RegisterObservedAbility(long abilityID, AbilityTemplate template, List<int> abilityEvents)
Parameters
abilityIDlongThe ability instance id used by activation broadcasts.
templateAbilityTemplateThe template the ability was built from.
abilityEventsList<int>Crafted event ids, or null.
Remarks
Goes straight into KnownAbilities. An observer's copy of a peer's set is
written once by ReadPayload when it starts observing, so without this anything
the caster learned afterwards stayed unknown and every cast of it was dropped by
OnAbilityActivatedBroadcast — invisible for the rest of the session.
AbilityLearnedObserverBroadcast is what closes that gap.
This used to land in a separate observer-only dictionary so that CanActivate(long, uint, out Ability), which gates on KnownAbilities, could keep the invariant that only server-authoritative paths populate it. A local client is required to hold an observed character's real state — Inspect and faction/aggro evaluation read it, not just the renderer — so the parallel set was the wrong shape and is gone. The invariant is preserved more cheaply by the owner check below.
Never applied to our own character. The owner learns through the authoritative
KnownAbilityAddBroadcast family, which is registered for the owner alone. This
message only ever describes somebody else, so refusing it on our own character costs
nothing and means a forged learn can never reach the dictionary an activation is gated
on.
Release()
Releases the held state for the current ability. For charged abilities this triggers the release (fire). For channeled abilities this stops the channel early.
public void Release()
RemoveAbility(long)
Removes the ability with the given reference ID from the known abilities set.
public void RemoveAbility(long referenceID)
Parameters
referenceIDlongThe ability reference ID to remove.
RequiresHeld(long)
Returns true if the given ability requires held input (channeled or charged). AI should pass the result as the isHeld parameter when calling Activate().
public bool RequiresHeld(long abilityID)
Parameters
abilityIDlongThe ability ID to check.
Returns
ResetState(bool)
Resets this NetworkBehaviour so that it may be added to an object pool.
public override void ResetState(bool asServer)
Parameters
asServerbool
TryGetAbilityForVisuals(long, out Ability)
Resolves an ability for the visual reproduction paths (activation and destroy broadcasts).
public bool TryGetAbilityForVisuals(long abilityID, out Ability ability)
Parameters
Returns
Remarks
A thin wrapper over KnownAbilities, kept as its own method because the call sites are the VISUAL paths and naming them as such is what stops somebody reaching for this to decide whether a character may cast. That remains CanActivate(long, uint, out Ability)'s job.
WritePayload(NetworkConnection, Writer)
Writes the ability controller's state to the network payload, including ability RNG seed, known abilities, and cooldowns.
public override void WritePayload(NetworkConnection conn, Writer writer)
Parameters
connNetworkConnectionThe network connection.
writerWriterThe network writer to write to.
Events
OnAbilityDenied
Fired when the server denies an ability the client already started predicting. The ability ID is the one the client predicted but the server rejected. Subscribers should show an "interrupted" flash, restore predicted resource costs, etc.
public event Action<long> OnAbilityDenied
Event Type
OnAddAbility
Event invoked when a new ability is added to the character.
public event Action<Ability> OnAddAbility
Event Type
OnAddKnownAbility
Event invoked when a new base ability is learned.
public event Action<BaseAbilityTemplate> OnAddKnownAbility
Event Type
OnAddKnownAbilityEvent
Event invoked when a new ability event is learned.
public event Action<AbilityEvent> OnAddKnownAbilityEvent
Event Type
OnCanManipulate
Event invoked to check if the character can manipulate abilities (e.g., not stunned). Backed by a list to avoid per-call delegate array allocation.
public event Func<bool> OnCanManipulate
Event Type
Remarks
Handlers are iterated in REVERSE so that a handler that unsubscribes itself
during its Invoke() does not cause the next entry to be skipped (forward
iteration would shift the indices). Adding a new handler during iteration is
still unsupported and will produce an extra invoke on the inserted handler.
OnCancel
Event invoked when the current ability is cancelled.
public event Action OnCancel
Event Type
OnConsumableUsed
Invoked on both client and server after a consumable is successfully consumed via this controller's activation pipeline. Server-side subscribers should send the appropriate InventorySetItemBroadcast or InventoryRemoveItemBroadcast to the owning client. Client-side subscribers can use this for UI feedback or validation. Parameters: (character, consumableTemplateID, inventorySlot).
public event Action<ICharacter, int, int> OnConsumableUsed
Event Type
- Action<ICharacter, int, int>
OnInterrupt
Event invoked when the current ability is interrupted.
public event Action OnInterrupt
Event Type
OnPredictionMismatch
Fired when predicted ability objects are destroyed due to state mismatch. Provides the reconcile tick used for rollback so clients can trigger correction VFX/UI. For small timing mismatches (1-2 ticks), the ability is replayed automatically and no visual correction is needed. For larger mismatches, subscribers may want to hide/fade correction artifacts.
public event Action<uint> OnPredictionMismatch
Event Type
OnRemoveAbility
Event triggered when a crafted ability is removed (forgotten / re-crafted). Carries the ability's reference ID; the instance is already gone by then.
public event Action<long> OnRemoveAbility
Event Type
Remarks
The add half of this pair has always existed. Without the remove half every subscriber had to poll KnownAbilities to notice a forgotten ability — which is exactly what the hotkey bar was doing, on every frame, for all twelve slots.
OnReset
Event invoked to reset the ability UI.
public event Action OnReset
Event Type
OnUpdate
Event for ability UI updates (e.g., cast bar, telegraphs).
public event Action<string, float, float> OnUpdate