Initial Combat Implementation
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
#if UNITY_EDITOR
|
||||
using System.Collections.Generic;
|
||||
using ProjectM.Simulation;
|
||||
using Unity.Entities;
|
||||
using Unity.NetCode;
|
||||
|
||||
namespace ProjectM.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// Editor-only debug hook (mirrors ProjectM.Client.DebugInputInjectionSystem's static-poke pattern)
|
||||
/// for driving the server-authoritative modifier stack from MCP execute_code. Because modifiers are
|
||||
/// server-authoritative, a client-side append would be stomped by the next snapshot, so this runs in
|
||||
/// the SERVER world: the change flows back through the snapshot and is prediction-correct on the
|
||||
/// client. In-editor single-process only (client + server worlds in one process). Poke from execute_code:
|
||||
/// DebugModifierInjectionSystem.AddModifier((byte)StatTarget.Damage, (byte)ModOp.Flat, 50f);
|
||||
/// DebugModifierInjectionSystem.AddModifier((byte)StatTarget.MoveSpeed, (byte)ModOp.PercentAdd, 0.5f);
|
||||
/// DebugModifierInjectionSystem.CycleAbility(); // Primary -> FastLight -> SlowHeavy -> Primary
|
||||
/// DebugModifierInjectionSystem.ClearModifiers();
|
||||
/// All applied to the first player on the next server tick.
|
||||
/// </summary>
|
||||
[WorldSystemFilter(WorldSystemFilterFlags.ServerSimulation)]
|
||||
public partial class DebugModifierInjectionSystem : SystemBase
|
||||
{
|
||||
struct PendingModifier { public byte Target; public byte Op; public float Value; }
|
||||
|
||||
static readonly List<PendingModifier> s_Pending = new List<PendingModifier>();
|
||||
static bool s_Clear;
|
||||
static bool s_Cycle;
|
||||
|
||||
/// <summary>Queue a modifier to append to the first player on the next server tick.</summary>
|
||||
public static void AddModifier(byte target, byte op, float value)
|
||||
{
|
||||
s_Pending.Add(new PendingModifier { Target = target, Op = op, Value = value });
|
||||
}
|
||||
|
||||
/// <summary>Clear the first player's whole modifier stack on the next server tick.</summary>
|
||||
public static void ClearModifiers() => s_Clear = true;
|
||||
|
||||
/// <summary>Cycle the first player's primary ability id on the next server tick.</summary>
|
||||
public static void CycleAbility() => s_Cycle = true;
|
||||
|
||||
protected override void OnUpdate()
|
||||
{
|
||||
if (s_Pending.Count == 0 && !s_Clear && !s_Cycle)
|
||||
return;
|
||||
|
||||
Entity player = Entity.Null;
|
||||
foreach (var (abilityRef, e) in
|
||||
SystemAPI.Query<RefRO<AbilityRef>>().WithAll<PlayerTag, StatModifier>().WithEntityAccess())
|
||||
{
|
||||
player = e;
|
||||
break;
|
||||
}
|
||||
if (player == Entity.Null)
|
||||
return;
|
||||
|
||||
if (s_Clear)
|
||||
{
|
||||
EntityManager.GetBuffer<StatModifier>(player).Clear();
|
||||
s_Clear = false;
|
||||
}
|
||||
|
||||
if (s_Pending.Count > 0)
|
||||
{
|
||||
var buffer = EntityManager.GetBuffer<StatModifier>(player);
|
||||
for (int i = 0; i < s_Pending.Count; i++)
|
||||
{
|
||||
var m = s_Pending[i];
|
||||
buffer.Add(new StatModifier { Target = m.Target, Op = m.Op, Value = m.Value, SourceId = 0u });
|
||||
}
|
||||
s_Pending.Clear();
|
||||
}
|
||||
|
||||
if (s_Cycle)
|
||||
{
|
||||
var abilityRef = EntityManager.GetComponentData<AbilityRef>(player);
|
||||
abilityRef.Id = abilityRef.Id switch
|
||||
{
|
||||
(byte)AbilityId.Primary => (byte)AbilityId.FastLight,
|
||||
(byte)AbilityId.FastLight => (byte)AbilityId.SlowHeavy,
|
||||
_ => (byte)AbilityId.Primary,
|
||||
};
|
||||
EntityManager.SetComponentData(player, abilityRef);
|
||||
s_Cycle = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user