using UnityEngine;
namespace ProjectM.Client
{
///
/// Live-tunable knobs for the client-only COMBAT-FEEL slice (Stage E). A static bridge — mirrors
/// — so values can be poked at runtime via MCP execute_code
/// (e.g. ProjectM.Client.FeelConfig.HitShakeLocal = 0.4f;) WITHOUT a recompile, for interactive
/// tuning. Read ONLY by client-presentation systems (,
/// ) and the MonoBehaviour — all non-Burst,
/// main-thread. NEVER read these from a [BurstCompile] system (managed-static + Color/enum-in-Burst
/// hazards); they are presentation-only and never touch the deterministic simulation.
///
/// Defaults match the values previously hardcoded in CombatFeedbackSystem so behaviour is byte-identical
/// until a knob is poked. re-stamps every field on play-enter via
/// [RuntimeInitializeOnLoadMethod(SubsystemRegistration)] because statics survive fast-enter-playmode
/// domain reloads — without it a poked value would leak across play-enters and flash stale feel (the exact
/// bug 's reset prevents).
///
///
public static class FeelConfig
{
// ---- Feature 1: hit camera punch + (camera-only) hit-stop ----
/// Camera shake when the LOCAL player is hit (fed to PrototypeCameraRig.AddShake, clamp 0.8).
public static float HitShakeLocal;
/// Camera shake when a remote player / Husk is hit.
public static float HitShakeRemote;
/// Hit-spark particle burst count (procedural fallback path).
public static int HitBurstCount;
/// Hit SFX volume.
public static float HitSfxVolume;
/// Degrees of transient FOV "kick" on a LOCAL hit — the netcode-safe hit-stop (NEVER Time.timeScale). 0 = off.
public static float HitStopFovKick;
/// Milliseconds the FOV kick eases back to base.
public static float HitStopDurationMs;
// ---- Feature 1/2: death camera punch ----
/// Camera shake on LOCAL player death (loudest event by design).
public static float PlayerDeathShake;
/// Camera shake on a remote player's death.
public static float RemotePlayerDeathShake;
/// Base death-burst particle count (player death + Husk-death base).
public static int DeathBurstCount;
// ---- Feature 2: kill-shot fanfare (Husk death) ----
/// Camera shake on a Husk kill (nudged above a glancing hit, kept under PlayerDeathShake).
public static float KillShake;
/// Multiplier on DeathBurstCount for a Husk kill (result clamped by MaxActiveVfx).
public static float KillBurstScale;
/// Optional FOV kick on a kill (degrees). 0 = off.
public static float KillFovKick;
/// Husk-death SFX volume.
public static float KillSfxVolume;
// ---- Feature 3: respawn shimmer / fade-in (local player recovery) ----
/// Master gate for the local-player respawn shimmer.
public static bool RespawnShimmerEnabled;
/// Particle burst count for the recovery shimmer.
public static int RespawnShimmerBurst;
/// Light camera punch on recovery so respawn reads as "reinforcing".
public static float RespawnShimmerShake;
// ---- Feature 4: reticle lock-on tether (cosmetic aim HINT) ----
/// Master gate for the lock-on tether.
public static bool LockOnEnabled;
/// Show the tether only on the Gamepad scheme (mirrors the server's gamepad-only auto-target assist).
public static bool LockOnGamepadOnly;
/// Max world distance from the player to a tethered Husk.
public static float LockOnRange;
/// Forward half-arc (degrees) around PlayerFacing within which a Husk is eligible.
public static float LockOnArcDegrees;
/// Tether line tint (subtle highlight, not a laser).
public static Color LockOnLineColor;
/// Tether line width (world units).
public static float LockOnLineWidth;
// ---- Feature B: enemy health bars (Slice 1) ----
/// Squared world-distance beyond which a bar is hidden when the pool cap is reached (default 400 = 20m).
public static float HealthBarMaxDistSq;
// ---- Feature 5 (MC-1): dash juice ----
/// Camera shake on the local player's dash start.
public static float DashShake;
/// Transient FOV punch (degrees) on dash start — the "lurch" read (camera punch, never Time.timeScale).
public static float DashFovKick;
/// Afterimage/whoosh particle burst count at dash start.
public static int DashBurstCount;
/// Dash whoosh SFX volume.
public static float DashSfxVolume;
/// Particles emitted per frame while the local i-frame window is active (the shimmer trail).
public static int DashShimmerPerFrame;
/// Suppress local hit-feedback during the local i-frame window (masks the prediction-reconciliation
/// Health flicker on a clean dodge — the documented acceptable-not-a-bug interaction).
public static bool DashHitSuppress;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
public static void ResetDefaults()
{
// Feature 1
HitShakeLocal = 0.32f;
HitShakeRemote = 0.10f;
HitBurstCount = 10;
HitSfxVolume = 0.70f;
HitStopFovKick = 1.5f;
HitStopDurationMs = 90f;
// Feature 1/2 death
PlayerDeathShake = 0.50f;
RemotePlayerDeathShake = 0.25f;
DeathBurstCount = 28;
// Feature 2 kill-shot
KillShake = 0.20f;
KillBurstScale = 1.5f;
KillFovKick = 1.0f;
KillSfxVolume = 0.75f;
// Feature 3 respawn
RespawnShimmerEnabled = true;
RespawnShimmerBurst = 24;
RespawnShimmerShake = 0.12f;
// Feature 4 tether
LockOnEnabled = true;
LockOnGamepadOnly = true;
LockOnRange = 9.0f;
LockOnArcDegrees = 60f;
LockOnLineColor = new Color(0.55f, 0.9f, 1f, 0.35f);
LockOnLineWidth = 0.05f;
// Feature B health bars (Slice 1)
HealthBarMaxDistSq = 400f; // 20 m radius
// Feature 5 dash (MC-1)
DashShake = 0.18f;
DashFovKick = 1.2f;
DashBurstCount = 14;
DashSfxVolume = 0.55f;
DashShimmerPerFrame = 2;
DashHitSuppress = true;
}
}
}