36950ca21d
Aoe/Hitscan archetype dispatch in AbilityFireSystem (both-worlds cooldown; server-only ecb.Instantiate — the client-never-instantiates invariant; ZoneEffect vs DecoyTag chosen by prefab membership). Harpooner REEL as a homing state (ReelState + ReelSystem re-aim the hit Husk's KnockbackState toward the caster's live position each tick; EnemyAISystem stays sole Position writer), stamped by ProjectileDamageSystem on a Reel-flag hit. ZonePulseSystem (enemy-only periodic AoE, caster attribution, no friendly fire, Vortex pull, born-0 lazy-stamp). Decoy aggro in EnemyAISystem + DecoySystem despawn. AbilityDefBlob gains EffectFlags (Reel) + DurationTicks. +3 ZonePulseSystem EditMode tests (497 green). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
38 lines
2.1 KiB
C#
38 lines
2.1 KiB
C#
using Unity.Collections;
|
|
using Unity.Entities;
|
|
|
|
namespace ProjectM.Simulation
|
|
{
|
|
/// <summary>
|
|
/// Phase 1.7 per-projectile mechanic-changer state — SERVER-ONLY, NOT a <c>[GhostField]</c> (mirrors
|
|
/// <see cref="KnockbackState"/>): it adds no replicated surface, so the <see cref="Projectile"/> ghost hash
|
|
/// stays FROZEN (adding fields to the ghost <see cref="Projectile"/> 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 (<c>AbilityFireSystem</c>) from the owner's
|
|
/// <see cref="BoonEffects"/>, and read only by <c>ProjectileDamageSystem</c> (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 <see cref="Projectile.Direction"/>; pull just flips the
|
|
/// server-stamped <see cref="KnockbackState.Dir"/>).
|
|
/// </summary>
|
|
public struct ProjectileEffectState : IComponentData
|
|
{
|
|
/// <summary>Enemy hits remaining before the projectile despawns (0 = destroy on next hit).</summary>
|
|
public byte PierceRemaining;
|
|
/// <summary>Chain-to-next-target hops remaining after a hit.</summary>
|
|
public byte ChainRemaining;
|
|
/// <summary>bit0 = Pull (stamp knockback TOWARD the shooter instead of away).</summary>
|
|
public byte Flags;
|
|
/// <summary>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).</summary>
|
|
public FixedList64Bytes<Entity> Hit;
|
|
}
|
|
|
|
/// <summary>Bit masks for <see cref="ProjectileEffectState.Flags"/>.</summary>
|
|
public static class ProjectileEffectFlag
|
|
{
|
|
/// <summary>bit1 = Reel (HookPull): stamp the homing <see cref="ReelState"/> toward the CASTER instead of a frozen knockback.</summary>
|
|
public const byte Reel = 2;
|
|
public const byte Pull = 1;
|
|
}
|
|
}
|