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);
}
}