using UnityEngine; using UnityEngine.Rendering.HighDefinition; using UnityEngine.Playables; using System.Collections; using UnityEngine.Animations.Rigging; using System.Text.RegularExpressions; public class CandleController : MonoBehaviour { [Header("References")] [SerializeField] private GameObject candleMesh; public Light candleLight; [SerializeField] private HDAdditionalLightData lightData; [Header("Candle Settings")] [SerializeField] private float maxCandleLife = 100f; [SerializeField] private float lightIntensity = 200f; [SerializeField] private float _candleLife; [SerializeField] private float _candleSecondsToTurnOffWhenRunning = 0.3f; public bool canUseCandle = true; public bool isUsingCandle; public bool canToggleCandle; public bool isSettingOnFireCandle; private bool _isCandleOn = false; [SerializeField] private PlayableDirector candleLitPlayable; [SerializeField] private GameObject matchGO; [SerializeField] private ParticleSystem matchFlame; [SerializeField] private ParticleSystem candleFlame; Coroutine IsRunningTimerCoroutine; [Header("Inverse Kinematics")] [SerializeField] private float multiAimConstraintTransitionDuration = 1; [SerializeField] MultiAimConstraint multiAimConstraintPlayersRightHand; private Coroutine TransitionWeightToAimingCandleLightCoroutine; private Coroutine TransitionWeightToNotAimingCandleLightCoroutine; private static CandleController _instance; public static CandleController GetInstance() => _instance; public bool isCandleOn => _isCandleOn; public float candleLife => _candleLife; private void Awake() { if (_instance == null) _instance = this; } private void Start() { _candleLife = maxCandleLife; if (candleLight != null) { candleLight.enabled = false; lightData = candleLight.GetComponent(); lightData.intensity = lightIntensity; } if (candleMesh != null) { candleMesh.SetActive(false); } matchGO.SetActive(false); InitialSetup(); StartCoroutine(AfterGameLoaded()); } void InitialSetup() { GameObject playerGo = PlayerManager.GetInstance().playerGameObj; if (multiAimConstraintPlayersRightHand == null) { multiAimConstraintPlayersRightHand = playerGo.transform.Find("MainCharacter/Rig 1/CandleLight_MultiAimConstraint").GetComponent(); } else { Debug.LogError("No multiAimConstraintPlayersRightHand found in the scene."); } } IEnumerator AfterGameLoaded() { yield return new WaitUntil(() => LoadManager.GetInstance() != null && !LoadManager.GetInstance().LoadingGame); yield return new WaitUntil(() => PlayerManager.GetInstance() != null); PlayerManager.GetInstance()._PlayerMovement.OnRunning += IsRunningStartCandleTurnOffTimer; PlayerManager.GetInstance()._PlayerMovement.OnStoppedRunning += IsRunningStopCandleTurnOffTimer; InitialSetup(); } private void OnDisable() { PlayerManager.GetInstance()._PlayerMovement.OnRunning -= IsRunningStartCandleTurnOffTimer; PlayerManager.GetInstance()._PlayerMovement.OnStoppedRunning -= IsRunningStopCandleTurnOffTimer; } private void Update() { if (GameProgressManager.GetInstance().CandleHolderIsObtained) { if (Input.GetKeyDown(KeyCode.F) && !isSettingOnFireCandle) { UseCandleHolder(); } if (canToggleCandle && _candleLife > 0f) { if (Input.GetKeyDown(KeyCode.R)) { if (_isCandleOn == false) { TransitionWeightToNotAimingCandleLight(); isSettingOnFireCandle = true; candleLitPlayable.Play(); PlayerManager.GetInstance()._PlayerMovement._CharacterAnimator.SetBool("CandleIdle", false); PlayerManager.GetInstance()._PlayerMovement._CharacterAnimator.SetBool("IsLitCandle", true); //ToggleCandle(); CanNotToggleCandle(); print("Play candle lit playable"); } //else //{ // PlayerManager.GetInstance()._PlayerMovement._CharacterAnimator.SetBool("IsUsingCandle", false); // PlayerManager.GetInstance()._PlayerMovement._CharacterAnimator.SetBool("IsLitCandle", false); // _isCandleOn = false; //} } } if (_isCandleOn) { _candleLife -= Time.deltaTime; if (_candleLife <= 0f) { _candleLife = 0f; TurnOffCandle(); } } RaycastHit hit; Vector3 forward = FlashlightRaycast.GetInstance().flashlightRaycast.forward; if (isUsingCandle && canToggleCandle) { if (Physics.Raycast(FlashlightRaycast.GetInstance().flashlightRaycast.transform.position, forward, out hit, 0.5f, FlashlightRaycast.GetInstance().collisionLayer, QueryTriggerInteraction.Ignore)) { FlashlightRaycast.GetInstance().flashlightCurrentCollider = hit.collider.transform; if (hit.collider) { if (!PlayerManager.GetInstance()._PlayerMovement._CharacterAnimator.GetBool("IsWallInFront")) { TransitionWeightToNotAimingCandleLight(); PlayerManager.GetInstance()._PlayerMovement._CharacterAnimator.SetBool("IsWallInFront", true); } } //print("Found an object - distance: " + hit.distance); } else { FlashlightRaycast.GetInstance().flashlightCurrentCollider = null; if (PlayerManager.GetInstance()._PlayerMovement._CharacterAnimator.GetBool("IsWallInFront")) { TransitionWeightToAimingCandleLight(); PlayerManager.GetInstance()._PlayerMovement._CharacterAnimator.SetBool("IsWallInFront", false); } } //Vector3 forward = transform.TransformDirection(Vector3.forward) * 0.5f; Debug.DrawRay(transform.position, forward * 0.5f, Color.green); } } } public void UseCandleHolder() { if (canUseCandle) { if (!isUsingCandle) { candleMesh.SetActive(true); canToggleCandle = false; PlayerManager.GetInstance()._PlayerMovement._CharacterAnimator.SetBool("IsUsingCandle", true); PlayerManager.GetInstance()._PlayerMovement._CharacterAnimator.SetBool("CandleIdle", true); StartCoroutine(CanUseAndToggleCandleAfterSeconds(true, true)); TransitionWeightToAimingCandleLight(); isUsingCandle = true; canUseCandle = false; } else { canToggleCandle = false; PlayerManager.GetInstance()._PlayerMovement._CharacterAnimator.SetBool("IsUsingCandle", false); PlayerManager.GetInstance()._PlayerMovement._CharacterAnimator.SetBool("CandleIdle", false); PlayerManager.GetInstance()._PlayerMovement._CharacterAnimator.SetBool("IsLitCandle", false); StartCoroutine(CanUseAndToggleCandleAfterSeconds(true, false)); StopCandleFlameParticle(); TurnOffCandle(); isUsingCandle = false; canUseCandle = false; } } } public void IsRunningStartCandleTurnOffTimer() { PlayerManager.GetInstance()._PlayerMovement._CharacterAnimator.SetBool("CandleIdleRunning", true); if(IsRunningTimerCoroutine == null) { IsRunningTimerCoroutine = StartCoroutine(IsRunningTimer()); } } public void IsRunningStopCandleTurnOffTimer() { PlayerManager.GetInstance()._PlayerMovement._CharacterAnimator.SetBool("CandleIdleRunning", false); if (IsRunningTimerCoroutine != null) { StopCoroutine(IsRunningTimerCoroutine); print("Stopped Running timer turn off candle"); IsRunningTimerCoroutine = null; } } IEnumerator IsRunningTimer() { yield return new WaitForSeconds(_candleSecondsToTurnOffWhenRunning); TurnOffCandle(); print("Player sprinted for: " + _candleSecondsToTurnOffWhenRunning + " seconds so the candle turned Off"); } IEnumerator CanUseAndToggleCandleAfterSeconds(bool canUseCandle, bool canToggleCandle) { yield return new WaitForSeconds(1f); if (canToggleCandle) { CanToggleCandle(); } else { CanNotToggleCandle(); } if (canUseCandle) { CanUseCandle(); } else { CanNotUseCandle(); } } public void PlayMatchFlameParticle() { matchGO.SetActive(true); matchFlame.Play(); } public void StopMatchFlameParticle() { matchFlame.Stop(); matchGO.SetActive(false); } public void PlayCandleFlameParticle() { candleFlame.Play(); } public void StopCandleFlameParticle() { candleFlame.Stop(); } public void CanToggleCandle() { canToggleCandle = true; } public void CanNotToggleCandle() { canToggleCandle = false; } public void CanUseCandle() { canUseCandle = true; } public void CanNotUseCandle() { canUseCandle = false; } public void SetAnimatorBoolCandleIdle(bool CandleIdle) { PlayerManager.GetInstance()._PlayerMovement._CharacterAnimator.SetBool("CandleIdle", CandleIdle); } public void SetAnimatorBoolIsLitCandle(bool IsLitCandle) { PlayerManager.GetInstance()._PlayerMovement._CharacterAnimator.SetBool("IsLitCandle", IsLitCandle); isSettingOnFireCandle = false; } public void ToggleCandle() { if (_isCandleOn) TurnOffCandle(); else TurnOnCandle(); } public void TurnOnCandle() { if (_candleLife <= 0f) return; _isCandleOn = true; candleLight.enabled = true; TransitionWeightToAimingCandleLight(); if (candleMesh != null) candleMesh.SetActive(true); } public void TurnOffCandle() { _isCandleOn = false; candleLight.enabled = false; candleFlame.Stop(); TransitionWeightToNotAimingCandleLight(); PlayerManager.GetInstance()._PlayerMovement._CharacterAnimator.SetBool("IsWallInFront", false); } public void TransitionWeightToAimingCandleLight() { TransitionWeightToAimingCandleLightCoroutine = StartCoroutine(TransitionWeightAimingCandleLight(multiAimConstraintPlayersRightHand.weight, 1, 2)); if (TransitionWeightToNotAimingCandleLightCoroutine != null) { StopCoroutine(TransitionWeightToNotAimingCandleLightCoroutine); TransitionWeightToNotAimingCandleLightCoroutine = null; } } public void TransitionWeightToNotAimingCandleLight() { TransitionWeightToNotAimingCandleLightCoroutine = StartCoroutine(TransitionWeightAimingCandleLight(multiAimConstraintPlayersRightHand.weight, 0, 2)); if (TransitionWeightToAimingCandleLightCoroutine != null) { StopCoroutine(TransitionWeightToAimingCandleLightCoroutine); TransitionWeightToAimingCandleLightCoroutine = null; } } public void ReduceCandleLife(float amount) { _candleLife = Mathf.Max(0f, _candleLife - amount); if (_candleLife == 0f) TurnOffCandle(); } public void RefillCandle(float amount) { _candleLife = Mathf.Clamp(_candleLife + amount, 0f, maxCandleLife); } public void FullyRefillCandle() { _candleLife = maxCandleLife; } public float GetCandleLifePercent() { return _candleLife / maxCandleLife; } private IEnumerator TransitionWeightAimingCandleLight(float startWeight, float targetWeight, float speed) { float elapsedTime = 0f; while (elapsedTime < multiAimConstraintTransitionDuration) { elapsedTime += Time.deltaTime; float t = Mathf.Clamp01(elapsedTime / multiAimConstraintTransitionDuration); multiAimConstraintPlayersRightHand.weight = Mathf.Lerp(startWeight, targetWeight, speed * t); yield return null; } // Ensure the target weight is reached precisely multiAimConstraintPlayersRightHand.weight = targetWeight; //canPressButtonToOpenOrCloseFlashlight = true; if (!isUsingCandle) { candleMesh.SetActive(false); } } }