using UnityEngine; using UnityEngine.Events; using UnityEngine.Localization; public class Sanity : MonoBehaviour { private static Sanity _instance; public static Sanity GetInstance() => _instance; [Header("Sanity Values")] [SerializeField] private float _sanity = 500f; [SerializeField] private float _sanityMaxValue = 500f; [SerializeField] private float sanityDropSpeed = 2f; [SerializeField] private float sanityDropSpeedInGhostUniverse = 4f; [SerializeField] private float restoreSpeed = 25f; [Header("Sanity Thresholds")] [SerializeField] private float minorHallucinationsValue = 350f; [SerializeField] private float majorHallucinationsValue = 150f; [Header("Sanity Modifiers")] public float sanityDropMultiplierWhenWatched = 1.2f; [Header("States")] public bool IsInLightSource; public bool sanityEventIsTakingPlace; public bool shouldUpdateSanityState = true; private bool _canDisplayMessageSanityIsDecreasingFast = true; public enum SanityState { Sane, MinorHallucinations, MajorHallucinations, Insane } public SanityState mentalState = SanityState.Sane; public event UnityAction OnSane; public event UnityAction OnMinorHallucinations; public event UnityAction OnMajorHallucinations; public event UnityAction OnInsane; [Header("Localization")] public LocalizedString sanityIsDeteriorating; public float currentSanity => _sanity; public float SanityMaxValue => _sanityMaxValue; public void SetSanity(float value) { _sanity = Mathf.Clamp(value, 0f, _sanityMaxValue); } public float sanityDropSpeedValue { get => sanityDropSpeed; set => sanityDropSpeed = Mathf.Max(0f, value); } public float sanityDropSpeedInGhostUniverseValue => sanityDropSpeedInGhostUniverse; public float sanityDropSpeedDefaultValue => sanityDropSpeed; public void sanityChangeMaxValueAtRuntime(float newSanityMaxValue) { _sanityMaxValue = newSanityMaxValue; _sanity = Mathf.Clamp(_sanity, 0f, _sanityMaxValue); UIManager.GetInstance().sanityDuration = _sanity; } private void Awake() { if (_instance == null) { _instance = this; } _sanity = _sanityMaxValue; UIManager.GetInstance().sanityDuration = _sanity; UIManager.GetInstance().startTime = _sanity; } private void Update() { UpdateSanity(); EvaluateSanityState(); UIManager.GetInstance().SanityMeterUI.material.SetFloat("_CurrentSanityValue", _sanity); HandleSanityWarnings(); } private void UpdateSanity() { if (sanityEventIsTakingPlace) return; bool isWatched = EyesManager.GetInstance()?.IsPlayerWatched() ?? false; float decay = AlternateUniverseManager.GetInstance().IsInGhostUniverse ? sanityDropSpeedInGhostUniverse : sanityDropSpeed; float finalDecay = decay; if (isWatched) { finalDecay *= sanityDropMultiplierWhenWatched; } if (!IsInLightSource) { _sanity -= finalDecay * Time.deltaTime; } else { if (isWatched) { // Ακόμα και αν είναι σε φως, αλλά παρακολουθείται, να χάνει sanity _sanity -= finalDecay * Time.deltaTime; } else { _sanity += restoreSpeed * Time.deltaTime; } } _sanity = Mathf.Clamp(_sanity, 0f, _sanityMaxValue); } private void EvaluateSanityState() { SanityState newState; if (_sanity > minorHallucinationsValue) newState = SanityState.Sane; else if (_sanity > majorHallucinationsValue) newState = SanityState.MinorHallucinations; else if (_sanity > 0) newState = SanityState.MajorHallucinations; else newState = SanityState.Insane; if (mentalState != newState) { mentalState = newState; TriggerStateEvent(newState); } } private void TriggerStateEvent(SanityState state) { switch (state) { case SanityState.Sane: OnSane?.Invoke(); break; case SanityState.MinorHallucinations: OnMinorHallucinations?.Invoke(); break; case SanityState.MajorHallucinations: OnMajorHallucinations?.Invoke(); break; case SanityState.Insane: OnInsane?.Invoke(); break; } } public void UsePill(float restoreAmount = -1f) { if (restoreAmount < 0f) restoreAmount = _sanityMaxValue; _sanity += restoreAmount; _sanity = Mathf.Clamp(_sanity, 0f, _sanityMaxValue); PlayerHealthManager.GetInstance().PillUsed = false; Debug.Log("Pills used"); } private void HandleSanityWarnings() { if (_sanity <= 200f && _canDisplayMessageSanityIsDecreasingFast) { UIManager.GetInstance().StartCoroutine(UIManager.GetInstance().DisplayMessage(sanityIsDeteriorating)); _canDisplayMessageSanityIsDecreasingFast = false; } else if (_sanity > 200f) { _canDisplayMessageSanityIsDecreasingFast = true; } } private void OnTriggerEnter(Collider col) { if (!AlternateUniverseManager.GetInstance().IsInGhostUniverse && col.CompareTag("LightSource")) { IsInLightSource = true; } } private void OnTriggerStay(Collider col) { if (!AlternateUniverseManager.GetInstance().IsInGhostUniverse && col.CompareTag("LightSource")) { IsInLightSource = true; } } private void OnTriggerExit(Collider col) { if (col.CompareTag("LightSource")) { IsInLightSource = false; } } }