using QSB.Player; using System.Linq; using UnityEngine; namespace QSB.RoastingSync; public class QSBMarshmallow : MonoBehaviour { public const float RAW_TOASTED_FRACTION = 0.2f; public const float PERFECT_TOASTED_FRACTION = 0.7f; public const float HEAT_CAPACITY = 300f; public const float BURN_THRESHOLD = 25f; public const float BURN_DURATION = 5f; public MeshRenderer _fireRenderer; public ParticleSystem _smokeParticles; public MeshRenderer _mallowRenderer; public Color _rawColor; public Color _toastedColor; public Color _burntColor; private Marshmallow.MallowState _mallowState; private ParticleSystem.MainModule _smokeParticlesSettings; private float _heatPerSecond; private float _toastedFraction; private float _initBurnTime; private float _initShrivelTime; private PlayerInfo _attachedPlayer; private void Awake() { _smokeParticlesSettings = _smokeParticles.main; _fireRenderer.enabled = false; _smokeParticles.Stop(); _attachedPlayer = QSBPlayerManager.PlayerList.First(x => x.Marshmallow == this); } private void Update() { if (_attachedPlayer.Campfire != null) { UpdateRoast(_attachedPlayer.Campfire.AttachedObject); } } public void SpawnMallow() { transform.localPosition = new Vector3(0f, 0f, 0.3f); transform.localScale = Vector3.one; _smokeParticles.Stop(); _fireRenderer.enabled = false; _toastedFraction = 0f; _mallowRenderer.enabled = true; _mallowState = Marshmallow.MallowState.Default; enabled = true; } public void Disable() { _smokeParticles.Stop(); _fireRenderer.enabled = false; enabled = false; } public void Extinguish() { if (_mallowState == Marshmallow.MallowState.Burning) { _fireRenderer.enabled = false; _mallowState = Marshmallow.MallowState.Default; } } public void UpdateRoast(Campfire campfire) { UpdateHeatExposure(campfire); UpdateVisuals(); transform.localPosition = Vector3.MoveTowards(transform.localPosition, Vector3.zero, Time.deltaTime); if (_mallowState != Marshmallow.MallowState.Default) { if (_mallowState == Marshmallow.MallowState.Shriveling) { var shrivelFraction = Mathf.Clamp01((Time.time - _initShrivelTime) / 2f); if (shrivelFraction >= 0.5 && _fireRenderer.enabled) { _fireRenderer.enabled = false; } transform.localScale = Vector3.one * (1f - shrivelFraction); } } _heatPerSecond = 0f; } private void UpdateHeatExposure(Campfire campfire) { _heatPerSecond = campfire.GetHeatAtPosition(transform.position); _toastedFraction += _heatPerSecond * Time.deltaTime / HEAT_CAPACITY; _toastedFraction = Mathf.Clamp01(_toastedFraction); } private void UpdateVisuals() { var num = _heatPerSecond / BURN_THRESHOLD; if (num > 0f) { if (!_smokeParticles.isEmitting) { _smokeParticles.Play(); } var smokeColor = new Color(1f, 1f, 1f, num); _smokeParticlesSettings.startColor = smokeColor; } else if (_smokeParticles.isEmitting) { _smokeParticles.Stop(); } Color newColor; if (_toastedFraction < PERFECT_TOASTED_FRACTION) { var fractionTowardsPerfect = _toastedFraction / PERFECT_TOASTED_FRACTION; newColor = Color.Lerp(_rawColor, _toastedColor, fractionTowardsPerfect); } else { var fractionTowardsBurnt = (_toastedFraction - PERFECT_TOASTED_FRACTION) / 0.3f; newColor = Color.Lerp(_toastedColor, _burntColor, fractionTowardsBurnt); } _mallowRenderer.material.color = Color.Lerp(_mallowRenderer.material.color, newColor, RAW_TOASTED_FRACTION); _smokeParticles.transform.forward = Locator.GetPlayerTransform().up; } public void Burn() { if (_mallowState == Marshmallow.MallowState.Default) { _fireRenderer.enabled = true; _toastedFraction = 1f; _initBurnTime = Time.time; _mallowState = Marshmallow.MallowState.Burning; } } public void Shrivel() { if (_mallowState == Marshmallow.MallowState.Burning) { _initShrivelTime = Time.time; _mallowState = Marshmallow.MallowState.Shriveling; } } public void RemoveMallow() { _smokeParticles.Stop(); _fireRenderer.enabled = false; _mallowRenderer.enabled = false; _mallowState = Marshmallow.MallowState.Gone; enabled = false; } }