Class Buff
Represents a single instance of a buff applied to a character, tracking time, stacks, and template. All state is deterministic — timing is tick-based (ExpiryTick, NextTickTick) rather than float-second accumulators, eliminating floating-point drift across prediction ticks.
public class Buff
- Inheritance
-
Buff
- Inherited Members
Constructors
Buff(int, uint, float, int, int)
Creates a new buff instance from a fresh application.
ExpiryTick and NextTickTick are computed from
the template's duration and tick-rate via ceil(seconds / tickDelta),
matching CooldownInstance's convention.
public Buff(int templateID, uint currentTick, float tickDelta, int stacks = 0, int tickCount = 0)
Parameters
templateIDintThe template ID for the buff.
currentTickuintThe network tick at the moment of application.
tickDeltafloatFixed seconds-per-tick for the active session.
stacksintThe initial stack count.
tickCountintThe number of ticks that have already fired (for restoration).
Buff(int, uint, uint, float, int, int)
Restores a buff from serialized absolute-tick values (reconcile / payload restore). Does not recompute tick values from the template — uses the provided values directly.
public Buff(int templateID, uint expiryTick, uint nextTickTick, float tickDelta, int stacks, int tickCount)
Parameters
templateIDintThe template ID for the buff.
expiryTickuintAbsolute tick at which the buff expires.
nextTickTickuintAbsolute tick at which the next OnTick fires.
tickDeltafloatFixed seconds-per-tick (for RemainingSeconds(uint) UI conversion).
stacksintThe current stack count.
tickCountintThe number of ticks that have already fired.
Fields
CumulativeTickMultiplier
Running sum of (1 + Stacks) for every tick that has fired on this buff instance.
Tracks the exact cumulative multiplier applied by templates such as
AttributeTickBuffTemplate so that OnRemove can reverse
the precise total modifier regardless of how many times Stacks
changed between tick firings. Reconciled via
CumulativeTickMultiplier so rollback replay
and post-reconcile removal both produce correct reversal.
public int CumulativeTickMultiplier
Field Value
ExpiryTick
The absolute network tick at which this buff expires.
A buff has expired when (int)(currentTick - ExpiryTick) >= 0.
Permanent buffs use FishNet.Managing.Timing.TimeManager.UNSET_TICK.
public uint ExpiryTick
Field Value
NextTickTick
The absolute network tick at which the next OnTick(Buff, ICharacter) should fire. Advances by one tick-rate interval after each fire so missed intervals catch up without drifting the cadence to the late current tick.
public uint NextTickTick
Field Value
Stacks
The current number of stacks of this buff.
public int Stacks
Field Value
TickCount
The number of ticks that have fired for this buff instance. Used by cumulative tick templates to track total applied modifiers for clean reversal. Serialized in payload for deterministic restoration.
public int TickCount
Field Value
Version
Version number for this buff instance, used for database state-driven safety on updates. Incremented whenever the buff's state changes in a way that requires persistence (e.g., stacks added/removed, remaining time checkpointed).
public long Version
Field Value
Properties
Caster
The character to credit for this buff's periodic effects, or null when there is nobody left to credit.
public ICharacter Caster { get; }
Property Value
Remarks
Returns null once the caster has been destroyed — a player who disconnected, an NPC that despawned. That is deliberately not treated as a reason to stop ticking: a lingering poison is part of the simulation whether or not the person who applied it is still in the scene, so the effect lands with a null attacker and simply generates no threat and no kill credit.
The null check goes through UnityEngine.Object on purpose. A destroyed component compared through an interface reference uses reference equality and reports itself as non-null, so the plain test would hand out a dead object.
IsAuthoritative
True while the tick currently executing on this buff runs on the authoritative simulation (the server). False on every client, replayed or not.
public bool IsAuthoritative { get; }
Property Value
Remarks
With state forwarding off, only the owning client (prediction) and the server tick a buff. The owner's tick keeps predicted health responsive, but everything that is not a pure resource mutation — ECA tick triggers, threat, kill credit, achievements — must happen exactly once, on the server. IsReplaying alone cannot express that: the owner's first, non-replayed pass is still not authoritative. Set by TryTick(ICharacter, uint, float, bool, bool) from the value the controller passes.
IsReplaying
True while this buff is ticking inside a prediction replay rather than for the first time.
public bool IsReplaying { get; }
Property Value
Remarks
Reconcile replays every input since the last authoritative state, so a DoT's tick fires again on each pass. The resource mutation must repeat — that is what keeps the client's predicted health in step — but the ECA triggers hanging off it must not, or a single tick of poison counts a dozen times toward an achievement.
Template
The template that defines this buff's behavior and properties.
public BaseBuffTemplate Template { get; }
Property Value
Methods
AddStack(ICharacter)
Adds a stack to the buff and applies stack effects to the target.
public void AddStack(ICharacter target)
Parameters
targetICharacterThe character receiving the stack.
Apply(ICharacter)
Applies the buff's effects to the target character.
public void Apply(ICharacter target)
Parameters
targetICharacterThe character receiving the buff.
HasExpired(uint)
Returns true when this buff has expired at the given tick. Uses a signed cast for overflow-safe wrap-around comparison; safe for any duration < 2^31 ticks (~828 days at 30 tps).
public bool HasExpired(uint currentTick)
Parameters
currentTickuint
Returns
RemainingSeconds(uint)
Computes the remaining buff duration in seconds for the given tick. Returns zero if the buff has already expired. Used by the UI duration slider.
public float RemainingSeconds(uint currentTick)
Parameters
currentTickuint
Returns
Remove(ICharacter)
Removes the buff's effects from the target character.
public void Remove(ICharacter target)
Parameters
targetICharacterThe character losing the buff.
RemoveStack(ICharacter)
Removes a stack from the buff and removes stack effects from the target.
public void RemoveStack(ICharacter target)
Parameters
targetICharacterThe character losing the stack.
ResetDuration(uint, float)
Resets the expiry to currentTick + durationTicks, refreshing the buff's lifetime.
public void ResetDuration(uint currentTick, float tickDelta)
Parameters
ResetTickTime(uint, float)
Resets NextTickTick to currentTick + tickRateTicks.
public void ResetTickTime(uint currentTick, float tickDelta)
Parameters
SetCaster(ICharacter)
Snapshots the character responsible for this buff.
public void SetCaster(ICharacter caster)
Parameters
casterICharacterThe character applying the buff, or null if unknown.
Remarks
Called again when an existing buff is re-applied or stacked, so a fresh application re-points attribution at whoever cast it most recently. A null is ignored rather than clearing an existing caster: a re-application from a source that does not know its initiator (a region trigger, a database restore) should not strip credit from one that did.
SetTickDelta(float)
Updates the cached tick-delta used by RemainingSeconds(uint). Called by Tick(uint) every tick so UI duration bars never get stuck reporting 0 when a buff was constructed before TimeManager became available. Ignores non-positive values to preserve the last good delta.
public void SetTickDelta(float tickDelta)
Parameters
tickDeltafloat
TryTick(ICharacter, uint, float, bool, bool)
Tries to trigger a tick for the buff if NextTickTick has been reached, then advances NextTickTick by the template tick-rate in ticks.
public bool TryTick(ICharacter target, uint currentTick, float tickDelta, bool isReplaying = false, bool isAuthoritative = true)
Parameters
targetICharacterThe character affected by the buff.
currentTickuintThe current network tick.
tickDeltafloatFixed seconds-per-tick of the active session.
isReplayingboolTrue when this tick is part of a prediction replay. Exposed to templates via IsReplaying so effects that raise events can suppress them.
isAuthoritativeboolTrue when the caller is the server. Exposed to templates via IsAuthoritative so ECA triggers and other non-idempotent side effects run on the server only. Defaults to true for direct callers; Tick(uint) always passes its own server state explicitly.
Returns
- bool
True if tick state changed (snapshot must be marked dirty).