using System; using System.Collections.Generic; using Cysharp.Threading.Tasks; using SepCore.DataTable; using SepCore.Definition; using SepCore.Entity; using GameFramework.Fsm; using GameFramework.Procedure; using UnityGameFramework.Runtime; using SepCore.AsyncTask; namespace SepCore.Procedure { public enum GameStateType { None = 0, Battle = 1, Shop = 2, LevelUp = 3, } public class ProcedureGame : ProcedureBase { public override bool UseNativeDialog => false; private PlayerData _currentPlayerData; public int CurrentLevel = 1; private GameStateType _currentGameState = GameStateType.None; private Dictionary _gameStates; public Player Player; public GameStateBase CurrentGameState => _gameStates[_currentGameState]; public GameStateType CurrentGameStateType => _currentGameState; private void InitGameState() { _gameStates = new Dictionary { { GameStateType.Battle, new GameStateBattle() }, { GameStateType.LevelUp, new GameStateLevelUp() }, { GameStateType.Shop, new GameStateShop() }, }; _gameStates[GameStateType.Battle].OnInit(this); _gameStates[GameStateType.LevelUp].OnInit(this); _gameStates[GameStateType.Shop].OnInit(this); _currentGameState = GameStateType.Battle; _gameStates[_currentGameState].OnEnter(); } public void BattleToShopOrLevelUp() { CurrentLevel++; if (_currentGameState == GameStateType.Shop || _currentGameState == GameStateType.LevelUp) return; _gameStates[_currentGameState].OnLeave(); _currentGameState = Player.PendingLevelPoints > 0 ? GameStateType.LevelUp : GameStateType.Shop; _gameStates[_currentGameState].OnEnter(); } public void ShopToBattle() { if (_currentGameState == GameStateType.Battle) return; _gameStates[_currentGameState].OnLeave(); _currentGameState = GameStateType.Battle; _gameStates[_currentGameState].OnEnter(); } public void LevelUpToShop() { if (_currentGameState == GameStateType.Shop) return; _gameStates[_currentGameState].OnLeave(); _currentGameState = GameStateType.Shop; _gameStates[_currentGameState].OnEnter(); } #region FSM protected override void OnEnter(IFsm procedureOwner) { base.OnEnter(procedureOwner); GameEntry.SimulationWorld?.ClearSimulationState(); CurrentLevel = 1; _currentPlayerData = new PlayerData(-1, 1001); EnterAsync(procedureOwner).Forget(); } protected override void OnUpdate(IFsm procedureOwner, float elapseSeconds, float realElapseSeconds) { base.OnUpdate(procedureOwner, elapseSeconds, realElapseSeconds); _gameStates?[_currentGameState].OnUpdate(elapseSeconds, realElapseSeconds); } protected override void OnLeave(IFsm procedureOwner, bool isShutdown) { if (_gameStates != null) { foreach (var state in _gameStates.Values) { state.OnDestroy(); } _gameStates.Clear(); } GameEntry.UIRouter.CloseUIAsync(UIFormType.HudForm).Forget(); Player = null; GameEntry.SimulationWorld?.ClearSimulationState(); base.OnLeave(procedureOwner, isShutdown); } #endregion private async UniTaskVoid EnterAsync(IFsm procedureOwner) { try { Player = await GameEntry.Entity.ShowPlayerAsync(_currentPlayerData); await GameEntry.UIRouter.OpenUIAsync(UIFormType.HudForm); int selectedRoleId = procedureOwner.GetData("SelectedRoleId").Value; var role = GameEntry.DataTable.GetDataTableRow(selectedRoleId); if (role == null) { Log.Error("ProcedureGame.EnterAsync() can not load role '{0}'.", selectedRoleId.ToString()); return; } Player.InitRole(role); InitGameState(); } catch (Exception exception) { Log.Error("ProcedureGame.EnterAsync() failed with exception '{0}'.", exception); } } } }