Table of Contents

Interface IBuffController

Namespace
FishMMO.Shared.Core
Assembly
FishMMO.Shared.dll

Interface for a character's buff controller, handling application, removal, and events for buffs and debuffs.

public interface IBuffController : ICharacterBehaviour
Inherited Members

Fields

OnAddBuff

Static event triggered when a buff (positive effect) is added. Carries the owner.

public static Action<IBuffController, Buff> OnAddBuff

Field Value

Action<IBuffController, Buff>

OnAddDebuff

Static event triggered when a debuff (negative effect) is added. Carries the owner.

public static Action<IBuffController, Buff> OnAddDebuff

Field Value

Action<IBuffController, Buff>

OnBuffTick

Static event fired each tick for every active buff, providing the owning controller and the current network tick for UI duration-bar updates via RemainingSeconds(uint).

public static Action<IBuffController, Buff, uint> OnBuffTick

Field Value

Action<IBuffController, Buff, uint>

Remarks

All five of these events carry their owner. They are static — one invocation list shared by every buff controller in the process — and they used to carry only the Buff, which has no owner either. The local player's buff and debuff strips subscribe to them, so every buff applied to every NPC, pet and other player in view was rendered onto the local player's own strips. The strips looked correct only because keying by template ID hid duplicates; a debuff landing on a mob genuinely appeared on the player.

Subscribers MUST compare the controller against the one they care about. There is no way to scope a static event at subscription time, so the filter has to be at the callback.

OnObservedBuffsChanged

Raised when this character's buff set changes on this peer — applied by its own simulation, or materialised from the server's message on a peer that only observes it. Subscribers read Buffs; there is no separate display list.

public static Action<IBuffController> OnObservedBuffsChanged

Field Value

Action<IBuffController>

OnRemoveBuff

Static event triggered when a buff (positive effect) is removed. Carries the owner.

public static Action<IBuffController, Buff> OnRemoveBuff

Field Value

Action<IBuffController, Buff>

OnRemoveDebuff

Static event triggered when a debuff (negative effect) is removed. Carries the owner.

public static Action<IBuffController, Buff> OnRemoveDebuff

Field Value

Action<IBuffController, Buff>

Properties

Buffs

Dictionary of all active buffs for the character, indexed by template ID.

SortedDictionary<int, Buff> Buffs { get; }

Property Value

SortedDictionary<int, Buff>

OnBuffApplyTriggers

Triggers invoked when a buff or debuff is applied to this character. EventData: BuffEventData.

List<Trigger> OnBuffApplyTriggers { get; }

Property Value

List<Trigger>

OnBuffRemoveTriggers

Triggers invoked when a buff or debuff is removed from this character. EventData: BuffEventData.

List<Trigger> OnBuffRemoveTriggers { get; }

Property Value

List<Trigger>

SimulatesBuffEffects

True when this peer runs this character's buff EFFECTS, rather than merely tracking the strip for display.

bool SimulatesBuffEffects { get; }

Property Value

bool

Remarks

The server always does; the owning client does too, because it predicts its own simulation. A third-party observer holds real Buff instances — Inspect, the target frame and aggro all read them — but has never run Buff.Apply, so it must not run Buff.Remove either, and must not spend anything a buff is holding.

On the interface because mitigation asks it from outside the controller: DamageMitigation is allowed to COMPUTE how much a shield would block on any peer — which is what lets a caster predict a blocked hit honestly — but may only spend the pool where this is true.

Methods

Apply(BaseBuffTemplate, PredictionTick, ICharacter)

Applies a buff to the character by template, creating a new instance if needed and handling stacking.

void Apply(BaseBuffTemplate template, PredictionTick currentTick, ICharacter caster = null)

Parameters

template BaseBuffTemplate

The buff template to apply.

currentTick PredictionTick

The replicate-domain tick at the moment of application.

caster ICharacter

The character applying the buff, snapshotted so periodic effects have somebody to credit. May be null when the source has no initiator.

Apply(Buff, bool)

Applies a buff instance to the character if not already present, invoking appropriate events.

void Apply(Buff buff, bool suppressFX = false)

Parameters

buff Buff

The buff instance to apply.

suppressFX bool

ApplyAuthoritative(BaseBuffTemplate, uint, ICharacter)

Applies a buff from a server-authoritative context. Implementations should stamp the buff with their current replicate-domain tick when one is available.

void ApplyAuthoritative(BaseBuffTemplate template, uint serverTick, ICharacter caster = null)

Parameters

template BaseBuffTemplate

The buff template to apply.

serverTick uint

Fallback authoritative tick used before any replicate tick exists.

caster ICharacter

The character applying the buff, snapshotted so periodic effects have somebody to credit. May be null when the source has no initiator.

CreateReconcileSnapshot()

Creates a reconcile snapshot of all active buffs. Returns null when no buffs are active.

BuffReconcileEntry[] CreateReconcileSnapshot()

Returns

BuffReconcileEntry[]

GetCurrentDomainTick()

Gets the current tick in the controller's replicate-domain. This is the reference tick used for all buff comparisons.

uint GetCurrentDomainTick()

Returns

uint

The current replicate-domain tick.

MarkBuffStateDirty()

Records that a buff's predicted state changed underneath the controller, so the next reconcile snapshot is rebuilt rather than served from the cache.

void MarkBuffStateDirty()

Remarks

Every ordinary mutation runs through the controller, which marks itself. Damage mitigation does not: DamageMitigation spends RemainingCharges on the Buff instance directly, from inside the damage pipeline, and the controller has no way to notice. Left unmarked, CreateReconcileSnapshot keeps handing back the cached array — so the server never reports the spent shield and the owner never learns its pool moved.

Deliberately narrow: it dirties the snapshot and nothing else. The observed strip does not carry charges, so a spend is not an observer-visible change and must not cost a broadcast.

Remove(int)

Removes a buff by template ID, invoking removal events and cleaning up.

void Remove(int buffID)

Parameters

buffID int

The template ID of the buff to remove.

RemoveAll(bool, bool, bool)

Removes all non-permanent buffs from the character, optionally suppressing removal events.

void RemoveAll(bool ignoreInvokeRemove = false, bool includePermanent = false, bool preserveFX = false)

Parameters

ignoreInvokeRemove bool

If true, does not invoke OnRemoveBuff/OnRemoveDebuff events.

includePermanent bool

True to remove permanent buffs as well. Default false so gameplay dispels leave them alone; the lifecycle callers pass true, because a pooled object inheriting the previous occupant's permanent buff also inherits its attribute modifiers.

preserveFX bool

True to leave buff effects showing. For a REFRESH — the spawn payload clears before it re-reads — where tearing effects down first makes every surviving buff's FX restart. Whatever is genuinely gone is despawned by the diff that follows.

RemoveRandom(DeterministicRNG, bool, bool)

Removes a random non-permanent buff or debuff, filtered by inclusion flags.

void RemoveRandom(DeterministicRNG rng, bool includeBuffs = false, bool includeDebuffs = false)

Parameters

rng DeterministicRNG

The deterministic random number generator to use.

includeBuffs bool

Whether to include buffs in the selection.

includeDebuffs bool

Whether to include debuffs in the selection.

ResolveAuthoritativeTick(uint)

Maps a raw authoritative tick to the controller's current replicate-domain tick when a replicate tick is available.

uint ResolveAuthoritativeTick(uint serverTick)

Parameters

serverTick uint

Fallback authoritative tick used before any replicate tick exists.

Returns

uint

The effective tick to use for buff comparisons.

RestoreFromReconcile(BuffReconcileEntry[], uint)

Restores buff state from a reconcile snapshot.

void RestoreFromReconcile(BuffReconcileEntry[] entries, uint reconcileTick)

Parameters

entries BuffReconcileEntry[]

Authoritative buff snapshot.

reconcileTick uint

Replicate tick associated with the reconcile snapshot.

Tick(uint)

Deterministic buff tick — evaluates expiry and tick conditions for all active buffs. Use this for CSP instead of relying on Unity's Update.

void Tick(uint currentTick)

Parameters

currentTick uint

The current network tick.