Table of Contents

Class ClientCastNameplateDisplay

Namespace
FishMMO.Client
Assembly
FishMMO.Client.dll

Shows what an observed character is casting on its nameplate.

public sealed class ClientCastNameplateDisplay
Inheritance
ClientCastNameplateDisplay
Inherited Members

Remarks

Why observers needed this. The only thing that reached an observer about another character's activation was the spawned ability object, so a self-buff, a pet summon or any consumable happened in complete silence: a character stood still, a bar somewhere changed, and nothing on screen connected the two. CharacterCastBroadcast is sent from the activation state machine, so it covers every activation whether or not anything spawns.

Not for the owner. The server excludes the owner from the broadcast, and this ignores the local character if one ever arrives: the owner's own cast is predicted and already drawn by its cast bar, which is ahead of anything the server can say. Drawing a second, later version of it on the owner's own nameplate is exactly the desync the message is meant to avoid.

Fields

ExpiryGraceSeconds

Extra time past a cast's own duration before it is dropped without a stop message.

public const float ExpiryGraceSeconds = 1.5

Field Value

float

Remarks

Not a loss allowance. The stop rides Channel.Reliable, and that is a correctness requirement rather than a comfort: the receiver keys a stop on the caster, so an unreliable stop from cast N reordering behind the start of cast N+1 clears the wrong row — reachable at instant-attack cadence, and pinned by CastVisibilityTests.TheCastMessageIsReliableAndAStopNamesWhatItEnds. (This used to say the stop was unreliable and could be lost; it cannot.)

What the grace is for is a stop that never EXISTS: a caster that disconnects or is despawned mid-cast, and a cast that finishes slower than this peer computed because a speed debuff landed on the caster after the row was opened. Without it such a plate would read "Casting" until that character left view.

MinimumDwellSeconds

The shortest time a cast stays on a nameplate.

public const float MinimumDwellSeconds = 0.6

Field Value

float

Remarks

An instant ability starts and ends inside one tick, so start and stop arrive together and a plate written and cleared in the same frame shows nothing at all. Holding the row briefly is what makes an instant cast readable as an event.

Methods

Clear()

Drops every row without unregistering. For a world change, where the network manager survives but every object id in FishMMO.Client.ClientCastNameplateDisplay.active is about to mean something else.

public void Clear()

Initialize(NetworkManager)

Registers the broadcast handler.

public void Initialize(NetworkManager networkManager)

Parameters

networkManager NetworkManager

The client's network manager.

ResolveExpiry(float, float, bool, float, float)

When a row is dropped if no stop message ever arrives for it.

public static float ResolveExpiry(float now, float duration, bool durationKnown, float remaining, float heldAllowance)

Parameters

now float

Unscaled time the row is being opened at.

duration float

The activation's computed duration in seconds.

durationKnown bool

False when the ability could not be resolved at all.

remaining float

Seconds of the activation still to run, which may be negative.

heldAllowance float

Extra seconds a held activation may legitimately run for.

Returns

float

The unscaled time to drop the row at.

Remarks

A zero-duration cast expires on the DWELL, not on the grace. The server no longer sends a stop for an activation that began and ended on one server tick (see AbilityController.SuppressesRedundantCastStop) — 17 of the 37 authored abilities are instant, the default attack among them — so for those this is the only thing that ever clears the row. Sizing it from ExpiryGraceSeconds would leave "Casting Punch" on a plate for 1.5 s per swing, which at auto-attack cadence never comes off at all. MinimumDwellSeconds is the row's whole intended life: long enough to read an instant cast as an event, short enough not to be believed as an ongoing one.

Only when the duration is actually KNOWN to be zero. An ability this peer cannot resolve — one learned after it started observing, or an NPC's set it never received — also reports zero, and that one may well be a five second cast whose stop is coming. Those keep the grace, which is why ResolveDuration(CharacterCastBroadcast, AbilityController, out bool) reports whether it resolved anything rather than leaving the caller to read zero two ways.

A HELD ability keeps the grace too, zero-duration or not: it has a hold allowance, it runs past its window for as long as the player holds it, and the server always sends its stop.

Shutdown()

Unregisters and clears every row this display wrote.

public void Shutdown()

Tick()

Clears rows whose cast has ended or timed out. Call once per frame.

public void Tick()