using Unity.Entities; using Unity.Mathematics; 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; } }