207 lines
5.9 KiB
C#
207 lines
5.9 KiB
C#
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;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|