using UnityEngine;
using UnityEngine.Events;
/// <summary>
/// GAME 1303 Tier 6 — "Being in the dark too long has bad effects on the player."
/// (Jax's class idea for Detective Liz.) A dread meter that fills in darkness, empties
/// in light, and hurts you when it's full.
///
/// SETUP
/// 1. Add to the player, next to Health and Flashlight2D.
/// 2. What counts as "safe light":
/// - the player's own flashlight being ON (tick Flashlight Counts), and/or
/// - standing inside a SafeLightZone trigger (a lamp, a window, a lit room).
/// 3. Fill Rate / Drain Rate are per second. At 1.0 the meter is full: the player takes
/// Damage Per Interval every Damage Interval seconds until they find light.
/// 4. OnMeterChanged(0-1) -> a HUD vignette (an Image whose alpha you drive) or a bar.
/// OnEnteredDarkness / OnFoundLight are good hooks for a heartbeat sound and music.
/// 5. Grace Seconds gives a moment of darkness for free so walking past a shadow doesn't
/// start the dread.
///
/// Design note: pairing this with the "recharge only while standing still" flashlight rule
/// makes a real dilemma — stand still to get light back, and the dread rises while you do.
/// That tension is the game.
/// </summary>
public class DarknessMeter : MonoBehaviour
{
[Header("Rates (per second)")]
public float fillRate = 0.15f;
public float drainRate = 0.5f;
public float graceSeconds = 1.5f;
[Header("Light sources that count")]
public bool flashlightCounts = true;
public Flashlight2D flashlight;
[Tooltip("Layers of SafeLightZone triggers.")]
public LayerMask safeLightLayers;
public float checkRadius = 0.3f;
[Header("Damage when full")]
public int damagePerInterval = 1;
public float damageInterval = 2f;
[Header("Events")]
public UnityEvent<float> OnMeterChanged; // 0-1
public UnityEvent OnEnteredDarkness;
public UnityEvent OnFoundLight;
public UnityEvent OnMeterFull;
public float Meter { get; private set; }
public bool InDarkness { get; private set; }
private Health health;
private float graceTimer;
private float damageTimer;
private bool wasInDarkness;
void Awake()
{
health = GetComponent<Health>();
if (flashlight == null) flashlight = GetComponent<Flashlight2D>();
}
void Update()
{
bool lit = IsInLight();
InDarkness = !lit;
if (InDarkness != wasInDarkness)
{
wasInDarkness = InDarkness;
if (InDarkness) { graceTimer = graceSeconds; OnEnteredDarkness?.Invoke(); }
else OnFoundLight?.Invoke();
}
float before = Meter;
if (InDarkness)
{
if (graceTimer > 0f) graceTimer -= Time.deltaTime;
else Meter = Mathf.Min(1f, Meter + fillRate * Time.deltaTime);
}
else
{
Meter = Mathf.Max(0f, Meter - drainRate * Time.deltaTime);
damageTimer = 0f;
}
if (!Mathf.Approximately(before, Meter)) OnMeterChanged?.Invoke(Meter);
if (Meter >= 1f)
{
if (before < 1f) OnMeterFull?.Invoke();
damageTimer -= Time.deltaTime;
if (damageTimer <= 0f)
{
damageTimer = damageInterval;
health?.TakeDamage(damagePerInterval);
}
}
}
bool IsInLight()
{
if (flashlightCounts && flashlight != null && flashlight.IsOn) return true;
return Physics2D.OverlapCircle(transform.position, checkRadius, safeLightLayers) != null;
}
/// <summary>Reset on respawn — wire RespawnManager.OnRespawned here.</summary>
public void ResetMeter()
{
Meter = 0f;
graceTimer = graceSeconds;
damageTimer = 0f;
OnMeterChanged?.Invoke(0f);
}
}