using Unity.Entities;
namespace ProjectM.Simulation
{
///
/// Slice 2 — pure mapping from a chosen class (a byte) to its spawn-time setup: the
/// Fire-slot ability id + the permanent trait s (tagged with the reserved
/// , NEVER stripped). Applied by GoInGameServerSystem on the just-spawned
/// player and unit-tested. Burst-safe (byte-only, no managed types).
///
/// Trait deltas seed onto the character (no per-class blob row needed — the
/// deltas ride the replicated StatModifier buffer, OwnerSendType.All, so the owning client folds the correct
/// EffectiveCharacterStats). The DRG-asymmetry (operator-locked): Warrior = melee bruiser (tankier,
/// slower, harder + longer-reach melee via MeleeDamage/MeleeRange); Ranger = ranged anchor (faster,
/// squishier, longer projectile range + a wider auto-target assist — the co-op synergy hook the Warrior's
/// knockback feeds). The Warrior's Fire = the aim-directed cone (); the
/// Ranger's Fire = the default projectile ().
///
///
public static class ClassTraits
{
public const byte WarriorClass = (byte)CharacterId.Warrior;
public const byte RangerClass = (byte)CharacterId.Ranger;
/// Normalize a wire ClassId to a known class (0 / unknown -> Warrior).
public static byte Normalize(byte classId) => classId == RangerClass ? RangerClass : WarriorClass;
/// The Fire-slot ability id for a class (Warrior = cone, Ranger = the default projectile).
public static byte AbilityFor(byte classId)
=> classId == RangerClass ? (byte)AbilityId.Primary : (byte)AbilityId.WarriorCone;
/// Append a class's permanent trait modifiers onto a player's StatModifier buffer (via ECB at spawn).
public static void AppendSeeds(byte classId, Entity player, EntityCommandBuffer ecb)
{
uint src = Tuning.ClassSourceId;
if (classId == RangerClass)
{
ecb.AppendToBuffer(player, new StatModifier { Target = (byte)StatTarget.MoveSpeed, Op = (byte)ModOp.PercentMult, Value = 0.15f, SourceId = src });
ecb.AppendToBuffer(player, new StatModifier { Target = (byte)StatTarget.MaxHealth, Op = (byte)ModOp.PercentMult, Value = -0.15f, SourceId = src + 1u });
ecb.AppendToBuffer(player, new StatModifier { Target = (byte)StatTarget.Range, Op = (byte)ModOp.PercentAdd, Value = 0.30f, SourceId = src + 2u });
ecb.AppendToBuffer(player, new StatModifier { Target = (byte)StatTarget.AutoTargetRange, Op = (byte)ModOp.Flat, Value = 3f, SourceId = src + 3u });
}
else
{
ecb.AppendToBuffer(player, new StatModifier { Target = (byte)StatTarget.MaxHealth, Op = (byte)ModOp.Flat, Value = 30f, SourceId = src });
ecb.AppendToBuffer(player, new StatModifier { Target = (byte)StatTarget.MoveSpeed, Op = (byte)ModOp.PercentMult, Value = -0.15f, SourceId = src + 1u });
ecb.AppendToBuffer(player, new StatModifier { Target = (byte)StatTarget.MeleeDamage, Op = (byte)ModOp.Flat, Value = 6f, SourceId = src + 2u });
ecb.AppendToBuffer(player, new StatModifier { Target = (byte)StatTarget.MeleeRange, Op = (byte)ModOp.Flat, Value = 0.8f, SourceId = src + 3u });
}
}
}
}