using System.Collections.Generic; using UnityEngine; public class Campfire : MonoBehaviour { public GameState GameState; public Light DynamicLight; public Flame Flame; public CampfireSfx Sfx; public bool DebugDisableFuelMechanic; [Tooltip("The speed at which fuel goes down. For example, 0.5 will cause the campfire to last twice as long.")] public float FuelTickingMultiplier = 1; public float GoodFuelAmount; [Tooltip("The light turns this color when Fuel < GoodFuelAmount. Otherwise it'll be as it is in the editor.")] public Color TooLowFuelColor; public float RandomVarianceDuration; public float RandomVarianceMagnitude; [Tooltip("How long of a break the campfire takes between eating logs, if multiple are placed on it.")] public float LogBurningCooldown; [Header("Out-of-camp mechanic")] public float CampRadius; [Tooltip("Fuel won't go below this threshold if the player is outside of the camp.")] public float OutOfCampFuelThreshold; public float OutOfCampFuelRateMultiplier; [Header("Runtime values")] public float Fuel; public bool OutOfCamp = false; public float TimeToEnd { get { return Fuel / FuelTickingMultiplier - 0.7f; } } private Color EnoughFuelColor; private float FullRange; private float RandomVariance = 0; private float NextRandomVariance = 0; private float LastRandomVarianceChange = 0; private List LogQueue = new List(); private float NextLogTime = 0; private Transform Player; private void Awake() { EnoughFuelColor = DynamicLight.color; FullRange = DynamicLight.range; Player = GameObject.FindGameObjectWithTag("Player").transform; } private void Update() { TickFuel(); if (LogQueue.Count > 0 && Time.time > NextLogTime) { if (BurnLog(LogQueue[0])) { LogQueue.RemoveAt(0); if (LogQueue.Count > 0) { NextLogTime = Time.time + LogQueue[0].Quality.BurnTime; } } } if (Time.time - LastRandomVarianceChange > RandomVarianceDuration) { NextRandomVariance = (Random.value - 0.5f) * 2f * RandomVarianceMagnitude; LastRandomVarianceChange = Time.time; } RandomVariance = Mathf.Lerp(RandomVariance, NextRandomVariance, (Time.time - LastRandomVarianceChange) / RandomVarianceDuration); DynamicLight.range = Fuel / GoodFuelAmount / 2f * FullRange + RandomVariance; DynamicLight.color = Color.Lerp(DynamicLight.color, Fuel < GoodFuelAmount ? TooLowFuelColor : EnoughFuelColor, 10f * Time.deltaTime); Flame.Aliveness = Mathf.Log(Mathf.Max(0.01f, TimeToEnd), 10) / 2f; if (Fuel <= 0) { GameState.Current = State.GameOver; } } private void TickFuel() { float TickAmount = Time.deltaTime * FuelTickingMultiplier; if (DebugDisableFuelMechanic) { TickAmount = 0; } OutOfCamp = true; if ((Player.position - transform.position).magnitude < CampRadius) { // In camp, tick at normal rate OutOfCamp = false; } else if (Fuel > OutOfCampFuelThreshold) { // Player is outside of the camp, and the campfire is within safe levels, tick fuel at a slow rate TickAmount *= OutOfCampFuelRateMultiplier; } else { // Player is outside of the camp, and the campfire is below the threshold, stop ticking fuel // ( So they'll come back "just in time" ;) ) TickAmount = 0; } Fuel = Mathf.Max(0, Fuel - TickAmount); } private bool BurnLog(Burnable burnable) { if (Fuel >= GoodFuelAmount * 2) { return false; } else { Fuel += burnable.Quality.FuelValue * Mathf.Max(0.5f, (2 - Fuel / GoodFuelAmount)); Destroy(burnable.gameObject); return true; } } private void OnCollisionEnter(Collision c) { if (c.collider.attachedRigidbody != null && c.collider.attachedRigidbody) { Burnable Burnable = c.collider.attachedRigidbody.GetComponent(); if (Burnable != null && !LogQueue.Contains(Burnable)) { Flame.AddFuelEffect += Burnable.Quality.FlameEffect; Sfx.ActiveBurn += Burnable.Quality.SoundEffect; if (LogQueue.Count == 0) { NextLogTime = Time.time + Burnable.Quality.BurnTime; } LogQueue.Add(Burnable); Burnable.BurningInCampfire = true; } } } private void OnCollisionExit(Collision c) { if (c.collider.attachedRigidbody != null && c.collider.attachedRigidbody) { Burnable Burnable = c.collider.attachedRigidbody.GetComponent(); if (Burnable != null && LogQueue.Contains(Burnable)) { LogQueue.Remove(Burnable); Burnable.BurningInCampfire = false; } } } }