using Unity.Entities;
using Unity.Mathematics;
using Unity.NetCode;
namespace ProjectM.Simulation
{
///
/// MC-1 — server-only Charger lunge state (a KnockbackState SHAPE-twin). Component PRESENCE is the Charger
/// discriminator (no enum / brain byte — honours the Burst cross-assembly-enum rule; EnemyAISystem is Bursted):
/// a Husk variant baked with LungeState is driven by the Charger branch, every other Husk by the Grunt branch
/// (which excludes these via .WithNone<LungeState>()). On a wind-up commit the Charger LOCKS
/// toward the target and travels at until — dealing
/// contact damage if it connects, or staggering into a punish window if it whiffs (wall-stop or overshoot).
/// NOT a [GhostField] (the lunged position replicates via the stock LocalTransform variant, like
/// KnockbackState). All ticks via TickUtil.NonZero; compared with only.
///
public struct LungeState : IComponentData
{
/// Fixed planar lunge heading, locked at commit (world XZ -> float2 x,y).
public float2 Dir;
/// Lunge speed (world units/s); only meaningful while is active.
public float Speed;
/// Raw tick the lunge ends (NonZero). 0 = not lunging. Active while .IsNewerThan(serverTick).
public uint UntilTick;
/// Raw tick the whiff-stagger punish window ends (NonZero; set at BOTH whiff sites). 0 = not
/// staggered — or already punished: HealthApplyDamageSystem zeroes it when the first player-sourced hit
/// lands so a window counts ONCE in DevTelemetry.ChargerWhiffPunishesLanded. The attack lockout itself
/// rides EnemyAttackCooldown.NextAttackTick; this field only scores the punish.
public uint StaggerUntilTick;
}
///
/// REPLICATED enableable MID-LUNGE flag on a Charger (Slice 1, Feature D). ENABLED for exactly the ticks a
/// Charger is committed to its locked-direction lunge ( active), DISABLED
/// otherwise. The ONLY replicated Charger surface beyond the stock LocalTransform — a [GhostEnabledBit],
/// NOT a [GhostField], because the client needs only on/off: the lunge HEADING is already carried by the
/// replicated LocalTransform.Rotation (EnemyAISystem writes LookRotationSafe(lungeDir) each lunge tick), so the
/// client indicator derives direction via AnimParamMath.PlanarForward like the danger cone already does. Fixes
/// the cue VANISHING at commit (AttackWindup zeroes on commit, so a windup-gated cone disappears exactly when
/// the danger is realest): this bit STAYS on through the committed travel. Server-derived once per tick from
/// LungeState.UntilTick in EnemyAISystem (the sole LungeState writer); BAKE DISABLED (a Charger spawns
/// not-lunging) + visit via .WithPresent<IsLunging>() to write the bit while disabled (the Dead idiom).
///
[GhostEnabledBit]
public struct IsLunging : IComponentData, IEnableableComponent { }
}