using Unity.Entities; namespace ProjectM.Simulation { /// /// SERVER-ONLY working state for the expedition BOSS (a scaled Charger that 's /// RoomEnemyDirectorSystem tags at spawn). NOT replicated and NOT baked — added at runtime via ECB on the boss /// entity, so it needs no ghost-hash change (a runtime-added replicated component would not replicate anyway; /// this one is deliberately server-only, like /). /// /// Component PRESENCE is the boss discriminator: BossAISystem is the SOLE mover/attacker of /// .WithAll<EnemyTag, BossState>(), and EnemyAISystem's Charger MOVE pass excludes it via /// .WithNone<BossState>() so exactly one system writes the boss's Position/AttackWindup. The boss does /// NOT use LungeState (its signature move is a telegraphed radial SLAM, not a lunge) — so EnemyAISystem's /// IsLunging derive visits it but sees LungeState.UntilTick==0 and derives the bit off (harmless single /// writer). is a byte (never a C# enum on a Bursted path — the cross-assembly-enum ICE rule). /// All tick fields route through TickUtil.NonZero and compare with . /// /// public struct BossState : IComponentData { /// 1 = phase one (heavy Charger + slam), 2 = phase two (<50% HP: faster + summons adds). Byte, not enum. public byte Phase; /// Earliest raw tick the boss may begin its next radial SLAM wind-up (NonZero; 0 = ready). public uint SlamReadyTick; /// Earliest raw tick the boss may summon its next add pack (phase two only; NonZero; 0 = ready). public uint SummonReadyTick; /// Earliest raw tick the boss may begin its next LUNGE wind-up (B4; NonZero; 0 = ready). public uint LungeReadyTick; /// Which attack the live AttackWindup belongs to: 0 = radial slam, 1 = lunge (B4 — slam and lunge /// share the one replicated windup field; this server-only byte disambiguates the elapse branch). The client /// distinguishes via the IsLunging ghost bit instead (BossAISystem holds LungeState.UntilTick through the /// lunge wind-up + travel, so EnemyAISystem's derive turns the bit on). public byte PendingAttack; } }