public NPCConversation Create(DialogueManager dialogueManager) { // Build a new quiz. This will result in regenerating new questions from any randomized pools GenerateQuizInstance(); // Create the callback that is called after any option is answered UnityAction OptionSelectedFunctor(int questionIndex, int optionIndex) { return(() => currentQuiz.AnswerQuestion(questionIndex, optionIndex)); } // Say the conversation that corresponds to the grade that the player got on the quiz void SayResponse() { // Destroy any previous response if (currentResponse) { Destroy(currentResponse); } // Instantiate a new response currentResponse = response.Get(CurrentQuiz.Grade).InstantiateAndSay(); // If we should requiz when we fail, then we must say the quiz after the response if (requizOnFail && CurrentQuiz.Grade != QuizGrade.Excellent) { SayQuizConversationNext(); } // If we will not requiz, then invoke my conversation ended event when this conversation is done else { // Set the quiz on the reports data to the quiz that we just finished GameManager.Instance.NotebookUI.Data.Reports.SetQuiz(LevelID.Current(), currentQuiz); // Invoke the quiz conversation ended event when the response is over currentResponse.OnConversationEnded(onConversationEnded.Invoke); } } // Try to get an npc conversation. If it exists, destroy it and add a new one NPCConversation conversation = gameObject.GetComponent <NPCConversation>(); if (conversation) { #if UNITY_EDITOR DestroyImmediate(conversation); #else Destroy(conversation); #endif } conversation = gameObject.AddComponent <NPCConversation>(); // Create the conversation to be edited here in the code EditableConversation editableConversation = new EditableConversation(); EditableSpeechNode previousSpeechNode = null; // A list of all nodes added to the conversation List <EditableConversationNode> nodes = new List <EditableConversationNode>(); // Loop over every question and add speech and option nodes for each for (int i = 0; i < currentQuiz.RuntimeTemplate.Questions.Length; i++) { // Cache the current question QuizQuestion question = currentQuiz.RuntimeTemplate.Questions[i]; // Create a new speech node EditableSpeechNode currentSpeechNode = CreateSpeechNode(conversation, editableConversation, question.Question, 0, i * 300, i == 0, null); nodes.Add(currentSpeechNode); // If a previous speech node exists, then make the options on the previous node // point to the speech on the current node if (previousSpeechNode != null) { foreach (EditableOptionNode option in previousSpeechNode.Options) { option.Speech.SetSpeech(currentSpeechNode); } } // Add an option node for each quiz option for (int j = 0; j < question.Options.Length; j++) { // Get the current option QuizOption option = question.Options[j]; // Create a new option node with the same label as the quiz option EditableOptionNode optionNode = CreateOptionNode(conversation, editableConversation, option.Label, j * 220, (i * 300) + 100); currentSpeechNode.AddOption(optionNode); nodes.Add(optionNode); // Create a dummy node. It is used to invoke events UnityAction optionCallback = OptionSelectedFunctor(i, j); EditableSpeechNode dummyNode = CreateSpeechNode(conversation, editableConversation, string.Empty, j * 220, (i * 300) + 200, false, optionCallback); nodes.Add(dummyNode); // Make the dummy node advance immediately dummyNode.AdvanceDialogueAutomatically = true; dummyNode.AutoAdvanceShouldDisplayOption = false; dummyNode.TimeUntilAdvance = 0f; // Make the option node point to the dummy node optionNode.SetSpeech(dummyNode); } // Update previous speech node to current before resuming previousSpeechNode = currentSpeechNode; } // Create the end of quiz node EditableSpeechNode endOfQuiz = CreateSpeechNode(conversation, editableConversation, endOfQuizText, 0, currentQuiz.RuntimeTemplate.Questions.Length * 300, false, SayResponse); nodes.Add(endOfQuiz); // If a previous speech node exists, // then make its options point to the end of quiz node if (previousSpeechNode != null) { foreach (EditableOptionNode option in previousSpeechNode.Options) { option.Speech.SetSpeech(endOfQuiz); } } // Have all the nodes register their UIDs (whatever the frick THAT means) foreach (EditableConversationNode node in nodes) { node.RegisterUIDs(); } // Serialize the editable conversation back into the NPCConversation and return the result conversation.RuntimeSave(editableConversation); return(conversation); }
public void OnValidate() { if (text == null || !tryParseConversation) { return; } tryParseConversation = false; // try parsing once GameObject gameObject = new GameObject("New Conversation"); gameObject.transform.parent = transform; NPCConversation NPCConversation = gameObject.AddComponent <NPCConversation>(); // Load in id and icon info Dictionary <string, Sprite> idToIconDictionary = new Dictionary <string, Sprite>(); if (iconIDInput.Length > 0) { foreach (var pair in iconIDInput) { idToIconDictionary.Add(pair.id, pair.icon); } } // Preprocess string toParse = text.text; EditableConversation conversation = new EditableConversation(); string[] nodeTexts = toParse.Split('\n'); // Initialize root node EditableSpeechNode root = new EditableSpeechNode(); root.Text = nodeTexts[0].Substring(nodeTexts[0].IndexOf(':', 1) + 1).Trim(); root.Name = defaultName; root.Icon = defaultIcon; string iconID = nodeTexts[0].Substring(1, nodeTexts[0].IndexOf(':', 1) - 1); if (idToIconDictionary.ContainsKey(iconID)) { root.Icon = idToIconDictionary[iconID]; NPCConversation.GetNodeData(NPCConversation.CurrentIDCounter).Icon = root.Icon; } root.ID = NPCConversation.CurrentIDCounter++; root.TMPFont = defaultFont; root.EditorInfo.isRoot = true; conversation.SpeechNodes.Add(root); bool previousNodeIsSpeech = true; EditableSpeechNode previousSpeech = root; List <EditableOptionNode> previousOptions = new List <EditableOptionNode>(); List <EditableConversationNode> nodes = new List <EditableConversationNode>(); nodes.Add(root); for (int i = 1; i < nodeTexts.Length; i++) { string currentText = nodeTexts[i]; if (currentText.Length == 0) { continue; } EditableConversationNode node; // First char is a colon, this is a speech if (currentText[0] == ':') { EditableSpeechNode speechNode = new EditableSpeechNode(); speechNode.Name = defaultName; // text enclosed by colons is id of the icon iconID = currentText.Substring(1, currentText.IndexOf(':', 1) - 1); if (idToIconDictionary.ContainsKey(iconID)) { speechNode.Icon = idToIconDictionary[iconID]; NPCConversation.GetNodeData(NPCConversation.CurrentIDCounter).Icon = speechNode.Icon; } else { // unknown id speechNode.Icon = defaultIcon; } // connect previous nodes to speech if (previousNodeIsSpeech) { speechNode.parents.Add(previousSpeech); previousSpeech.SetSpeech(speechNode); } else { // Connect previous immediate options to node foreach (var option in previousOptions) { speechNode.parents.Add(option); option.SetSpeech(speechNode); } previousOptions.Clear(); } previousNodeIsSpeech = true; previousSpeech = speechNode; conversation.SpeechNodes.Add(speechNode); node = speechNode; } else { EditableOptionNode optionNode = new EditableOptionNode(); optionNode.parents.Add(previousSpeech); previousSpeech.AddOption(optionNode); previousNodeIsSpeech = false; previousOptions.Add(optionNode); conversation.Options.Add(optionNode); node = optionNode; } // Common info node.EditorInfo.yPos = 100 * i; node.Text = currentText.Substring(currentText.IndexOf(':', 1) + 1).Trim(); node.TMPFont = defaultFont; node.ID = NPCConversation.CurrentIDCounter++; nodes.Add(node); } foreach (EditableConversationNode node in nodes) { node.RegisterUIDs(); } NPCConversation.Serialize(conversation); }