Vault Re-Alignment
This commit is contained in:
@@ -52,14 +52,18 @@ namespace ProjectM.Client
|
||||
ParticleSystem _hitFx;
|
||||
ParticleSystem _deathFx;
|
||||
ParticleSystem _muzzleFx;
|
||||
ParticleSystem _dashFx;
|
||||
AudioClip _hitClip;
|
||||
AudioClip _deathClip;
|
||||
AudioClip _fireClip;
|
||||
AudioClip _telegraphClip;
|
||||
AudioClip _dashClip;
|
||||
|
||||
Entity _localPlayer = Entity.Null;
|
||||
uint _lastLocalFireTick;
|
||||
bool _fireTickInit;
|
||||
uint _lastLocalDashTick;
|
||||
bool _dashTickInit;
|
||||
|
||||
const int NumberPoolSize = 32;
|
||||
const int MaxActiveVfx = 40; // bound one-shot VFX GameObject churn under sustained combat
|
||||
@@ -72,6 +76,7 @@ namespace ProjectM.Client
|
||||
_deathClip = MakeClip("husk_death", 320f, 50f, 0.34f, 0.55f, noise: false);
|
||||
_fireClip = MakeClip("fire", 880f, 1500f, 0.07f, 0.30f, noise: false);
|
||||
_telegraphClip = MakeClip("telegraph", 680f, 1020f, 0.12f, 0.35f, noise: false);
|
||||
_dashClip = MakeClip("dash", 950f, 240f, 0.12f, 0.50f, noise: false);
|
||||
}
|
||||
|
||||
protected override void OnStartRunning()
|
||||
@@ -83,6 +88,7 @@ namespace ProjectM.Client
|
||||
_hitFx = MakeBurst("HitSparks", mat, new Color(3f, 2.2f, 0.6f), 0.13f, 7f, 0.32f, 256);
|
||||
_deathFx = MakeBurst("DeathBurst", mat, new Color(3.2f, 0.7f, 0.25f), 0.22f, 9f, 0.55f, 512);
|
||||
_muzzleFx = MakeBurst("Muzzle", mat, new Color(0.6f, 2.4f, 3.2f), 0.12f, 5f, 0.20f, 128);
|
||||
_dashFx = MakeBurst("DashWhoosh", mat, new Color(0.7f, 2.6f, 3.0f), 0.16f, 4f, 0.30f, 256);
|
||||
|
||||
for (int i = 0; i < NumberPoolSize; i++)
|
||||
_numbers.Add(CreateNumber());
|
||||
@@ -104,6 +110,8 @@ namespace ProjectM.Client
|
||||
EntityManager.CompleteDependencyBeforeRO<Health>();
|
||||
EntityManager.CompleteDependencyBeforeRO<LocalTransform>();
|
||||
EntityManager.CompleteDependencyBeforeRO<AttackWindup>();
|
||||
EntityManager.CompleteDependencyBeforeRO<DashState>();
|
||||
EntityManager.CompleteDependencyBeforeRO<DashCooldown>();
|
||||
|
||||
// Resolve the local player (for hit colouring + fire feedback).
|
||||
_localPlayer = Entity.Null;
|
||||
@@ -115,6 +123,17 @@ namespace ProjectM.Client
|
||||
localPos = xf.ValueRO.Position;
|
||||
}
|
||||
|
||||
// Client-derived dash window of the LOCAL player (DashSystem runs in the client prediction loop
|
||||
// too): drives the i-frame shimmer + the hit-feedback suppression below. Observe-only.
|
||||
bool localIFrameActive = false;
|
||||
if (_localPlayer != Entity.Null && EntityManager.HasComponent<DashState>(_localPlayer)
|
||||
&& SystemAPI.TryGetSingleton<NetworkTime>(out var dashNetTime) && dashNetTime.ServerTick.IsValid)
|
||||
{
|
||||
var localDash = EntityManager.GetComponentData<DashState>(_localPlayer);
|
||||
localIFrameActive = localDash.IFrameUntilTick != 0u
|
||||
&& new NetworkTick(localDash.IFrameUntilTick).IsNewerThan(dashNetTime.ServerTick);
|
||||
}
|
||||
|
||||
// Edge-detect Health on every damageable ghost (players + Husks).
|
||||
_seen.Clear();
|
||||
foreach (var (health, xf, entity) in
|
||||
@@ -136,7 +155,9 @@ namespace ProjectM.Client
|
||||
PlayClip(_telegraphClip, (Vector3)p, 0.5f);
|
||||
}
|
||||
|
||||
if (cur < prev.Hp - 0.001f)
|
||||
// Local hit feedback is SUPPRESSED while the local i-frame window is active: the server
|
||||
// negates the hit; any transient Health dip is reconciliation flicker, not a real hit.
|
||||
if (cur < prev.Hp - 0.001f && !(isLocalPlayer && localIFrameActive && FeelConfig.DashHitSuppress))
|
||||
{
|
||||
SpawnNumber(prev.Hp - cur, (Vector3)p, isLocalPlayer, cam);
|
||||
Burst(_hitFx, cfg != null ? cfg.Hit : null, (Vector3)p + Vector3.up * 0.8f, FeelConfig.HitBurstCount);
|
||||
@@ -201,6 +222,26 @@ namespace ProjectM.Client
|
||||
_fireTickInit = true;
|
||||
}
|
||||
|
||||
// Local-player dash feedback (MC-1): DashCooldown.NextTick advances exactly once per dash
|
||||
// (replicated [GhostField], predicted both sides; raw uint edge like the muzzle flash — cosmetic
|
||||
// only). Whoosh + afterimage burst + camera punch on start, shimmer trail while i-frames last.
|
||||
if (_localPlayer != Entity.Null && EntityManager.HasComponent<DashCooldown>(_localPlayer))
|
||||
{
|
||||
uint nextDash = EntityManager.GetComponentData<DashCooldown>(_localPlayer).NextTick;
|
||||
if (_dashTickInit && nextDash != 0 && nextDash != _lastLocalDashTick)
|
||||
{
|
||||
EmitAt(_dashFx, (Vector3)localPos + Vector3.up * 0.6f, FeelConfig.DashBurstCount);
|
||||
PlayClip(_dashClip, (Vector3)localPos, FeelConfig.DashSfxVolume);
|
||||
PrototypeCameraRig.AddShake(FeelConfig.DashShake);
|
||||
PrototypeCameraRig.PunchFov(FeelConfig.DashFovKick, FeelConfig.HitStopDurationMs);
|
||||
}
|
||||
_lastLocalDashTick = nextDash;
|
||||
_dashTickInit = true;
|
||||
|
||||
if (localIFrameActive) // i-frame shimmer trail while the local window is active
|
||||
EmitAt(_dashFx, (Vector3)localPos + Vector3.up * 0.7f, FeelConfig.DashShimmerPerFrame);
|
||||
}
|
||||
|
||||
UpdateProjectileTrails(cfg);
|
||||
PruneVfx();
|
||||
AnimateNumbers(dt, cam);
|
||||
|
||||
Reference in New Issue
Block a user