Exemple #1
0
        private IEnumerator UpdateDialogue(bool firstEntryOfNode, bool dialogueStepped, bool fromCheckpoint,
                                           Action onFinish)
        {
            if (!fromCheckpoint)
            {
                // If the following lines of code are put into a new coroutine, one frame's delay will be introduced,
                // so don't do that
                currentDialogueEntry.ExecuteAction(DialogueActionStage.BeforeCheckpoint, isRestoring);
                while (actionPauseLock.isLocked)
                {
                    yield return(null);
                }
            }

            DialogueSaveCheckpoint(firstEntryOfNode, dialogueStepped, out var isReached,
                                   out var isReachedAnyHistory);
            dialogueWillChange.Invoke(new DialogueWillChangeData());

            currentDialogueEntry.ExecuteAction(DialogueActionStage.Default, isRestoring);
            while (actionPauseLock.isLocked)
            {
                yield return(null);
            }

            dialogueChanged.Invoke(new DialogueChangedData(nodeHistory.Last(), currentIndex,
                                                           currentDialogueEntry.GetDisplayData(), new Dictionary <string, VoiceEntry>(voicesNextDialogue),
                                                           isReached, isReachedAnyHistory));

            voicesNextDialogue.Clear();

            currentDialogueEntry.ExecuteAction(DialogueActionStage.AfterDialogue, isRestoring);
            while (actionPauseLock.isLocked)
            {
                yield return(null);
            }

            if (advancedDialogueHelper.GetFallThrough())
            {
                Step(Utils.WrapActionWithParameter <bool>(onFinish));
                yield break;
            }

            var pendingJumpTarget = advancedDialogueHelper.GetJump();

            if (pendingJumpTarget != null)
            {
                var node = flowChartTree.GetNode(pendingJumpTarget);
                this.RuntimeAssert(node != null, $"Node {pendingJumpTarget} not found.");
                MoveToNextNode(node, onFinish);
                yield break;
            }

            onFinish?.Invoke();
        }
Exemple #2
0
 /// <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 the current node and current dialogue index.
 /// This method will execute the action in the new current dialogue entry and informs all game state listeners
 /// Since the action inside the dialogue entry will be executed, this method should not be called twice
 /// if only one update has happen
 /// </remarks>
 private void UpdateGameState()
 {
     currentDialogueEntry = currentNode.GetDialogueEntryAt(currentIndex);
     DialogueWillChange.Invoke();
     currentDialogueEntry.ExecuteAction();
     DialogueChanged.Invoke(
         new DialogueChangedEventData(currentNode.name, currentIndex, currentDialogueEntry.text,
                                      voicesOfNextDialogue));
     voicesOfNextDialogue.Clear();
 }
Exemple #3
0
        /// <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());
            }
        }
Exemple #4
0
        /// <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());
        }