Slice Combat Depth (MC-3 + wiring + review fixes): Spitter aim-line + player-hit punch, rigged enemies, in-band gate (DR-041)
Completes the Combat Depth slice on top of the MC-2 server spine (56cf60cce):
MC-3 impact juice (client, observe-only):
- 7 FeelConfig fields + ResetDefaults; magnitude-scaled player-dealt-hit camera
PunchFov on the enemy-Health-decrease edge (camera-only hit-stop, never timeScale).
- Spitter Kind==2 aim-LANE telegraph (BuildLaneMesh) — reads baked SpitterState
client-side, falls back to a fixed length. True freeze + material flash deferred.
Content / wiring:
- SpitterProjectilePrefabAuthoring (the SpitterProjectilePrefab singleton).
- Both directors rebuilt to a 4-entry KIND-INDEXED roster [Grunt,Charger,Spitter,
Swarmer] + mix/MaxAlive config + the SpitterProjectileConfig singleton in the subscene.
- Real rigged models: EnemySpitter (re-skinned Kaiju, ranged poker) + EnemySwarmerUndead
(Undead-Werewolf, fast/low-HP); grunt/charger keep Werewolf/ChargerMuscle. EnemySpit =
ownerless interpolated ghost (no Health, no collider).
Post-impl adversarial review fixes (wf_febdcfdb-665):
- [MED] in-band fire gate: the Spitter committed its telegraph from ANY range (fired while
advancing from far). Now commits only when sInBand || sCornered (gives CorneredRange a
real read site) — a Spitter out-of-band holds fire and repositions.
- [LOW] EnemyProjectileDamageSystem early-returns on !ServerTick.IsValid (sibling parity).
- [LOW] EnemyAuthoring bake-time guard: errors if a prefab composes both Charger+Spitter
(would match zero AI passes -> never move).
- [LOW] tests: Spitter brain fires from Expedition (kills the Base==0 region false-green);
a direct partition-exclusion test replaces the order-masked claim; added out-of-band +
cornered negative tests.
388/388 EditMode green + two Play smokes (clean boot, fire, swept-hit, region, server==
client; rigged Kaiju spitter bakes + fires with zero console errors). Accepted as-is
(documented in DR-041): global spit soft-cap, co-op punch attribution.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -432,7 +432,13 @@ namespace ProjectM.Server
|
||||
else
|
||||
{
|
||||
bool sReady = sp.NextShotTick == 0 || !new NetworkTick(sp.NextShotTick).IsNewerThan(serverTick);
|
||||
if (sReady && (sTargetEntity != Entity.Null || sCoreAlive))
|
||||
// In-band gate (DR-041): telegraph + fire ONLY when holding the preferred band, OR when the target has
|
||||
// closed inside CorneredRange (point-blank, no retreat room). While ADVANCING from too far OR
|
||||
// RETREATING from a too-close target it must NOT fire — that IS the hold-range "reposition" question.
|
||||
float sDist = math.length(sToTarget);
|
||||
bool sInBand = math.abs(sDist - sp.PreferredRange) <= sp.RangeTolerance;
|
||||
bool sCornered = sDist <= sp.CorneredRange;
|
||||
if (sReady && (sInBand || sCornered) && (sTargetEntity != Entity.Null || sCoreAlive))
|
||||
{
|
||||
uint wTicks = (uint)math.max(1, sp.WindupTicks);
|
||||
windup.ValueRW.WindUpUntilTick = TickUtil.NonZero(now + wTicks);
|
||||
|
||||
@@ -44,7 +44,9 @@ namespace ProjectM.Server
|
||||
[BurstCompile]
|
||||
public void OnUpdate(ref SystemState state)
|
||||
{
|
||||
uint now = SystemAPI.GetSingleton<NetworkTime>().ServerTick.TickIndexForValidTick;
|
||||
var serverTick = SystemAPI.GetSingleton<NetworkTime>().ServerTick;
|
||||
if (!serverTick.IsValid) return; // mirror WaveSystem/ZoneEnemyDirectorSystem — never stamp SourceTick off an invalid tick
|
||||
uint now = serverTick.TickIndexForValidTick;
|
||||
var ecb = new EntityCommandBuffer(Allocator.Temp);
|
||||
|
||||
// Snapshot valid targets once (stable query order). PLAYERS carry HitRadius (PlayerAuthoring);
|
||||
|
||||
Reference in New Issue
Block a user