using UnityEngine; namespace Unheimlich.Features.Player { /// /// Manages the player's stress level and forwards it to . /// Stress rises instantly to the requested target and decays back to zero over time when not sustained. /// /// Intended to sit on OctoPlayerFP alongside other player-level components. /// Call , , or from /// gameplay systems (proximity triggers, jump-scares, scripted events, etc.). /// public class StressController : MonoBehaviour { // ── Inspector ───────────────────────────────────────────────────────────── [Header("References")] [Tooltip("The LostFootageRig component on CameraPivot.")] [SerializeField] private Unheimlich.World.CameraSystem.LostFootageRig _rig; [Header("Decay")] [Tooltip("Rate at which stress falls back to zero per second when not sustained.")] [SerializeField] private float _decaySpeed = 0.3f; [Tooltip("Stress must stay below this threshold for the rig to auto-deactivate.")] [SerializeField] private float _deactivateThreshold = 0.05f; [Header("Debug")] [SerializeField] private bool _debugSustainStress; [SerializeField] [Range(0f, 1f)] private float _debugStressValue; // ── Runtime state ───────────────────────────────────────────────────────── private float _currentStress; private float _targetStress; private bool _sustained; // true while an external system holds a target this frame // ── Unity lifecycle ─────────────────────────────────────────────────────── private void Update() { if (_debugSustainStress) SetStress(_debugStressValue); _sustained = false; if (_currentStress > _targetStress) _currentStress = Mathf.MoveTowards(_currentStress, _targetStress, _decaySpeed * Time.deltaTime); else _currentStress = _targetStress; _targetStress = 0f; // reset each frame; callers must re-assert every Update if sustained if (_rig == null) return; _rig.StressLevel = _currentStress; // Auto-toggle the rig based on stress level. if (!_rig.IsActive && _currentStress > _deactivateThreshold) _rig.SetActive(true); else if (_rig.IsActive && _currentStress <= _deactivateThreshold) _rig.SetActive(false); } // ── Public API ──────────────────────────────────────────────────────────── /// /// Sets a one-shot stress spike that will decay naturally next frame. /// For sustained stress, call this every frame from a trigger zone or event. /// public void SetStress(float value) { _targetStress = Mathf.Max(_targetStress, Mathf.Clamp01(value)); _currentStress = Mathf.Max(_currentStress, _targetStress); } /// Adds on top of the current target stress. public void AddStress(float delta) => SetStress(_targetStress + delta); /// Immediately zeroes stress and deactivates the rig. public void CalmDown() { _currentStress = 0f; _targetStress = 0f; _rig?.SetActive(false); } /// /// Directly activates or deactivates the rig regardless of stress level. /// Useful for scripted sequences where you want the effect without the stress system. /// public void ForceRig(bool active) => _rig?.SetActive(active); } }