using DataTable; using Definition.Enum; using Event; using GameFramework.DataTable; using GameFramework.Event; using GameFramework.Fsm; using GameFramework.Procedure; using UI; using UnityGameFramework.Runtime; namespace Procedure { public class ProcedureMain : ProcedureBase { private const int InitialChapterId = 1; private const int InitialDialogId = 1001; private const int DialogChapterDivisor = 1000; private IDataTable _dtDialog; private bool _pendingSceneChange; private int _pendingSceneId; public override bool UseNativeDialog => false; protected override void OnEnter(IFsm procedureOwner) { base.OnEnter(procedureOwner); AIChatEntryRuntime.EnsureOpen(); GameEntry.Event.Subscribe(StoryChapterEndedEventArgs.EventId, OnStoryChapterEnded); _pendingSceneChange = false; _pendingSceneId = 0; GameEntry.Dialog.Init(InitialChapterId); GameEntry.Dialog.StartDialog(InitialDialogId); } protected override void OnLeave(IFsm procedureOwner, bool isShutdown) { GameEntry.Event.Unsubscribe(StoryChapterEndedEventArgs.EventId, OnStoryChapterEnded); base.OnLeave(procedureOwner, isShutdown); } protected override void OnUpdate(IFsm procedureOwner, float elapseSeconds, float realElapseSeconds) { base.OnUpdate(procedureOwner, elapseSeconds, realElapseSeconds); if (!_pendingSceneChange) { return; } _pendingSceneChange = false; procedureOwner.SetData("NextSceneId", _pendingSceneId); ChangeState(procedureOwner); } private void OnStoryChapterEnded(object sender, GameEventArgs e) { if (!(e is StoryChapterEndedEventArgs args)) { return; } int currentChapterId = args.ChapterId > 0 ? args.ChapterId : (GameEntry.Dialog != null ? GameEntry.Dialog.CurrentChapterId : 0); int nextChapterId = currentChapterId + 1; if (nextChapterId <= 0) { return; } if (!TryResolveFirstDialogId(nextChapterId, out int nextDialogId)) { Log.Info( "ProcedureMain chapter '{0}' ended and no next chapter found. Return to menu scene.", currentChapterId.ToString()); CloseBgFormIfOpened(); _pendingSceneId = (int)SceneId.Menu; _pendingSceneChange = true; return; } if (GameEntry.Dialog == null) { Log.Warning("ProcedureMain chapter switch failed. Dialog component is missing."); return; } if (!GameEntry.Dialog.Init(nextChapterId)) { Log.Warning("ProcedureMain chapter switch failed. Init chapter '{0}' failed.", nextChapterId.ToString()); return; } if (!GameEntry.Dialog.StartDialog(nextDialogId)) { Log.Warning("ProcedureMain chapter switch failed. Start dialog '{0}' failed.", nextDialogId.ToString()); } } private bool TryResolveFirstDialogId(int chapterId, out int dialogId) { dialogId = 0; if (chapterId <= 0) { return false; } if (_dtDialog == null) { _dtDialog = GameEntry.DataTable.GetDataTable(); } if (_dtDialog == null) { Log.Warning("ProcedureMain chapter switch failed. Data table DRDialog is missing."); return false; } DRDialog[] dialogRows = _dtDialog.GetDataRows((a, b) => a.Id.CompareTo(b.Id)); for (int i = 0; i < dialogRows.Length; i++) { DRDialog row = dialogRows[i]; if (row == null) { continue; } if (ParseChapterIdFromDialogId(row.Id) != chapterId) { continue; } dialogId = row.Id; return dialogId > 0; } return false; } private static int ParseChapterIdFromDialogId(int dialogId) { return dialogId / DialogChapterDivisor; } private static void CloseBgFormIfOpened() { if (GameEntry.UI == null) { return; } UGuiForm bgForm = GameEntry.UI.GetUIForm(UIFormId.BgForm); if (bgForm != null) { GameEntry.UI.CloseUIForm(bgForm.UIForm); } } } }