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:
@@ -35,12 +35,22 @@ namespace ProjectM.Simulation
|
||||
public static bool FireActive(uint nextFireRaw, int cooldownTicks, NetworkTick serverTick, uint animTicks)
|
||||
{
|
||||
if (nextFireRaw == 0u || cooldownTicks <= 0 || !serverTick.IsValid) return false;
|
||||
uint startRaw = TickUtil.NonZero(nextFireRaw - (uint)cooldownTicks);
|
||||
uint startRaw = FireStartRaw(nextFireRaw, cooldownTicks);
|
||||
var start = new NetworkTick(startRaw);
|
||||
var end = new NetworkTick(TickUtil.NonZero(startRaw + animTicks));
|
||||
return start.IsValid && end.IsValid && !start.IsNewerThan(serverTick) && end.IsNewerThan(serverTick);
|
||||
}
|
||||
|
||||
/// <summary>Reconstructed fire-window START (raw NonZero tick) from the replicated per-socket cooldown
|
||||
/// stamp minus the locally-derived CooldownTicks; 0 = no window (unstamped / degenerate inputs). The ONE
|
||||
/// home of this reconstruction (07-21 G6 review wf_98bf1268: the cone connect-cue latches
|
||||
/// contact = FireStartRaw + ConeContactTicks at the fire edge — never re-derive it inline).</summary>
|
||||
public static uint FireStartRaw(uint nextFireRaw, int cooldownTicks)
|
||||
{
|
||||
if (nextFireRaw == 0u || cooldownTicks <= 0) return 0u;
|
||||
return TickUtil.NonZero(nextFireRaw - (uint)cooldownTicks);
|
||||
}
|
||||
|
||||
/// <summary>LANTERN 4-socket fire/cone resolution (any-socket model): firing if ANY socketed,
|
||||
/// NON-Movement Spark's per-socket window is mid-fire; cone if any such active socket holds a
|
||||
/// Cone-archetype Spark. Movement sockets are skipped OUTRIGHT (blink = dodge, not cast). Without a
|
||||
|
||||
Reference in New Issue
Block a user