136 lines
5.0 KiB
C#
136 lines
5.0 KiB
C#
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<Burnable> LogQueue = new List<Burnable>();
|
|
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<Burnable>();
|
|
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<Burnable>();
|
|
if (Burnable != null && LogQueue.Contains(Burnable)) {
|
|
LogQueue.Remove(Burnable);
|
|
Burnable.BurningInCampfire = false;
|
|
}
|
|
}
|
|
}
|
|
}
|