using Unity.Collections; using Unity.Entities; namespace ProjectM.Simulation { /// /// Phase 1.7 per-projectile mechanic-changer state — SERVER-ONLY, NOT a [GhostField] (mirrors /// ): it adds no replicated surface, so the ghost hash /// stays FROZEN (adding fields to the ghost component itself would change its /// StableTypeHash → serializer hash → ghost re-bake; a separate server-only component does not). Baked inert /// on the projectile prefab; seeded server-side at spawn (AbilityFireSystem) from the owner's /// , and read only by ProjectileDamageSystem (also server-only) — the owner's /// predicted projectile needs no local copy (pierce = server delays despawn → client reconciles via ghost /// persistence; chain = server rewrites the replicated ; pull just flips the /// server-stamped ). /// public struct ProjectileEffectState : IComponentData { /// Enemy hits remaining before the projectile despawns (0 = destroy on next hit). public byte PierceRemaining; /// Chain-to-next-target hops remaining after a hit. public byte ChainRemaining; /// bit0 = Pull (stamp knockback TOWARD the shooter instead of away). public byte Flags; /// Targets already hit by this projectile — excluded DURING target selection so a surviving /// (pierced/chained) projectile never re-hits the same enemy across ticks. Overflow ⇒ destroy (natural cap). public FixedList64Bytes Hit; } /// Bit masks for . public static class ProjectileEffectFlag { public const byte Pull = 1; } }