Page 1 of 1

[HOWTO] How To: Simple Fall Back System

Posted: Tue Jan 26, 2021 8:32 pm
by Tony Li
This script is a variation on the Dialogue System's ConversationPositionStack that may be easier to use in many cases. You can add it to the Dialogue Manager, or to a UI Button. If you add it to a UI Button, clicking that button will drop back to the previously recorded fallback position.

The script adds two Lua functions: RecordFallback and GotoFallback.

If you call RecordFallback in a dialogue entry node's Script field, it will record the current position in the conversation onto a stack.

If you call GotoFallback, or if the script is added to a UI Button, it will go back to the top position recorded on the stack.

FallbackButton.cs

Code: Select all

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using PixelCrushers.DialogueSystem;

/// <summary>
/// This is a somewhat simplified version of ConversationPositionStack. 
/// It adds two Lua functions: RecordFallback and GotoFallback.
/// If you call RecordFallback in a dialogue entry node's Script field, it
/// will record the current position in the conversation onto a stack.
/// If you call GotoFallback, or if the script is added to a UI Button,
/// it will go back to the top position recorded on the stack.
/// </summary>
public class FallbackButton : MonoBehaviour
{
    public bool debug = false;

    private static bool registered = false;
    private bool iRegistered = false;
    private bool fallingBack = false;
    private DialogueEntry fallbackEntry;
    private Stack<DialogueEntry> stack = new Stack<DialogueEntry>();

    private void OnEnable()
    {
        // Register the Lua functions:
        if (!registered)
        {
            registered = true;
            iRegistered = true;
            Lua.RegisterFunction("RecordFallback", this, SymbolExtensions.GetMethodInfo(() => RecordFallback()));
            Lua.RegisterFunction("GotoFallback", this, SymbolExtensions.GetMethodInfo(() => FallBack()));
        }

        // Hook up the UI button:
        var button = GetComponent<Button>();
        if (button != null) button.onClick.AddListener(FallBack);
    }

    private void OnDisable()
    {
        if (iRegistered)
        {
            registered = false;
            iRegistered = false;
            Lua.UnregisterFunction("RecordFallback");
            Lua.UnregisterFunction("GotoFallback");
        }
    }

    private void RecordFallback()
    {
        DialogueEntry entry = null;
        if (fallingBack)
        {
            // If we're falling back, record the entry we're falling back to:
            entry = fallbackEntry;
        }
        else
        {
            // Otherwise record the entry whose Script called RecordFallback():
            var state = DialogueManager.currentConversationState;
            entry = state.hasNPCResponse ? state.firstNPCResponse.destinationEntry
                : state.hasPCResponses ? state.pcResponses[0].destinationEntry
                : null;
        }
        if (entry != null)
        {
            if (debug) Debug.Log("Record [" + entry.id + "]: " + entry.subtitleText);
            stack.Push(entry);
        }
    }

    private void FallBack()
    {
        if (stack.Count > 0)
        {
            var entry = stack.Pop();
            if (entry == DialogueManager.currentConversationState.subtitle.dialogueEntry)
            {
                // If we're falling back from a fallback node, assume it has recorded
                // itself onto the top of the stack. We need to pop that off and then
                // pop the next one down to get the actual place to fall back:
                if (stack.Count == 0) return;
                entry = stack.Pop();
            }
            if (debug) Debug.Log("Fall back to [" + entry.id + "]: " + entry.subtitleText);
            fallingBack = true;
            fallbackEntry = entry;
            var state = DialogueManager.conversationModel.GetState(entry);
            fallingBack = false;
            DialogueManager.conversationController.GotoState(state);
        }
    }
}