LANTERN P1 step 2: AbilityFireSystem socket restructure + SpawnId repack

The netcode core of the 4-socket kit (Phase1_Combat_Gym_Build_Spec §1,§2,§5; review NP-1/
RS-1/DB-1/DB-3):
- PlayerInput: +4 Socket0..3 InputEvents + Burst-safe GetSocket(i); legacy Fire kept vestigial.
- PlayerInputGatherSystem: gather sockets from keyboard 1..4 (+gamepad RT/LB/RB); socket 0 also
  fires on the legacy primary (right-click / pad LT) as a bridge.
- AbilityFireSystem: query dropped to 4 type args (PlayerInput/PlayerFacing/LocalTransform/
  GhostOwner) + BufferLookup<AbilitySocket>/ComponentLookup<SocketCooldown>/BufferLookup<
  EffectiveSocketStats> (the 7-arg-cap fix); loops 4 sockets; per-socket cooldown + per-socket
  effective stats; Cone + Projectile dispatch per socket (predict-spawn Projectile-only).
- ProjectileSpawnId.Pack: pure Burst-safe key owner14|socket2|fireCount12|fork4 so same-tick
  multi-socket projectiles never collide; AbilityFireSystem uses it.
L1 clean; L2 494/494 (+5 ProjectileSpawnId tests: distinct-per-socket, fork, owner, bit-ranges,
count-wrap). L3 two-player + rollback is the group-A gate (after step 2.5). Note: the client
feel layer (muzzle/anim) still reads the legacy cooldown until step 2.5; sockets bake empty
until content (step 4), so nothing fires in-game yet.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-14 10:59:45 -07:00
parent b143eb6bb5
commit 12f86c86de
7 changed files with 290 additions and 181 deletions
@@ -81,6 +81,12 @@ namespace ProjectM.Client
// MC-4 offense rebind: melee combo = PRIMARY (left-click / pad West); ranged projectile demoted to right-click / pad left-trigger. Both suppressed while placing a build (like dash/old fire).
bool attackPressed = ((mouse != null && mouse.leftButton.wasPressedThisFrame) || (gamepad != null && gamepad.buttonWest.wasPressedThisFrame)) && !BuildPaletteState.Active;
bool firePressed = ((mouse != null && mouse.rightButton.wasPressedThisFrame) || (gamepad != null && gamepad.leftTrigger.wasPressedThisFrame)) && !BuildPaletteState.Active;
// LANTERN 4-socket kit bindings: keyboard 1..4 (+ gamepad RT/LB/RB); socket 0 also fires on the
// legacy primary (right-click / pad LT). Suppressed while placing a build.
bool socket0Pressed = firePressed || ((keyboard != null && keyboard.digit1Key.wasPressedThisFrame) && !BuildPaletteState.Active);
bool socket1Pressed = ((keyboard != null && keyboard.digit2Key.wasPressedThisFrame) || (gamepad != null && gamepad.rightTrigger.wasPressedThisFrame)) && !BuildPaletteState.Active;
bool socket2Pressed = ((keyboard != null && keyboard.digit3Key.wasPressedThisFrame) || (gamepad != null && gamepad.leftShoulder.wasPressedThisFrame)) && !BuildPaletteState.Active;
bool socket3Pressed = ((keyboard != null && keyboard.digit4Key.wasPressedThisFrame) || (gamepad != null && gamepad.rightShoulder.wasPressedThisFrame)) && !BuildPaletteState.Active;
float2 rightStick = float2.zero;
bool gamepadActive = false;
@@ -170,6 +176,11 @@ namespace ProjectM.Client
input.ValueRW.Attack = default;
if (attackPressed)
input.ValueRW.Attack.Set();
// LANTERN 4-socket kit: reset then raise each socket's fire event on the press edge.
input.ValueRW.Socket0 = default; if (socket0Pressed) input.ValueRW.Socket0.Set();
input.ValueRW.Socket1 = default; if (socket1Pressed) input.ValueRW.Socket1.Set();
input.ValueRW.Socket2 = default; if (socket2Pressed) input.ValueRW.Socket2.Set();
input.ValueRW.Socket3 = default; if (socket3Pressed) input.ValueRW.Socket3.Set();
}
}