G6+G4: Cone damage-at-contact + zone fill telegraph (ZoneEffect GhostFields) + co-op saturation budget
Cone/SpecialSlam damage lands at its visual contact via ConeContactPending (knob 32, 0=legacy; early-flush + resolve re-validate; death + BOTH class-swap paths drop armed pendings — fixes the shipped melee death-strand in the same stroke). Zones: [GhostField] Caster/Radius/NextTick + ZoneTelegraphSystem (Geyser latch contract on InterpolationTick; rim = true radius; arm grows, persistent phase drains). Cone cues latch to contact (FireStartRaw, C14); TuningConfig.Defaults() fallback at client cue sites (release-build timing fix). G4: SaturationMath ally-FX degrade (living-enemy census, solo-exempt; enemy telegraphs structurally exempt) + CombatStressDebug + overlay saturation rows. Reviews wf_98bf1268 (13 confirmed folded) / wf_9757d214 (5 confirmed fixed). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,32 +1,42 @@
|
||||
using Unity.Entities;
|
||||
using Unity.NetCode;
|
||||
|
||||
namespace ProjectM.Simulation
|
||||
{
|
||||
/// <summary>
|
||||
/// SERVER-ONLY periodic-AoE state on a player-cast zone ghost (Vortex / LightZone) — the LANTERN Aoe/zone
|
||||
/// archetype. NOT a <c>[GhostField]</c>: the zone is a server-spawned INTERPOLATED ownerless ghost whose
|
||||
/// position replicates via the stock LocalTransform variant; only its damage schedule lives here, server-side.
|
||||
/// <c>ZonePulseSystem</c> borrows the <c>GeyserEruptSystem</c> skeleton (the INVERTED invalid-tick guard so a
|
||||
/// born-0 tick never storm-fires + the <c>= now + period</c> reschedule) but is ENEMY-ONLY (no friendly fire),
|
||||
/// stamps <see cref="DamageEvent.SourceNetworkId"/> = <see cref="CasterNetworkId"/> (kills credit the caster,
|
||||
/// feeding KillRewardSystem — NOT the -1 environment convention), and has NO region gate (a no-world gym).
|
||||
/// DestroyEntity when <see cref="ExpireTick"/> elapses.
|
||||
/// Periodic-AoE state on a player-cast zone ghost (Vortex / LightZone) — the LANTERN Aoe/zone archetype.
|
||||
/// The zone is a server-spawned INTERPOLATED ownerless ghost; position replicates via the stock LocalTransform
|
||||
/// variant. 07-21 G6 (design review wf_98bf1268): THREE fields are now <c>[GhostField]</c> so the client can
|
||||
/// draw an HONEST fill telegraph (ZoneTelegraphSystem): <see cref="CasterNetworkId"/> (G3 ownership tint),
|
||||
/// <see cref="Radius"/> (rim = the TRUE folded damage radius) and <see cref="NextTick"/> (fill arrival = the
|
||||
/// damage moment — server mutations propagate to all clients on an ownerless ghost). Damage schedule/amount
|
||||
/// stay server-only. <c>ZonePulseSystem</c> borrows the <c>GeyserEruptSystem</c> skeleton (the INVERTED
|
||||
/// invalid-tick guard so a born-0 tick never storm-fires + the <c>= now + period</c> reschedule) but is
|
||||
/// ENEMY-ONLY (no friendly fire), stamps <see cref="DamageEvent.SourceNetworkId"/> = <see cref="CasterNetworkId"/>
|
||||
/// (kills credit the caster, feeding KillRewardSystem — NOT the -1 environment convention), and has NO region
|
||||
/// gate (a no-world gym). DestroyEntity when <see cref="ExpireTick"/> elapses.
|
||||
/// </summary>
|
||||
public struct ZoneEffect : IComponentData
|
||||
{
|
||||
/// <summary>NetworkId of the casting player (damage/kill attribution).</summary>
|
||||
public int CasterNetworkId;
|
||||
/// <summary>Pulse cadence in ticks — single source for ZonePulseSystem (damage) and ZoneTelegraphSystem
|
||||
/// (the client fill window). Hoisted 07-21 G6 (was ZonePulseSystem.k_PulsePeriodTicks).</summary>
|
||||
public const uint PulsePeriodTicks = 30;
|
||||
|
||||
/// <summary>Planar (XZ) damage radius, world units.</summary>
|
||||
public float Radius;
|
||||
/// <summary>NetworkId of the casting player (damage/kill attribution + the client's mine-vs-ally tint).</summary>
|
||||
[GhostField] public int CasterNetworkId;
|
||||
|
||||
/// <summary>Damage dealt to each living enemy in radius per pulse.</summary>
|
||||
/// <summary>Planar (XZ) damage radius, world units. Replicated so the drawn rim is the TRUE folded radius.</summary>
|
||||
[GhostField(Quantization = 100)] public float Radius;
|
||||
|
||||
/// <summary>Raw next-pulse tick (NonZero). <c>0</c> = unscheduled → lazy-stamped born-correct (GeyserErupt H2
|
||||
/// rule, never storm-fires). Replicated for the client fill: ride the ABSOLUTE tick + a value-latch + a
|
||||
/// was-counting-down arm-guard (the Geyser ★ rule — never edge-detect the re-stamp).</summary>
|
||||
[GhostField] public uint NextTick;
|
||||
|
||||
/// <summary>Damage dealt to each living enemy in radius per pulse. Server-only.</summary>
|
||||
public float DamagePerPulse;
|
||||
|
||||
/// <summary>Raw next-pulse tick (NonZero). <c>0</c> = unscheduled → lazy-stamped born-correct (GeyserErupt H2 rule, never storm-fires).</summary>
|
||||
public uint NextTick;
|
||||
|
||||
/// <summary>Raw tick the zone despawns (NonZero). Active while .IsNewerThan(serverTick).</summary>
|
||||
/// <summary>Raw tick the zone despawns (NonZero). Active while .IsNewerThan(serverTick). Server-only.</summary>
|
||||
public uint ExpireTick;
|
||||
|
||||
/// <summary>See <see cref="ZoneEffectFlag"/>. bit0 = Vortex (also pull enemies toward the zone center each pulse).</summary>
|
||||
|
||||
Reference in New Issue
Block a user