LANTERN purge B6: delete the legacy single-ability path (sockets are THE ability model)
AbilityRef, AbilityCooldown, EffectiveAbilityStats, DefaultAbility deleted. GoInGameServerSystem seeds the per-frame 4-socket Spark loadout UNCONDITIONALLY (was gym-only); ClassSelectReceiveSystem + DebugOp.SetClass swap FrameId + re-seed sockets + zero SocketCooldown; ClassSwapUtil.Apply drops newAbilityId; EquipSystem weapons become stat-sticks (GrantedAbilityId removed from the item blob/authoring); StatRecomputeSystem folds CharacterStatsRef + sockets only; HUD cooldown bar reads socket 0 of SocketCooldown/EffectiveSocketStats; class HUD readers are FrameId-only (ClassForAbility/AbilityFor deleted); DebugModifierInjectionSystem drops CycleAbility. 390 tests green; Play-verified: a non-gym spawn gets frame=2 with Sparks [7,8,6,9] and no console errors. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -6,12 +6,13 @@ using Unity.NetCode;
|
||||
namespace ProjectM.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// Server receiver for <see cref="ClassSelectRequest"/> — the player picks their class at base. Honored ONLY in
|
||||
/// Staging (class = a between-runs choice; mid-run it would desync the fight). Resolves sender → player (the
|
||||
/// Server receiver for <see cref="ClassSelectRequest"/> — the player picks their frame at base. Honored ONLY in
|
||||
/// Staging (frame = a between-runs choice; mid-run it would desync the fight). Resolves sender → player (the
|
||||
/// MetaSpend/ReadyToggle idiom), then applies the FULL in-place swap via <see cref="ClassSwapUtil"/> (class seeds +
|
||||
/// permanent-meta re-sync) and writes AbilityRef / PlayerClass / AbilityCooldown + <see cref="ClassSwapUtil.HealClamp"/>.
|
||||
/// Plain server group, before RunDirectorSystem (the receiver convention); requests are ALWAYS destroyed. NOT
|
||||
/// Burst-compiled (a cross-assembly blob+buffer helper on a low-frequency RPC — Burst safety over micro-perf).
|
||||
/// permanent-meta re-sync), writes FrameId / PlayerClass, re-seeds the 4-socket Spark loadout, and calls
|
||||
/// <see cref="ClassSwapUtil.HealClamp"/>. Plain server group, before RunDirectorSystem (the receiver convention);
|
||||
/// requests are ALWAYS destroyed. NOT Burst-compiled (a cross-assembly blob+buffer helper on a low-frequency RPC).
|
||||
/// </summary>
|
||||
/// </summary>
|
||||
[WorldSystemFilter(WorldSystemFilterFlags.ServerSimulation)]
|
||||
[UpdateInGroup(typeof(SimulationSystemGroup))]
|
||||
@@ -50,18 +51,26 @@ namespace ProjectM.Server
|
||||
var conn = receive.ValueRO.SourceConnection;
|
||||
if (!PlayerResolve.TryResolve(ref state, playerByConn, conn, out var player))
|
||||
continue;
|
||||
if (!SystemAPI.HasComponent<AbilityRef>(player)) continue;
|
||||
if (!SystemAPI.HasBuffer<AbilitySocket>(player)) continue;
|
||||
|
||||
var mods = SystemAPI.GetBuffer<StatModifier>(player);
|
||||
var metaRecord = haveMeta ? SystemAPI.GetBuffer<MetaTierState>(dir) : default;
|
||||
ClassSwapUtil.Apply(req.ValueRO.ClassId, mods, haveMeta, metaCat, metaRecord,
|
||||
out byte newClass, out byte newAbilityId);
|
||||
ClassSwapUtil.Apply(req.ValueRO.ClassId, mods, haveMeta, metaCat, metaRecord, out byte newClass);
|
||||
|
||||
SystemAPI.SetComponent(player, new AbilityRef { Id = newAbilityId });
|
||||
if (SystemAPI.HasComponent<FrameId>(player))
|
||||
SystemAPI.SetComponent(player, new FrameId { Value = newClass });
|
||||
if (SystemAPI.HasComponent<PlayerClass>(player))
|
||||
SystemAPI.SetComponent(player, new PlayerClass { ClassId = newClass });
|
||||
if (SystemAPI.HasComponent<AbilityCooldown>(player))
|
||||
SystemAPI.SetComponent(player, new AbilityCooldown { NextFireTick = 0 }); // swapped ability fires now
|
||||
// Re-seed the 4-socket Spark loadout for the new frame + clear its cooldowns (fires now).
|
||||
ClassTraits.FrameLoadout(newClass, out byte f0, out byte f1, out byte f2, out byte f3);
|
||||
var sockets = SystemAPI.GetBuffer<AbilitySocket>(player);
|
||||
sockets.Clear();
|
||||
sockets.Add(new AbilitySocket { SparkId = f0 });
|
||||
sockets.Add(new AbilitySocket { SparkId = f1 });
|
||||
sockets.Add(new AbilitySocket { SparkId = f2 });
|
||||
sockets.Add(new AbilitySocket { SparkId = f3 });
|
||||
if (SystemAPI.HasComponent<SocketCooldown>(player))
|
||||
SystemAPI.SetComponent(player, default(SocketCooldown)); // 0 = ready: the swapped kit fires now
|
||||
if (haveDb && SystemAPI.HasComponent<Health>(player) && SystemAPI.HasComponent<CharacterStatsRef>(player))
|
||||
{
|
||||
byte charId = SystemAPI.GetComponent<CharacterStatsRef>(player).Id;
|
||||
|
||||
Reference in New Issue
Block a user