Beispiel #1
0
    /// <summary>
    /// Handles functionality for right-click context items. Modify this function if you wish to add new
    /// right-click functionality.
    /// </summary>
    public override void ContextCallback(object obj)
    {
        switch (obj.ToString())
        {
        case "questDialogueNode":
            numberOfStates++;
            QuestDialogueNode.Create(new Rect(mousePos.x, mousePos.y, 350, 350), numberOfStates);
            break;

        case "dialogueChoice":
            numberOfChoiceStates++;
            QuestChoiceNode.Create(new Rect(mousePos.x, mousePos.y, 100, 50), numberOfChoiceStates);
            break;

        case "deleteNode":
            Node node = NodeAtPosition(mousePos);
            if (node != null)
            {
                if (node.GetType() == typeof(QuestDialogueNode))
                {
                    numberOfStates--;
                }
                else if (node.GetType() == typeof(DialogueChoiceNode))
                {
                    numberOfChoiceStates--;
                }

                // Find all nodes with higher state values than the deleted node and subtract 1 from their state.
                foreach (Node successorNode in nodeCanvas.nodes)
                {
                    // Ignore choice states
                    if (successorNode.state != -2 && successorNode.state > node.state)
                    {
                        successorNode.state--;
                        successorNode.name = "State " + successorNode.state;
                    }
                }

                _nodeCanvas.nodes.Remove(node);

                if (node is DialogueChoiceNode)
                {
                    _nodeCanvas.choiceNodes.Remove(node);
                    _nodeCanvas.choiceNodeNames.Remove(node.name);
                }

                // Iterate over all the other nodes and update start/final states
                foreach (Node editorNode in Node_Editor.editor.nodeCanvas.nodes)
                {
                    Node_Editor.editor.RecalculateFrom(editorNode);
                }

                node.OnDelete();
            }

            break;
        }
    }
    /// <summary>
    /// sets the input choice node as part of a turn-in or in-progress conversation.
    /// </summary>
    private void SetDialogueTypeChoiceNode()
    {
        QuestChoiceNode temp = (QuestChoiceNode)Inputs[0].connection.body;

        if (temp.turnInQuest)
        {
            turnInQuest = true;
        }
        if (temp.inProgressDialogue)
        {
            inProgressDialogue = true;
        }
    }
    /// <summary>
    /// Creates a new quest choice node.
    /// </summary>
    public new static void Create(Rect NodeRect, int choiceStateNumber)
    {
        QuestChoiceNode node = ScriptableObject.CreateInstance <QuestChoiceNode>();

        node.name                = "Choice State " + choiceStateNumber;
        node.rect                = NodeRect;
        node.originState         = -1; // I just chose -1. I don't think this matters. Will need to enforce that this state has an input though.
        node.state               = -2;
        node.numberOfTransitions = 0;
        node.isStartState        = false;
        node.expanded            = true;

        // Instantiate 9 outputs for the choice selection
        for (int i = 0; i < 9; i++)
        {
            NodeOutput.Create(node, "Dialogue Option " + (i + 1).ToString(), typeof(int));
        }

        // Create input for previous state
        NodeInput.Create(node, "Previous Dialogue State", typeof(int));

        node.Init();
    }
Beispiel #4
0
    /// <summary>
    /// Parses the Dialogue FSM from the node editor and returns a DialgueFSM object.
    /// </summary>
    private DialogueFSM ParseDialogueFromQuest(QuestNodeCanvas questToParse, bool getTurnInQuestDialogue, bool getInProgressDialogue)
    {
        QuestNodeCanvas fsm = questToParse;             // grab each Node Canvas Object, which holds all our states

        DialogueFSM newFSM = new DialogueFSM(-1, 1.0f); // default values for quest dialogue. Probability is always 100% and can happen infinite number of times if the quest is available.

        string initiator = null;                        // the character who initiates this fsm

        // Iterate over every node in the FSM
        foreach (IQuestNode node in fsm.nodes)
        {
            // the boolean parameters act like switches. If we want a specific interaction, we want to ignore nodes that do not meet that interaction's criteria.
            if (!getTurnInQuestDialogue && !getInProgressDialogue && (node.IsTurnInDialogue() || node.IsInProgressDialogue()))
            {
                continue;
            }
            else if (getTurnInQuestDialogue && !node.IsTurnInDialogue())
            {
                continue;
            }
            else if (getInProgressDialogue && !node.IsInProgressDialogue())
            {
                continue;
            }

            if (node.GetType() == typeof(QuestDialogueNode))
            {
                QuestDialogueNode newNode = (QuestDialogueNode)node;

                if (newNode.isStartState)
                {
                    // Assign the initiator to the player if the player initiation toggle has been set on the start state. Otherwise, set it to the npc's name.
                    initiator = newNode.playerInitiatesConversation ? "Player" : newNode.speakers[0].name;
                    newFSM.SetStartState(newNode.state);
                }

                // Separate the style sprite into a body and tail. Note that the body and tail sprites MUST have the same prefix to their names as the original style. For instance, if the original style is "NormalDialogue", then the body and tail must be "NormalDialogueBody" and "NormalDialogueTail".
                List <Sprite> newBodyStyles = new List <Sprite>();
                List <Sprite> newTailStyles = new List <Sprite>();

                for (int j = 0; j < newNode.styles.Count; j++)
                {
                    newBodyStyles.Add(Resources.Load <Sprite>("Sprites/Dialogue/" + newNode.styles[j].name + "Body"));
                    newTailStyles.Add(Resources.Load <Sprite>("Sprites/Dialogue/" + newNode.styles[j].name + "Tail"));
                }

                // Parse data from dialogue node. Note that we are using our characters hash table for the speaker. This might not be necessary, but this should ensure that we are grabbing the instances of the gameobjects that are IN the scene instead of in the editor. I'm not sure if there's a distinction between prefabs in the editor and instantiated prefabs in the scene.
                List <GameObject> newSpeakerList = new List <GameObject>();

                foreach (GameObject character in newNode.speakers)
                {
                    newSpeakerList.Add(speakers[character.name]);
                    newFSM.AddParticipant(speakers[character.name]);
                }

                newFSM.AddQuestState(newSpeakerList, newNode.dialogues, newNode.description, newBodyStyles, newTailStyles, newNode.state, newNode.accept, newNode.reject);

                // Add Transitions for non-choice nodes.
                if (newNode.Outputs[0].connections.Count > 0)
                {
                    // Ignore states that transition to a choice state
                    if (newNode.Outputs[0].connections[0].body.state != -2)
                    {
                        // Note that all states fire on the 0 input. However, choices fire on 1 - 9 inputs. Proceeding through dialogue always occurs using 0 input.
                        newFSM.AddTransition(newNode.state, newNode.Outputs[0].connections[0].body.state, 0);
                    }
                }
                else if (newNode.returnsToChoiceNode)
                {
                    // Iterate over the previous choice node and create transitions for this state to go to any of the choice options on the previous choice node.
                    for (int j = 0; j < newNode.previousChoiceNode.Outputs.Count; j++)
                    {
                        if (newNode.previousChoiceNode.Outputs[j].connections.Count == 0)
                        {
                            continue;
                        }

                        newFSM.AddTransition(newNode.state, newNode.previousChoiceNode.Outputs[j].connections[0].body.state, j + 1);
                    }
                }
                else
                {
                    // handle the final state case. A dialogue node with no output connection must be a final state so it transitions to -1.
                    newFSM.AddTransition(newNode.state, -1, 0);
                }
            }
            else if (node.GetType() == typeof(QuestChoiceNode))
            {
                QuestChoiceNode newNode = (QuestChoiceNode)node;

                // Parse transitions from choice node. Origin state is what leads us to the choice node. It is the state, all dialogue choices come from.
                for (int j = 0; j < newNode.Outputs.Count; j++)
                {
                    if (newNode.Outputs[j].connections.Count > 0)
                    {
                        newFSM.AddTransition(newNode.originState, newNode.Outputs[j].connections[0].body.state, j + 1);
                    }
                }
            }
        }

        // Check and make sure states were added. No states may be added to the FSM if no turn in dialogue options were created.
        if (newFSM.GetStateCount() > 0)
        {
            return(newFSM);
        }
        else
        {
            return(null);
        }
    }