Keep state layers separate

LayerUseful forDoes not establish
Entity/component propertyReported state within its network visibility and entity lifetimeA complete roster-wide history.
Controller cacheCurrent GUI projection and recoveryFresh entity truth after every rebuild.
Transition eventThe producer-defined change boundaryEvery changed field or a unique historical action.
Observation/tickCurrent snapshot and time-derived displayA newly received server packet.
Marker, ribbon or soundPresentation and user feedbackExactly one hit, kill or action per visual cue.

Health and death have several owners

Raw vehicle health, HUD health, crew activity and arena death attribution are distinct. The player health path clamps HUD health to zero, but retains separate crew/liveness and first-update state. Positive HP with inactive crew can enter postmortem. Repeated dead health can refresh the HUD without repeating the death transition; changed respawn availability can refresh postmortem without another destruction notification.

The arena kill publication uses the already-updated roster death record and its battle entity IDs, reason and other attribution fields. It does not derive the killer from an entity health delta or require a live victim entity. Repeated publication is not deduplicated by that method. A recovery reason can publish through the same kill-named event, so a journal must preserve reason and per-life policy.

Entity death presentation has different gates and no attacker argument. Starting visuals for an already-dead entity can run it again; inactive crew can also reach it while HP remains positive. Cleanup calls, postmortem refreshes and display reconstruction must not each increment a kill/death ledger.

Borrowed health caches and rebuilds

The battlefield controller's health getter returns a tuple for an allied entry but its stored list for an enemy entry. Copy retained values before deferred comparison; mutating borrowed enemy state bypasses sum/notification maintenance. Dead-ID event payloads can likewise expose controller-owned sets rather than historical snapshots.

Attaching view components and arena invalidation can rebuild the health cache from roster maximums. For example, a cached 350/1000 entry can return to 1000/1000 while separate spotted state remains set; that is reconstruction, not a healing event. A previously borrowed enemy list becomes detached from the replacement dictionary, so reacquire state after the owner rebuilds.

Zero HP updates sums but does not itself perform every alive/dead-cache transition. Death status removes the alive entry and resets enemy spotted status; a later health-only update does not recreate it. Preserve cache generation, last observation and independent spotting state instead of reducing them to one boolean.

Feedback routing is contextual

Avatar feedback forwarding is gated by observer status or the currently controlled vehicle matching the player vehicle. Component forwarding through OwnVehicle still reaches that gate. Individual records then have different routes: an enemy kill can enter the general player batch, while target visibility activates a trigger and detection publishes a separate event. The inspected missing-target marker queue is not a withheld-damage backlog.

Absence from one consumer does not prove server suppression, absence of damage or later replay of missed records. Keep control/observer identity and the original channel with observations. Likewise, sounds and ribbons can coalesce, repeat, expire or appear during reconstruction; their counts are not a universal event ledger.

Mechanic preparation, transition, observation and ticks

MechanicStatesEvents prepares one retained state, uses the new state's transition predicate, then stores/publishes observations. Transition publication occurs before retained-state replacement; observation occurs afterward. Use event arguments instead of assuming all owner getters have advanced together.

Nested updates are not serialized. For example, if an A→B transition listener initiates C, both transitions can see A as previous; C is observed before the outer update resumes and stores B. A nested write need not remain the final state. Defer dependent work when reentrancy would corrupt the feature.

Late subscription replays current prepared/observation state before registration. That initializes a consumer; it is not a new mechanic activation or historical transition replay. Direct late callbacks can also propagate exceptions outside ordinary safe-event dispatch. Tick events republish the retained state, whose clock-reading properties can change without a new object.

Time, eligibility and object validity

A deadline, a remaining-duration snapshot and elapsed display progress are different contracts. For example, replicated stun state is a server-time deadline; the derived getter refreshes a client record and can return negative remaining time after expiry without clearing the property. Retained records do not advance themselves. Marker timers and status timers can consume different projections from that same source.

Equipment stage, stock, activation eligibility and command acceptance must remain separate. A retained refill item can remain valid-looking after its controller clears ownership; a delayed sound can still run after a later ready update. Drop retained objects on controller/vehicle reset and reacquire them from the current layout.

For a recovering HUD, seed current state, subscribe to its owner and treat later observations as state updates. Maintain history separately. See event publication details, timer ownership, data pipelines and result reconciliation.