private void AddEntry(InitParams initParams) { if (checkpointManager.IsReached(initParams.currentNodeName, initParams.currentDialogueIndex, initParams.variablesHashBeforeChange) is GameStateStepRestoreCheckpointEntry) { lastCheckpointLogParamsRef = initParams; } var logEntry = Instantiate(logEntryPrefab, logContent.transform) .GetComponent <LogEntryController>(); UnityAction <int> onGoBackButtonClicked = logEntryIndex => OnGoBackButtonClicked(initParams.currentNodeName, initParams.currentDialogueIndex, logEntryIndex, initParams.variablesHashBeforeChange); UnityAction onPlayVoiceButtonClicked = null; if (initParams.voices.Any()) { onPlayVoiceButtonClicked = () => OnPlayVoiceButtonClicked(initParams.voices); } logEntry.Init(initParams.displayData, onGoBackButtonClicked, onPlayVoiceButtonClicked, initParams.logEntryIndex); logEntries.Add(logEntry); logParams.Add(initParams); RestrainLogEntryNum(maxLogEntryNum); }
/// <summary> /// Called after the current node or the index of the current dialogue entry has changed. /// </summary> /// <remarks> /// The game state will be updated according to walkedThroughNodes and current dialogue index. /// This method will check if the game state has changed and trigger proper events /// </remarks> /// <param name="forceRefreshDialogue">refresh dialogue no matter the game state has change or not</param> /// <param name="forceRefreshNode">refresh the node no matter the node has changed or not</param> private void UpdateGameState(bool forceRefreshDialogue = false, bool forceRefreshNode = false) { Assert.IsFalse(walkedThroughNodes.Count == 0, "Nova: walkedThroughNodes is empty, can not update game state."); // update current node var desiredNodeName = walkedThroughNodes.Last(); var nodeChanged = currentNode == null || currentNode.name != desiredNodeName; if (nodeChanged || forceRefreshNode) { currentNode = flowChartTree.FindNode(desiredNodeName); if (NodeChanged != null) { NodeChanged.Invoke(new NodeChangedData(currentNode.name, currentNode.description)); } } // update dialogue var dialogueChanged = nodeChanged || currentIndex != oldIndex; if (dialogueChanged || forceRefreshDialogue) { Assert.IsTrue(currentIndex >= 0 && currentIndex < currentNode.DialogueEntryCount, "Nova: dialogue index out of range"); currentDialogueEntry = currentNode.GetDialogueEntryAt(currentIndex); oldIndex = currentIndex; if (checkpointManager.IsReached(currentNode.name, currentIndex) == null) { // tell the checkpoint manager a new dialogue entry has been reached checkpointManager.SetReached(currentNode.name, currentIndex, GetGameStateStepRestoreEntry()); } if (DialogueWillChange != null) { DialogueWillChange.Invoke(); } state = State.ActionRunning; currentDialogueEntry.ExecuteAction(); StartCoroutine(WaitActionEnd()); } }
/// <summary> /// Called after the current node or the index of the current dialogue entry has changed. /// </summary> /// <remarks> /// Trigger events according to the current game state and how it is changed /// </remarks> /// <param name="nodeChanged"></param> /// <param name="dialogueChanged"></param> /// <param name="firstEntryOfNode"></param> /// <param name="dialogueStepped"></param> private void UpdateGameState(bool nodeChanged, bool dialogueChanged, bool firstEntryOfNode, bool dialogueStepped) { // Debug.LogFormat("UpdateGameState begin {0} {1} {2}", stepNumFromLastCheckpoint, restrainCheckpoint, forceCheckpoint); if (nodeChanged) { // Debug.Log($"Nova: node changed to {currentNode.name}"); if (firstEntryOfNode) { EnsureCheckpoint(); // always get a checkpoint at the beginning of the node } NodeChanged?.Invoke(new NodeChangedData(currentNode.name)); } if (dialogueChanged) { this.RuntimeAssert(currentIndex >= 0 && currentIndex < currentNode.dialogueEntryCount, "Dialogue index out of range."); if (!firstEntryOfNode && dialogueStepped) { stepNumFromLastCheckpoint++; } var gameStateRestoreEntry = checkpointManager.IsReached(currentNode.name, currentIndex, variables.hash); if (gameStateRestoreEntry == null) { // Tell the checkpoint manager a new dialogue entry has been reached checkpointManager.SetReached(currentNode.name, currentIndex, variables, GetGameStateStepRestoreEntry()); } // Change states after creating or restoring from checkpoint if (shouldSaveRealCheckpoint) { stepNumFromLastCheckpoint = 0; } if (gameStateRestoreEntry != null) { this.RuntimeAssert(stepNumFromLastCheckpoint == gameStateRestoreEntry.stepNumFromLastCheckpoint, $"StepNumFromLastCheckpoint mismatch: {stepNumFromLastCheckpoint} {gameStateRestoreEntry.stepNumFromLastCheckpoint}"); this.RuntimeAssert(restrainCheckpoint == gameStateRestoreEntry.restrainCheckpointNum, $"RestrainCheckpointNum mismatch: {restrainCheckpoint} {gameStateRestoreEntry.restrainCheckpointNum}"); } if (checkpointRestrained) { restrainCheckpoint--; if (restrainCheckpoint == 1) { Debug.LogWarning($"Nova: restrainCheckpoint reaches 1"); } } // As the action for this dialogue will be re-run, it's fine to just reset forceCheckpoint to false forceCheckpoint = false; DialogueWillChange?.Invoke(); state = State.ActionRunning; lastVariablesHashBeforeAction = variables.hash; currentDialogueEntry = currentNode.GetDialogueEntryAt(currentIndex); currentDialogueEntry.ExecuteAction(); StartCoroutine(WaitActionEnd(gameStateRestoreEntry != null)); } // Debug.LogFormat("UpdateGameState end {0} {1} {2} {3}", stepNumFromLastCheckpoint, restrainCheckpoint, forceCheckpoint, currentDialogueEntry?.displayData.FormatNameDialogue()); }