Dev tool: switch player class (Warrior/Ranger) at runtime for testing
Editor-only class swap via the existing scalar dev-RPC family (new DebugOp.SetClass): F1/F2 keybind (ClassSwitchHotkeySystem), DebugOverlay '- Class -' buttons, and DebugCommandSendSystem.SetWarrior/SetRanger/SetClass statics. Server (DebugCommandReceiveSystem) swaps class in place on the spawned player: strips+re-seeds the ClassTraits StatModifier seeds, swaps the AbilityRef Fire slot, resets the ability cooldown, and heals a LIVING player to the new max (dead players skip the heal so respawn isn't raced). Server-authoritative + prediction-correct (same buffer-mutation path as GrantUpgrade); wire type unchanged so the RpcCollection hash is unaffected. ClassTraits gains a shared Seeds core (spawn + swap can't drift), ClassSeedCount, IsClassSeed, a DynamicBuffer AppendSeeds overload, and Reapply. +3 EditMode tests (exact-count round-trip, value-equality fold, boundary/foreign-mod preservation); 351/351 green; Warrior<->Ranger round-trip Play-validated (server+client agree). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
#if UNITY_EDITOR
|
||||
using Unity.Entities;
|
||||
using Unity.NetCode;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
namespace ProjectM.Client
|
||||
{
|
||||
/// <summary>
|
||||
/// EDITOR-ONLY dev hotkey to switch the local player's class while playtesting: <b>F1 = Warrior</b>,
|
||||
/// <b>F2 = Ranger</b>. The <see cref="DebugOverlay"/>'s Class buttons only live in the DevSandbox scene, so this
|
||||
/// keybind makes the swap reachable in the real menu -> Game flow too (no scene wiring needed). It enqueues the
|
||||
/// SAME authoritative <see cref="ProjectM.Simulation.DebugCommandRequest"/> (DebugOp.SetClass) the overlay buttons
|
||||
/// do, via <see cref="DebugCommandSendSystem"/> — the server strips/re-seeds the class traits, swaps the Fire
|
||||
/// ability, and heals a living player to the new class's max. Reads <see cref="Keyboard"/> directly (no
|
||||
/// .inputactions edit) and edge-detects with wasPressedThisFrame. Stripped from player builds (#if UNITY_EDITOR).
|
||||
/// </summary>
|
||||
[WorldSystemFilter(WorldSystemFilterFlags.ClientSimulation)]
|
||||
public partial class ClassSwitchHotkeySystem : SystemBase
|
||||
{
|
||||
protected override void OnUpdate()
|
||||
{
|
||||
var kb = Keyboard.current;
|
||||
if (kb == null)
|
||||
return;
|
||||
|
||||
if (kb.f1Key.wasPressedThisFrame)
|
||||
DebugCommandSendSystem.SetWarrior();
|
||||
else if (kb.f2Key.wasPressedThisFrame)
|
||||
DebugCommandSendSystem.SetRanger();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d255b172df6aa27499947eba62c8be78
|
||||
@@ -40,6 +40,10 @@ namespace ProjectM.Client
|
||||
public static void SetHeat(int heat) => Send(DebugOp.SetHeat, heat);
|
||||
/// <summary>Set the <see cref="ProjectM.Simulation.TuningKnob"/> knob to value (server-applied, x1000 fixed-point; MC-0).</summary>
|
||||
public static void SetTuning(byte knob, float value) => Send(DebugOp.SetTuning, knob, Mathf.RoundToInt(value * 1000f));
|
||||
/// <summary>Swap the sender's class to <paramref name="classId"/> (a <see cref="ProjectM.Simulation.CharacterId"/> byte); server-authoritative (class-switch dev tool).</summary>
|
||||
public static void SetClass(byte classId) => Send(DebugOp.SetClass, classId);
|
||||
public static void SetWarrior() => SetClass(ClassTraits.WarriorClass);
|
||||
public static void SetRanger() => SetClass(ClassTraits.RangerClass);
|
||||
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
|
||||
static void ResetOnEnterPlayMode() => s_Pending.Clear();
|
||||
|
||||
@@ -65,6 +65,12 @@ namespace ProjectM.Client
|
||||
if (GUILayout.Button("Go Base")) DebugCommandSendSystem.Teleport(RegionId.Base);
|
||||
if (GUILayout.Button("Go Expedition")) DebugCommandSendSystem.Teleport(RegionId.Expedition);
|
||||
GUILayout.EndHorizontal();
|
||||
GUILayout.Space(6);
|
||||
GUILayout.Label("- Class (F1/F2) -");
|
||||
GUILayout.BeginHorizontal();
|
||||
if (GUILayout.Button("Warrior")) DebugCommandSendSystem.SetWarrior();
|
||||
if (GUILayout.Button("Ranger")) DebugCommandSendSystem.SetRanger();
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
GUILayout.Space(6);
|
||||
GUILayout.Label("- Telemetry (MC-0) -");
|
||||
|
||||
Reference in New Issue
Block a user