Enum renamed in StatIds.cs (byte values unchanged - serialized definitions/saves
never re-mean); all call sites + doc mentions swept (ClassTraits, PlayerAuthoring,
CharacterStatsDefinition field type, menu/UI, tests). CharacterStatsDefinition SO
CLASS name kept (asset-binding risk; deferred per plan). 390 green.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
FrameId (replicated frame/class signal) now WRITTEN server-side at spawn for all
players; the two class-HUD readers (ClassPrepPortal, MetaShop) read FrameId (with
an AbilityRef fallback for pre-FrameId players) instead of ClassForAbility. The
gym seeds a PER-FRAME default Spark loadout via ClassTraits.FrameLoadout —
Harpooner (Ranger slot): reel/mobility/skillshots; Bathynaut (Warrior slot):
pull-in/dash/zone-control. FrameId uses ecb.AddComponent (baked on the real
player; absent on the minimal MetaSeeding test prefab). 497 EditMode green.
Deferred to a focused pass (risky wholesale refactor, "still works" via the
transition): full removal of legacy AbilityRef/AbilityCooldown/EffectiveAbility
Stats (woven through equip/class/meta/StatRecompute + tests) and the CharacterId
Bathynaut/Harpooner rename.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
GymTag + GymEnemyRoster (+ GymRosterAuthoring) bake the gym singletons. New
DebugOp.SpawnEnemy (client SpawnEnemy wrapper + server receive case) spawns a
chosen enemy KIND (Drowner/Grindylow) from the baked roster near the sender —
replacing the wave-roster hack per the roadmap's Enemy-test GYM direction.
GoInGameServerSystem takes a GymTag branch: bypass the meta-catalog spawn guard
(a fresh gym has no CycleDirector) + seed a default Spark loadout on keys 1-4.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- New Server/PlayerResolve.TryResolve single-sources the RPC
SourceConnection -> NetworkId -> conn->player map resolve (3 sites:
ClassSelectReceive, PrepPurchase, DebugCommandReceive); EntityManager
reads keep it source-gen-safe from Bursted receivers.
- ecb.Dispose() after Playback in 9 Temp-ECB systems (explicit-lifetime
hygiene).
- The TuningConfig.GetOrDefault(ref state) variant of this tail was
REVERTED: state.GetEntityQuery in OnUpdate trips the Entities
"creates a query during OnUpdate" diagnostic per system per world
(caught in Play smoke) - the SystemAPI.TryGetSingleton idiom is
already source-gen-optimal, confirming the original B4 deferral.
Verified: 466/466 EditMode green on the final tree, console clean,
Play smoke 0 errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The per-player class travels on GoInGameRequest.ClassId (client reads a ClassSelection
singleton); GoInGameServerSystem seeds the class at spawn via ClassTraits (AbilityRef +
permanent trait StatModifiers on a reserved ClassSourceId; CharacterStatsRef stays Default
so the DRG-asymmetry deltas ride the replicated OwnerSendType.All buffer). AbilityFireSystem
gains the aim-directed Cone archetype: cooldown predicted both worlds, server-only cone
damage to living enemies (same-tick, SourceTick-stamped, like the melee cleave). 345/345.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>