using System; using System.Collections; using System.Collections.Generic; //using Gaia; using Invector.vCharacterController; using Invector.vCharacterController.AI; using Invector.vCharacterController.AI.FSMBehaviour; using PixelCrushers; using Sirenix.OdinInspector; using SRF.Components; using UnityEngine; using UnityEngine.Events; using UnityEngine.SceneManagement; namespace Beyond { public class GameStateManager : Saver//AutoSingleton { public enum Difficulty { EASY = 0, NORMAL = 1, HARD = 2, COUNT }; [Button] public void SetDifficulty(Difficulty d) { m_saveData.difficulty = d; switch (d) { case Difficulty.EASY: m_enemyDamageModifier = 0.63f; break; case Difficulty.NORMAL: m_enemyDamageModifier = 1f; break; case Difficulty.HARD: m_enemyDamageModifier = 1.35f; break; } } [Serializable] public class SaveData { public Difficulty difficulty = Difficulty.NORMAL; } private static GameStateManager s_instance = null; private static bool s_isDestroyed = false; private float m_enemyDamageModifier = 1f; public SaveData m_saveData = new(); private HashSet m_CompabStates; private HashSet m_IdleStates; public static GameStateManager Instance// => s_instance; { get { if (s_instance) { return s_instance; } else if (s_isDestroyed) { //don't recreate object after scene destorys it return null; } else { var inst = FindObjectOfType(); if (inst != null) { s_instance = inst; return s_instance; } else { var go = new GameObject("_" + typeof(GameStateManager).Name); go.AddComponent(); // _instance set by Awake() constructor } } return s_instance; } } //public void OnSc public override void OnDestroy() { base.OnDestroy(); s_isDestroyed = true; // Debug.Log("Destroying GameStateManager"); } //[ShowInInspector] public Difficulty GameDifficulty => m_saveData.difficulty; public float EnemyDamageModifier => m_enemyDamageModifier; public override void Awake() { base.Awake(); if (s_instance != null) { Debug.Log("GameStateManager already exists! destroying..."); Destroy(this); return; } SceneManager.sceneLoaded += SceneManager_sceneUnloaded; s_instance = this; //SetDifficulty(Difficulty.NORMAL); m_CompabStates = new HashSet(); m_CompabStates.Add("Combat"); m_CompabStates.Add("Alert"); m_CompabStates.Add("Jump Chase"); m_CompabStates.Add("Jump"); m_CompabStates.Add("Chase"); m_IdleStates = new HashSet(); m_IdleStates.Add("Idle"); m_IdleStates.Add("Flee"); m_IdleStates.Add("Patrol"); } //reset isDestroyed, so object can be recreated for the next scene private void SceneManager_sceneUnloaded(Scene arg0, LoadSceneMode arg1) { s_isDestroyed = false; } public enum State { NORMAL, COMBAT } public UnityEvent m_OnStateChanged = new UnityEvent(); private HashSet m_combatControllers = new HashSet(); private State m_state = State.NORMAL, m_prevState = State.NORMAL; public State CurrentState => m_state; public bool m_changeCameraState; public string m_cameraCombatState = "Combat"; public vThirdPersonInput m_thirdPersonInput; private GenericInput m_jumpInput, m_rollInput; protected bDrawHideMeleeWeapons m_weaponDraw; protected vThirdPersonController m_thirdPersonController; public bool m_autoDrawWeapon = true; // Start is called before the first frame update public HashSet GetActiveCombatcontrollers() { return m_combatControllers; } public override void Reset() { base.Reset(); saveAcrossSceneChanges = true; m_saveData.difficulty = Difficulty.NORMAL; } [Button] public void SetEasy() { m_saveData.difficulty = Difficulty.EASY; } [Button] public void SetNormal() { m_saveData.difficulty = Difficulty.NORMAL; } [Button] public void SetHard() { m_saveData.difficulty = Difficulty.HARD; } private void Start() { // m_state = State.NORMAL; if (Player.Instance == null) { return; } if (m_thirdPersonInput == null) m_thirdPersonInput = Player.Instance.GetComponent(); if (m_weaponDraw == null) m_weaponDraw = Player.Instance.GetComponent(); if (m_thirdPersonController == null) m_thirdPersonController = Player.Instance.GetComponent(); var respawner = Player.Instance.GetComponent(); if (respawner != null) { respawner.m_onRespawned.AddListener(ResetState); } m_jumpInput = m_thirdPersonInput.jumpInput; m_rollInput = m_thirdPersonInput.rollInput; } public override string RecordData() { return SaveSystem.Serialize(m_saveData); } public override void ApplyData(string s) { if (!String.IsNullOrEmpty(s)) { m_saveData = SaveSystem.Deserialize(s); SetDifficulty(m_saveData.difficulty); } } public override void ApplyDataImmediate() { // Immediately restore Lua in case other scripts' // Start() methods need to read values from it. var data = SaveSystem.currentSavedGameData.GetData(key); if (!String.IsNullOrEmpty(data)) { m_saveData = SaveSystem.Deserialize(data); SetDifficulty(m_saveData.difficulty); } } private void ResetState() { foreach (var c in m_combatControllers) { c.ResetFSM(); } m_combatControllers.Clear(); m_thirdPersonInput.ResetCameraState(); SetState(State.NORMAL); } public void SetState(State state) { if (m_state == state) return; m_prevState = m_state; if (m_changeCameraState) { if (m_prevState == State.COMBAT) { m_thirdPersonInput.ResetCameraState(); SetDefaultInputsForRollJump(); } else if (state == State.COMBAT) { SetRollInputOnJump(); m_thirdPersonInput.ChangeCameraState(m_cameraCombatState, true); } } switch (state) { case State.COMBAT: SetRollInputOnJump(); if (m_autoDrawWeapon && m_weaponDraw != null) { m_weaponDraw.DrawWeapons(); } break; case State.NORMAL: SetDefaultInputsForRollJump(); if (m_autoDrawWeapon && m_weaponDraw != null) { m_weaponDraw.HideWeapons(); } break; } m_state = state; m_OnStateChanged?.Invoke(m_state); } private void SetRollInputOnJump() { m_thirdPersonInput.rollInput = m_jumpInput; m_thirdPersonInput.jumpInput = m_rollInput; } private void SetDefaultInputsForRollJump() { m_thirdPersonInput.rollInput = m_rollInput; m_thirdPersonInput.jumpInput = m_jumpInput; } public void OnCombat(vFSMBehaviourController combatController) { if (m_combatControllers.Count == 0) { SetState(State.COMBAT); } m_combatControllers.Add(combatController); } public void OnCombatEnd(vFSMBehaviourController combatController) { m_combatControllers.Remove(combatController); if (m_combatControllers.Count == 0) { SetState(State.NORMAL); } } // Update is called once per frame //private float m_timer = 1; private void Update() { foreach (var c in m_combatControllers) { //Debug.Log($"{c.name} is in {c.currentState.Name}"); string name = c.currentState.Name; //if (!m_CompabStates.Contains(name)) if (m_IdleStates.Contains(name)) { OnCombatEnd(c); break; } } } } }