private void AddEntryToSelection(DialogueEntry entry) { newSelectedLink = null; currentEntry = entry; multinodeSelection.nodes.Add(entry); UpdateEntrySelection(); }
/// <summary> /// Initializes a new Subtitle. /// </summary> /// <param name="speakerInfo">Speaker info.</param> /// <param name="listenerInfo">Listener info.</param> /// <param name="formattedText">Formatted text.</param> /// <param name="sequence">Sequence.</param> /// <param name="responseMenuSequence">Response menu sequence.</param> /// <param name="dialogueEntry">Dialogue entry.</param> public Subtitle(CharacterInfo speakerInfo, CharacterInfo listenerInfo, FormattedText formattedText, string sequence, string responseMenuSequence, DialogueEntry dialogueEntry) { this.speakerInfo = speakerInfo; this.listenerInfo = listenerInfo; this.formattedText = formattedText; this.sequence = sequence; this.responseMenuSequence = responseMenuSequence; this.dialogueEntry = dialogueEntry; this.entrytag = null; CheckVariableInputPrompt(); }
void Update() { string history = PixelCrushers.DialogueSystem.DialogueLua.GetVariable("DialogueEntryRecords_" + conversation).asString; string[] fields = history.Split(';'); var numRecords = (fields.Length > 0) ? PixelCrushers.DialogueSystem.Tools.StringToInt(fields[0]) : 0; //Debug.Log( conversation + "has" + fields[0] + " records."); if (numRecords > 0) { int conversationID = PixelCrushers.DialogueSystem.Tools.StringToInt(fields[fields.Length - 3]); int entryID = PixelCrushers.DialogueSystem.Tools.StringToInt(fields[fields.Length - 2]); //Debug.Log("Last record is [" + conversationID + ":" + entryID + "] -- " + history); PixelCrushers.DialogueSystem.DialogueEntry entry = PixelCrushers.DialogueSystem.DialogueManager.masterDatabase.GetDialogueEntry(conversationID, entryID); if (entry != null) { GetComponent <TextMeshProUGUI>().text = entry.DialogueText; } } }
private DialogueEntry AddNewDialogueEntry(DialogueEntry originalEntry, string dialogueText, int partNum, bool trimWhitespace) { var newEntry = new DialogueEntry(); newEntry.id = GetHighestDialogueEntryID() + 1; newEntry.conversationID = originalEntry.conversationID; newEntry.isRoot = originalEntry.isRoot; newEntry.isGroup = originalEntry.isGroup; newEntry.nodeColor = originalEntry.nodeColor; newEntry.delaySimStatus = originalEntry.delaySimStatus; newEntry.falseConditionAction = originalEntry.falseConditionAction; newEntry.conditionsString = string.Equals(originalEntry.falseConditionAction, "Passthrough") ? originalEntry.conditionsString : string.Empty; newEntry.userScript = string.Empty; newEntry.fields = new List <Field>(); foreach (var field in originalEntry.fields) { if (string.IsNullOrEmpty(field.title)) { continue; } string fieldValue = field.value; bool isSplittable = (field.title.StartsWith(DialogueSystemFields.Sequence) || (field.type == FieldType.Localization)) && !string.IsNullOrEmpty(field.value) && field.value.Contains("|"); if (isSplittable) { string[] substrings = field.value.Split(new char[] { '|' }); if (partNum < substrings.Length) { fieldValue = trimWhitespace ? substrings[partNum].Trim() : substrings[partNum].Trim(); } } newEntry.fields.Add(new Field(field.title, fieldValue, field.type)); } newEntry.DialogueText = dialogueText; dialogueEntries.Add(newEntry); return(newEntry); }
/// <summary> /// Gets the text of the dialogue entry that a link points to. /// </summary> /// <returns> /// The text of the link's destination dialogue entry, or <c>null</c> if the link is invalid. /// </returns> /// <param name='link'> /// The link to follow. /// </param> public string GetLinkText(Link link) { DialogueEntry entry = GetDialogueEntry(link); return((entry == null) ? string.Empty : entry.responseButtonText); }
/// <summary> /// Initializes a new Subtitle. /// </summary> /// <param name="speakerInfo">Speaker info.</param> /// <param name="listenerInfo">Listener info.</param> /// <param name="entryActorsInfo">Info about all actors in entry.</param> /// <param name="formattedText">Formatted text.</param> /// <param name="sequence">Sequence.</param> /// <param name="responseMenuSequence">Response menu sequence.</param> /// <param name="dialogueEntry">Dialogue entry.</param> public Subtitle(CharacterInfo speakerInfo, CharacterInfo listenerInfo, List <CharacterInfo> entryActorsInfo, FormattedText formattedText, string sequence, string responseMenuSequence, DialogueEntry dialogueEntry) { this.speakerInfo = speakerInfo; this.listenerInfo = listenerInfo; this.entryActorsInfo = entryActorsInfo.Select(x => x).ToList(); this.formattedText = formattedText; this.sequence = sequence; this.responseMenuSequence = responseMenuSequence; this.dialogueEntry = dialogueEntry; this.entrytag = null; CheckVariableInputPrompt(); }
private Link NewLink(DialogueEntry origin, DialogueEntry destination, ConditionPriority priority = ConditionPriority.Normal) { Link newLink = new Link(); newLink.originConversationID = origin.conversationID; newLink.originDialogueID = origin.id; newLink.destinationConversationID = destination.conversationID; newLink.destinationDialogueID = destination.id; newLink.isConnector = (origin.conversationID != destination.conversationID); newLink.priority = priority; return newLink; }
private void SplitEntryAtPipes(int originalEntryIndex, string dialogueText) { // Split by Dialogue Text: string[] substrings = dialogueText.Split(new char[] { '|' }); DialogueEntry originalEntry = dialogueEntries[originalEntryIndex]; originalEntry.DefaultDialogueText = substrings[0]; List <Link> originalOutgoingLinks = originalEntry.outgoingLinks; ConditionPriority priority = ((originalOutgoingLinks != null) && (originalOutgoingLinks.Count > 0)) ? originalOutgoingLinks[0].priority : ConditionPriority.Normal; DialogueEntry currentEntry = originalEntry; // Split Menu Text: string[] menuTextSubstrings = originalEntry.DefaultMenuText.Split(new char[] { '|' }); // Split Audio Files: string audioFilesText = originalEntry.AudioFiles; audioFilesText = ((audioFilesText != null) && (audioFilesText.Length >= 2)) ? audioFilesText.Substring(1, audioFilesText.Length - 2) : string.Empty; string[] audioFiles = audioFilesText.Split(new char[] { ';' }); currentEntry.AudioFiles = string.Format("[{0}]", new System.Object[] { (audioFiles.Length > 0) ? audioFiles[0] : string.Empty }); // Create new dialogue entries for the split parts: int i = 1; while (i < substrings.Length) { DialogueEntry newEntry = AddNewDialogueEntry(originalEntry, substrings[i], i); newEntry.MenuText = (i < menuTextSubstrings.Length) ? menuTextSubstrings[i] : string.Empty; newEntry.AudioFiles = string.Format("[{0}]", new System.Object[] { (i < audioFiles.Length) ? audioFiles[i] : string.Empty }); currentEntry.outgoingLinks = new List <Link>() { NewLink(currentEntry, newEntry, priority) }; currentEntry = newEntry; i++; } // Set the last entry's links to the original outgoing links: currentEntry.outgoingLinks = originalOutgoingLinks; // Fix up the other splittable fields in the original entry: foreach (var field in originalEntry.fields) { if (string.IsNullOrEmpty(field.title)) { continue; } string fieldValue = field.value; bool isSplittable = (field.title.StartsWith("Sequence") || (field.type == FieldType.Localization)) && !string.IsNullOrEmpty(field.value) && field.value.Contains("|"); if (isSplittable) { substrings = field.value.Split(new char[] { '|' }); if (substrings.Length > 1) { fieldValue = substrings[0]; field.value = fieldValue; } } } }
private bool LinkExists(DialogueEntry origin, DialogueEntry destination) { Link link = origin.outgoingLinks.Find(x => ((x.destinationConversationID == destination.conversationID) && (x.destinationDialogueID == destination.id))); return (link != null); }
private string GetLinkText(CharacterType characterType, DialogueEntry entry) { return((characterType == CharacterType.NPC) ? entry.SubtitleText : entry.ResponseButtonText); }
private void EvaluateLinksAtPriority(ConditionPriority priority, DialogueEntry entry, List <Response> npcResponses, List <Response> pcResponses, List <DialogueEntry> visited, bool stopAtFirstValid = false) { if (entry != null) { for (int ol = 0; ol < entry.outgoingLinks.Count; ol++) { var link = entry.outgoingLinks[ol]; DialogueEntry destinationEntry = m_database.GetDialogueEntry(link); if ((destinationEntry != null) && (/*(destinationEntry.conditionPriority == priority) ||*/ (link.priority == priority))) // Note: Only observe link priority. Why does Chat Mapper even have conditionPriority? { CharacterType characterType = m_database.GetCharacterType(destinationEntry.ActorID); Lua.Run("thisID = " + destinationEntry.id); bool isValid = Lua.IsTrue(destinationEntry.conditionsString, DialogueDebug.logInfo, m_allowLuaExceptions) && ((isDialogueEntryValid == null) || isDialogueEntryValid(destinationEntry)); if (isValid || (m_includeInvalidEntries && (characterType == CharacterType.PC))) { // Condition is true (or blank), so add this link: if (destinationEntry.isGroup) { // For groups, evaluate their links (after running the group node's Lua code and OnExecute() event): if (DialogueDebug.logInfo) { Debug.Log(string.Format("{0}: Add Group ({1}): ID={2}:{3} '{4}' ({5})", new System.Object[] { DialogueDebug.Prefix, GetActorName(m_database.GetActor(destinationEntry.ActorID)), link.destinationConversationID, link.destinationDialogueID, destinationEntry.Title, isValid })); } Lua.Run(destinationEntry.userScript, DialogueDebug.logInfo, m_allowLuaExceptions); destinationEntry.onExecute.Invoke(); for (int i = (int)ConditionPriority.High; i >= 0; i--) { int originalResponseCount = npcResponses.Count + pcResponses.Count;; EvaluateLinksAtPriority((ConditionPriority)i, destinationEntry, npcResponses, pcResponses, visited); if ((npcResponses.Count + pcResponses.Count) > originalResponseCount) { break; } } } else { // For regular entries, just add them: if (DialogueDebug.logInfo) { Debug.Log(string.Format("{0}: Add Link ({1}): ID={2}:{3} '{4}' ({5})", new System.Object[] { DialogueDebug.Prefix, GetActorName(m_database.GetActor(destinationEntry.ActorID)), link.destinationConversationID, link.destinationDialogueID, GetLinkText(characterType, destinationEntry), isValid })); } if (characterType == CharacterType.NPC) { // Add NPC response: npcResponses.Add(new Response(FormattedText.Parse(destinationEntry.subtitleText, m_database.emphasisSettings), destinationEntry, isValid)); } else { // Add PC response, wrapping old responses in em tags if specified: string text = destinationEntry.responseButtonText; if (m_emTagForOldResponses != EmTag.None) { string simStatus = Lua.Run(string.Format("return Conversation[{0}].Dialog[{1}].SimStatus", new System.Object[] { destinationEntry.conversationID, destinationEntry.id })).asString; bool isOldResponse = string.Equals(simStatus, DialogueLua.WasDisplayed); if (isOldResponse) { text = string.Format("[em{0}]{1}[/em{0}]", (int)m_emTagForOldResponses, text); } } if (m_emTagForInvalidResponses != EmTag.None) { if (!isValid) { text = string.Format("[em{0}]{1}[/em{0}]", (int)m_emTagForInvalidResponses, text); } } pcResponses.Add(new Response(FormattedText.Parse(text, m_database.emphasisSettings), destinationEntry, isValid)); DialogueLua.MarkDialogueEntryOffered(destinationEntry); } } if (stopAtFirstValid) { return; } } else { // Condition is false, so block or pass through according to destination entry's setting: if (LinkUtility.IsPassthroughOnFalse(destinationEntry)) { if (DialogueDebug.logInfo) { Debug.Log(string.Format("{0}: Passthrough on False Link ({1}): ID={2}:{3} '{4}' Condition='{5}'", new System.Object[] { DialogueDebug.Prefix, GetActorName(m_database.GetActor(destinationEntry.ActorID)), link.destinationConversationID, link.destinationDialogueID, GetLinkText(characterType, destinationEntry), destinationEntry.conditionsString })); } List <Response> linkNpcResponses = new List <Response>(); List <Response> linkPcResponses = new List <Response>(); EvaluateLinks(destinationEntry, linkNpcResponses, linkPcResponses, visited); npcResponses.AddRange(linkNpcResponses); pcResponses.AddRange(linkPcResponses); } else { if (DialogueDebug.logInfo) { Debug.Log(string.Format("{0}: Block on False Link ({1}): ID={2}:{3} '{4}' Condition='{5}'", new System.Object[] { DialogueDebug.Prefix, GetActorName(m_database.GetActor(destinationEntry.ActorID)), link.destinationConversationID, link.destinationDialogueID, GetLinkText(characterType, destinationEntry), destinationEntry.conditionsString })); } } } } } } }
private void EvaluateLinksAtPriority(ConditionPriority priority, DialogueEntry entry, List<Response> npcResponses, List<Response> pcResponses, List<DialogueEntry> visited, bool stopAtFirstValid = false) { if (entry != null) { foreach (Link link in entry.outgoingLinks) { DialogueEntry destinationEntry = database.GetDialogueEntry(link); if ((destinationEntry != null) && ((destinationEntry.conditionPriority == priority) || (link.priority == priority))) { CharacterType characterType = database.GetCharacterType(destinationEntry.ActorID); bool isValid = Lua.IsTrue(destinationEntry.conditionsString, DialogueDebug.LogInfo, allowLuaExceptions) && ((IsDialogueEntryValid == null) || IsDialogueEntryValid(destinationEntry)); if (isValid || includeInvalidEntries) { // Condition is true (or blank), so add this link: if (destinationEntry.isGroup) { // For groups, evaluate their links (after running the group node's Lua code): if (DialogueDebug.LogInfo) Debug.Log(string.Format("{0}: Add Group ({1}): ID={2}:{3} '{4}' ({5})", new System.Object[] { DialogueDebug.Prefix, GetActorName(database.GetActor(destinationEntry.ActorID)), link.destinationConversationID, link.destinationDialogueID, destinationEntry.Title, isValid })); Lua.Run(destinationEntry.userScript, DialogueDebug.LogInfo, allowLuaExceptions); for (int i = (int) ConditionPriority.High; i >= 0; i--) { int originalResponseCount = npcResponses.Count + pcResponses.Count;; EvaluateLinksAtPriority((ConditionPriority) i, destinationEntry, npcResponses, pcResponses, visited); if ((npcResponses.Count + pcResponses.Count) > originalResponseCount) break; } } else { // For regular entries, just add them: if (DialogueDebug.LogInfo) Debug.Log(string.Format("{0}: Add Link ({1}): ID={2}:{3} '{4}' ({5})", new System.Object[] { DialogueDebug.Prefix, GetActorName(database.GetActor(destinationEntry.ActorID)), link.destinationConversationID, link.destinationDialogueID, GetLinkText(characterType, destinationEntry), isValid })); if (characterType == CharacterType.NPC) { // Add NPC response: npcResponses.Add(new Response(FormattedText.Parse(destinationEntry.SubtitleText, database.emphasisSettings), destinationEntry, isValid)); } else { // Add PC response, wrapping old responses in em tags if specified: string text = destinationEntry.ResponseButtonText; if (emTagForOldResponses != EmTag.None) { string simStatus = Lua.Run(string.Format("return Conversation[{0}].Dialog[{1}].SimStatus", new System.Object[] { destinationEntry.conversationID, destinationEntry.id })).AsString; bool isOldResponse = string.Equals(simStatus, "WasDisplayed"); if (isOldResponse) text = string.Format("[em{0}]{1}[/em{0}]", (int) emTagForOldResponses, text); } pcResponses.Add(new Response(FormattedText.Parse(text, database.emphasisSettings), destinationEntry, isValid)); DialogueLua.MarkDialogueEntryOffered(destinationEntry); } } if (stopAtFirstValid) return; } else { // Condition is false, so block or pass through according to destination entry's setting: if (LinkTools.IsPassthroughOnFalse(destinationEntry)) { if (DialogueDebug.LogInfo) Debug.Log(string.Format("{0}: Passthrough on False Link ({1}): ID={2}:{3} '{4}' Condition='{5}'", new System.Object[] { DialogueDebug.Prefix, GetActorName(database.GetActor(destinationEntry.ActorID)), link.destinationConversationID, link.destinationDialogueID, GetLinkText(characterType, destinationEntry), destinationEntry.conditionsString })); List<Response> linkNpcResponses = new List<Response>(); List<Response> linkPcResponses = new List<Response>(); EvaluateLinks(destinationEntry, linkNpcResponses, linkPcResponses, visited); npcResponses.AddRange(linkNpcResponses); pcResponses.AddRange(linkPcResponses); } else { if (DialogueDebug.LogInfo) Debug.Log(string.Format("{0}: Block on False Link ({1}): ID={2}:{3} '{4}' Condition='{5}'", new System.Object[] { DialogueDebug.Prefix, GetActorName(database.GetActor(destinationEntry.ActorID)), link.destinationConversationID, link.destinationDialogueID, GetLinkText(characterType, destinationEntry), destinationEntry.conditionsString })); } } } } } }
/// <summary> /// Evaluates a dialogue entry's links. Evaluation follows the same rules as Chat Mapper: /// - Links are evaluated from highest to lowest priority; once links are found in a /// priority level, evaluation stops. Lower priority links aren't evaluated. /// - If a link evaluates <c>false</c> and the false condition action is "Passthrough", /// the link's children are evaluated. /// </summary> /// <param name='entry'> /// Dialogue entry. /// </param> /// <param name='npcResponses'> /// Links from the entry that are NPC responses are added to this list. /// </param> /// <param name='pcResponses'> /// Links from the entry that are PC responses are added to this list. /// </param> /// <param name='visited'> /// Keeps track of links that have already been visited so we don't loop back on ourselves /// and get frozen in an infinite loop. /// </param> private void EvaluateLinks(DialogueEntry entry, List<Response> npcResponses, List<Response> pcResponses, List<DialogueEntry> visited, bool stopAtFirstValid = false) { if ((entry != null) && !visited.Contains(entry)) { visited.Add(entry); for (int i = (int) ConditionPriority.High; i >= 0; i--) { EvaluateLinksAtPriority((ConditionPriority) i, entry, npcResponses, pcResponses, visited, stopAtFirstValid); if ((npcResponses.Count > 0) || (pcResponses.Count > 0)) return; } } }
private void CheckSequenceField(DialogueEntry entry) { if (string.IsNullOrEmpty(entry.Sequence) && !string.IsNullOrEmpty(entry.VideoFile)) { if (DialogueDebug.LogWarnings) Debug.LogWarning(string.Format("{0}: Dialogue entry '{1}' Video File field is assigned but Sequence is blank. Cutscenes now use Sequence field.", new System.Object[] { DialogueDebug.Prefix, entry.DialogueText })); } }
/// <summary> /// "Follows" a dialogue entry and returns its full conversation state. This method updates /// the Lua environment (marking the entry as visited) and evaluates all links from the /// dialogue entry and records valid links in the state. /// </summary> /// <returns> /// The state representing the dialogue entry. /// </returns> /// <param name='entry'> /// The dialogue entry to "follow." /// </param> public ConversationState GetState(DialogueEntry entry) { return GetState(entry, true); }
/// <summary> /// "Follows" a dialogue entry and returns its full conversation state. This method updates /// the Lua environment (marking the entry as visited). If includeLinks is <c>true</c>, /// it evaluates all links from the dialogue entry and records valid links in the state. /// </summary> /// <returns>The state.</returns> /// <param name="entry">The dialogue entry to "follow."</param> /// <param name="includeLinks">If set to <c>true</c> records all links from the dialogue entry whose conditiosn are true.</param> /// <param name="stopAtFirstValid">If set to <c>true</c> stops including at the first valid link.</param> public ConversationState GetState(DialogueEntry entry, bool includeLinks, bool stopAtFirstValid = false) { if (entry != null) { DialogueLua.MarkDialogueEntryDisplayed(entry); SetDialogTable(entry.conversationID); Lua.Run(entry.userScript, DialogueDebug.LogInfo, allowLuaExceptions); CharacterInfo actorInfo = GetCharacterInfo(entry.ActorID); CharacterInfo listenerInfo = GetCharacterInfo(entry.ConversantID); FormattedText formattedText = FormattedText.Parse(entry.SubtitleText, database.emphasisSettings); CheckSequenceField(entry); string entrytag = database.GetEntrytag(entry.conversationID, entry.id, entrytagFormat); Subtitle subtitle = new Subtitle(actorInfo, listenerInfo, formattedText, entry.Sequence, entry.ResponseMenuSequence, entry, entrytag); List<Response> npcResponses = new List<Response>(); List<Response> pcResponses = new List<Response>(); if (includeLinks) EvaluateLinks(entry, npcResponses, pcResponses, new List<DialogueEntry>(), stopAtFirstValid); return new ConversationState(subtitle, npcResponses.ToArray(), pcResponses.ToArray(), entry.isGroup); } else { return null; } }
public DialogueEntry CreateDialogueEntry(int id, int conversationID, string title) { DialogueEntry entry = new DialogueEntry(); entry.fields = CreateFields(dialogueEntryFields); entry.id = id; entry.conversationID = conversationID; entry.Title = title; return entry; }
private static int GetEntryBarkPriority(DialogueEntry entry) { return((entry == null) ? 0 : Field.LookupInt(entry.fields, DialogueSystemFields.Priority)); }
private string GetLinkText(CharacterType characterType, DialogueEntry entry) { return (characterType == CharacterType.NPC) ? entry.SubtitleText : entry.ResponseButtonText; }
/// <summary> /// Initializes a new Response. /// </summary> /// <param name='formattedText'> /// Formatted text. /// </param> /// <param name='destinationEntry'> /// Destination entry. /// </param> public Response(FormattedText formattedText, DialogueEntry destinationEntry, bool enabled = true) { this.formattedText = formattedText; this.destinationEntry = destinationEntry; this.enabled = enabled; }
private void RemoveEntryFromSelection(DialogueEntry entry) { newSelectedLink = null; multinodeSelection.nodes.Remove(entry); if (multinodeSelection.nodes.Count == 0) { currentEntry = null; } else { currentEntry = multinodeSelection.nodes[multinodeSelection.nodes.Count-1]; } UpdateEntrySelection(); }
/// <summary> /// "Follows" a dialogue entry and returns its full conversation state. This method updates /// the Lua environment (marking the entry as visited) and evaluates all links from the /// dialogue entry and records valid links in the state. /// </summary> /// <returns> /// The state representing the dialogue entry. /// </returns> /// <param name='entry'> /// The dialogue entry to "follow." /// </param> public ConversationState GetState(DialogueEntry entry) { return(GetState(entry, true)); }
private void ShowNodeContextMenu(DialogueEntry entry) { GenericMenu contextMenu = new GenericMenu(); contextMenu.AddItem(new GUIContent("Create Child Node"), false, AddChildCallback, entry); contextMenu.AddItem(new GUIContent("Make Link"), false, MakeLinkCallback, entry); if ((multinodeSelection.nodes.Count > 1) && (multinodeSelection.nodes.Contains(entry))) { contextMenu.AddItem(new GUIContent("Duplicate"), false, DuplicateMultipleEntriesCallback, entry); contextMenu.AddItem(new GUIContent("Delete"), false, DeleteMultipleEntriesCallback, entry); } else if (entry == startEntry) { contextMenu.AddDisabledItem(new GUIContent("Duplicate")); contextMenu.AddDisabledItem(new GUIContent("Delete")); } else { contextMenu.AddItem(new GUIContent("Duplicate"), false, DuplicateEntryCallback, entry); contextMenu.AddItem(new GUIContent("Delete"), false, DeleteEntryCallback, entry); } contextMenu.AddItem(new GUIContent("Arrange Nodes"), false, ArrangeNodesCallback, entry); contextMenu.ShowAsContext(); }
/// <summary> /// Copy constructor. /// </summary> /// <param name="sourceEntry">Source entry.</param> public DialogueEntry(DialogueEntry sourceEntry) { this.id = sourceEntry.id; this.fields = Field.CopyFields(sourceEntry.fields); this.conversationID = sourceEntry.conversationID; this.isRoot = sourceEntry.isRoot; this.isGroup = sourceEntry.isGroup; this.nodeColor = sourceEntry.nodeColor; this.delaySimStatus = sourceEntry.delaySimStatus; this.falseConditionAction = sourceEntry.falseConditionAction; this.conditionPriority = ConditionPriority.Normal; this.outgoingLinks = CopyLinks(sourceEntry.outgoingLinks); this.conditionsString = sourceEntry.conditionsString; this.userScript = sourceEntry.userScript; }
/// <summary> /// Adds the conversation dialogue entry. Starting in Chat Mapper 1.6, XML entries don't /// include the conversation ID, so we set it manually here. /// </summary> /// <param name='chatMapperEntry'> /// Chat Mapper entry. /// </param> private void AddConversationDialogueEntry(ChatMapper.DialogEntry chatMapperEntry) { DialogueEntry entry = new DialogueEntry(chatMapperEntry); entry.conversationID = id; dialogueEntries.Add(entry); }
private void MakeLinkCallback(object o) { linkSourceEntry = o as DialogueEntry; isMakingLink = (linkSourceEntry != null); }
/// <summary> /// Marks a dialogue entry as untouched, by setting the Lua variable /// <c>Conversation[#].Dialog[#].SimStatus="Untouched"</c>, where <c>#</c> is the /// conversation and/or dialogue entry ID. The ConversationModel marks entries /// displayed when they are used in a conversation. /// </summary> /// <param name='dialogueEntry'> /// Dialogue entry to mark. /// </param> public static void MarkDialogueEntryUntouched(DialogueEntry dialogueEntry) { MarkDialogueEntry(dialogueEntry, "Untouched"); }
private void SetCurrentEntry(DialogueEntry entry) { newSelectedLink = null; if (entry != currentEntry) ResetLuaWizards(); currentEntry = entry; multinodeSelection.nodes.Clear(); multinodeSelection.nodes.Add(entry); UpdateEntrySelection(); }
/// <summary> /// Initializes a new Response. /// </summary> /// <param name='formattedText'> /// Formatted text. /// </param> /// <param name='destinationEntry'> /// Destination entry. /// </param> public Response(FormattedText formattedText, DialogueEntry destinationEntry, bool enabled = true) { this.formattedText = formattedText; this.destinationEntry = destinationEntry; this.enabled = enabled; }
private void UpdateRuntimeConversationsTab() { if (DialogueManager.HasInstance) { var newConversationState = DialogueManager.CurrentConversationState; if (newConversationState != currentConversationState) { currentConversationState = newConversationState; currentRuntimeEntry = (currentConversationState != null && currentConversationState.subtitle != null) ? currentConversationState.subtitle.dialogueEntry : null; Repaint(); } } }
/// <summary> /// Marks a dialogue entry as displayed, by setting the Lua variable /// <c>Conversation[#].Dialog[#].SimStatus="WasDisplayed"</c>, where <c>#</c> is the /// conversation and/or dialogue entry ID. The ConversationInterpreter marks entries /// displayed when they are used in a conversation. /// </summary> /// <param name='dialogueEntry'> /// Dialogue entry to mark. /// </param> public static void MarkDialogueEntryDisplayed(DialogueEntry dialogueEntry) { MarkDialogueEntry(dialogueEntry, "WasDisplayed"); }
private DialogueEntry AddNewDialogueEntry(DialogueEntry originalEntry, string dialogueText, int partNum) { DialogueEntry newEntry = new DialogueEntry(); newEntry.id = GetHighestDialogueEntryID() + 1; newEntry.conversationID = originalEntry.conversationID; newEntry.isRoot = originalEntry.isRoot; newEntry.isGroup = originalEntry.isGroup; newEntry.nodeColor = originalEntry.nodeColor; newEntry.delaySimStatus = originalEntry.delaySimStatus; newEntry.falseConditionAction = originalEntry.falseConditionAction; newEntry.conditionsString = string.Equals(originalEntry.falseConditionAction, "Passthrough") ? originalEntry.conditionsString : string.Empty; newEntry.userScript = string.Empty; newEntry.fields = new List<Field>(); foreach (var field in originalEntry.fields) { if (string.IsNullOrEmpty(field.title)) continue; string fieldValue = field.value; bool isSplittable = (field.title.StartsWith("Sequence") || (field.type == FieldType.Localization)) && !string.IsNullOrEmpty(field.value) && field.value.Contains("|"); if (isSplittable) { string[] substrings = field.value.Split(new char[] { '|' }); if (partNum < substrings.Length) { fieldValue = substrings[partNum]; } } newEntry.fields.Add(new Field(field.title, fieldValue, field.type)); } newEntry.DefaultDialogueText = dialogueText; dialogueEntries.Add (newEntry); return newEntry; }
private void DeleteNodeLinkToDialogueID(DialogueEntry origin, int destinationConversationID, int destinationDialogueID) { if (origin == null) return; Link link = origin.outgoingLinks.Find(x => (x.destinationConversationID == destinationConversationID) && (x.destinationDialogueID == destinationDialogueID)); if (link == null) return; origin.outgoingLinks.Remove(link); }
/// <summary> /// Attempts to make a character bark. This is a coroutine; you must start it using /// StartCoroutine() or Unity will hang. Shows a line from the named conversation, plays /// the sequence, and sends OnBarkStart/OnBarkEnd messages to the participants. /// </summary> /// <param name='conversationTitle'> /// Title of conversation to pull bark lines from. /// </param> /// <param name='speaker'> /// Speaker performing the bark. /// </param> /// <param name='listener'> /// Listener that the bark is directed to; may be <c>null</c>. /// </param> /// <param name='barkHistory'> /// Bark history used to keep track of the most recent bark so this method can iterate /// through them in a specified order. /// </param> /// <param name='database'> /// The dialogue database to use. If <c>null</c>, uses DialogueManager.MasterDatabase. /// </param> public static IEnumerator Bark(string conversationTitle, Transform speaker, Transform listener, BarkHistory barkHistory, DialogueDatabase database = null) { if (string.IsNullOrEmpty(conversationTitle) && DialogueDebug.LogWarnings) { Debug.Log(string.Format("{0}: Bark (speaker={1}, listener={2}): conversation title is blank", new System.Object[] { DialogueDebug.Prefix, speaker, listener }), speaker); } if ((speaker == null) && DialogueDebug.LogWarnings) { Debug.LogWarning(string.Format("{0}: Bark (speaker={1}, listener={2}): '{3}' speaker is null", new System.Object[] { DialogueDebug.Prefix, speaker, listener, conversationTitle })); } if (string.IsNullOrEmpty(conversationTitle) || (speaker == null)) { yield break; } IBarkUI barkUI = speaker.GetComponentInChildren(typeof(IBarkUI)) as IBarkUI; if ((barkUI == null) && DialogueDebug.LogWarnings) { Debug.LogWarning(string.Format("{0}: Bark (speaker={1}, listener={2}): '{3}' speaker has no bark UI", new System.Object[] { DialogueDebug.Prefix, speaker, listener, conversationTitle }), speaker); } ConversationModel conversationModel = new ConversationModel(database ?? DialogueManager.MasterDatabase, conversationTitle, speaker, listener, DialogueManager.AllowLuaExceptions, DialogueManager.IsDialogueEntryValid); ConversationState firstState = conversationModel.FirstState; if ((firstState == null) && DialogueDebug.LogWarnings) { Debug.LogWarning(string.Format("{0}: Bark (speaker={1}, listener={2}): '{3}' has no START entry", new System.Object[] { DialogueDebug.Prefix, speaker, listener, conversationTitle }), speaker); } if (!firstState.HasAnyResponses && DialogueDebug.LogWarnings) { Debug.LogWarning(string.Format("{0}: Bark (speaker={1}, listener={2}): '{3}' has no valid bark at this time", new System.Object[] { DialogueDebug.Prefix, speaker, listener, conversationTitle }), speaker); } if ((firstState != null) && firstState.HasAnyResponses) { try { InformParticipants("OnBarkStart", speaker, listener); Response[] responses = firstState.HasNPCResponse ? firstState.npcResponses : firstState.pcResponses; int index = (barkHistory ?? new BarkHistory(BarkOrder.Random)).GetNextIndex(responses.Length); DialogueEntry barkEntry = responses[index].destinationEntry; if ((barkEntry == null) && DialogueDebug.LogWarnings) { Debug.LogWarning(string.Format("{0}: Bark (speaker={1}, listener={2}): '{3}' bark entry is null", DialogueDebug.Prefix, speaker, listener, conversationTitle), speaker); } if (barkEntry != null) { ConversationState barkState = conversationModel.GetState(barkEntry, false); if (firstState.HasNPCResponse) { CharacterInfo tempInfo = barkState.subtitle.speakerInfo; barkState.subtitle.speakerInfo = barkState.subtitle.listenerInfo; barkState.subtitle.listenerInfo = tempInfo; } if (DialogueDebug.LogInfo) { Debug.Log(string.Format("{0}: Bark (speaker={1}, listener={2}): '{3}'", DialogueDebug.Prefix, speaker, listener, barkState.subtitle.formattedText.text), speaker); } // Show the bark subtitle: if (((barkUI == null) || !(barkUI as MonoBehaviour).enabled) && DialogueDebug.LogWarnings) { Debug.LogWarning(string.Format("{0}: Bark (speaker={1}, listener={2}): '{3}' bark UI is null or disabled", new System.Object[] { DialogueDebug.Prefix, speaker, listener, barkState.subtitle.formattedText.text }), speaker); } if ((barkUI != null) && (barkUI as MonoBehaviour).enabled) { barkUI.Bark(barkState.subtitle); } // Run Lua: if (!string.IsNullOrEmpty(barkState.subtitle.dialogueEntry.userScript)) { Lua.Run(barkState.subtitle.dialogueEntry.userScript, DialogueDebug.LogInfo, false); } // Play the sequence: Sequencer sequencer = null; if (!string.IsNullOrEmpty(barkState.subtitle.sequence)) { sequencer = DialogueManager.PlaySequence(barkState.subtitle.sequence, speaker, listener, false, false); sequencer.entrytag = barkState.subtitle.entrytag; } LastSequencer = sequencer; while (((sequencer != null) && sequencer.IsPlaying) || ((barkUI != null) && barkUI.IsPlaying)) { yield return(null); } if (sequencer != null) { GameObject.Destroy(sequencer); } } } finally { InformParticipants("OnBarkEnd", speaker, listener); } } }
private void DrawConversationSectionNodeStyle() { if (Application.isPlaying && DialogueManager.HasInstance) { currentConversationState = DialogueManager.CurrentConversationState; currentRuntimeEntry = (currentConversationState != null && currentConversationState.subtitle != null) ? currentConversationState.subtitle.dialogueEntry : null; } else { currentRuntimeEntry = null; } CheckDialogueTreeGUIStyles(); if (nodeEditorDeleteCurrentConversation) DeleteCurrentConversationInNodeEditor(); if (inspectorSelection == null) inspectorSelection = currentConversation; DrawCanvas(); DrawNodeEditorTopControls(); HandleEmptyCanvasEvents(); HandleKeyEvents(); }
private static void ExportSubtree(DialogueDatabase database, string language, Dictionary <int, string> actorNames, Dictionary <int, int> numLinksToEntry, List <DialogueEntry> visited, DialogueEntry entry, int siblingIndex, StreamWriter file) { if (entry == null) { return; } visited.Add(entry); if (entry.id > 0) { var omit = omitNoneOrContinueEntries && (entry.Sequence == "None()" || entry.Sequence == "Continue()"); var show = !omit; // Write this entry (the root of the subtree). // Write entry ID if necessary: if (siblingIndex == -1) { if (show) { file.WriteLine(string.Format("\tUnconnected entry [{0}]:", entry.id)); } if (show) { file.WriteLine(string.Empty); } } else if ((siblingIndex == 0 && !string.IsNullOrEmpty(entry.conditionsString)) || (siblingIndex > 0) || (numLinksToEntry.ContainsKey(entry.id) && numLinksToEntry[entry.id] > 1)) { if (string.IsNullOrEmpty(entry.conditionsString)) { if (show) { file.WriteLine(string.Format("\tEntry [{0}]:", entry.id)); } } else { if (show) { file.WriteLine(string.Format("\tEntry [{0}]: ({1})", entry.id, entry.conditionsString)); } } if (show) { file.WriteLine(string.Empty); } } if (!actorNames.ContainsKey(entry.ActorID)) { Actor actor = database.GetActor(entry.ActorID); actorNames.Add(entry.ActorID, (actor != null) ? actor.Name.ToUpper() : "ACTOR"); } if (show) { file.WriteLine(string.Format("\t\t\t\t{0}", actorNames[entry.ActorID])); } var description = Field.LookupValue(entry.fields, "Description"); if (!string.IsNullOrEmpty(description)) { if (show) { file.WriteLine(string.Format("\t\t\t({0})", description)); } } var lineText = string.IsNullOrEmpty(language) ? entry.subtitleText : Field.LookupValue(entry.fields, language); if (entry.isGroup) { // Group entries use Title: lineText = Field.LookupValue(entry.fields, "Title"); lineText = !string.IsNullOrEmpty(lineText) ? ("(" + lineText + ")") : "(Group entry; no dialogue)"; } if (show) { file.WriteLine(string.Format("\t\t{0}", lineText)); } if (show) { file.WriteLine(string.Empty); } } // Handle link summary: if (entry.outgoingLinks.Count == 0) { file.WriteLine("\t\t\t\t[END]"); file.WriteLine(string.Empty); } else if (entry.outgoingLinks.Count > 1) { var s = "\tResponses: "; var first = true; for (int i = 0; i < entry.outgoingLinks.Count; i++) { if (!first) { s += ", "; } first = false; var link = entry.outgoingLinks[i]; if (link.destinationConversationID == entry.conversationID) { s += "[" + link.destinationDialogueID + "]"; } else { var destConversation = database.GetConversation(link.destinationConversationID); if (destConversation != null) { s += "[" + destConversation.Title.ToUpper() + ":" + link.destinationDialogueID + "]"; } else { s += "[Other Conversation]"; } } } file.WriteLine(s); file.WriteLine(string.Empty); } // Follow each outgoing link as a subtree: for (int i = 0; i < entry.outgoingLinks.Count; i++) { var child = database.GetDialogueEntry(entry.outgoingLinks[i]); if (!visited.Contains(child)) { ExportSubtree(database, language, actorNames, numLinksToEntry, visited, child, i, file); } } }
private void DrawEntryConnectors(DialogueEntry entry) { if (entry == null) return; foreach (var link in entry.outgoingLinks) { if (link.destinationConversationID == currentConversation.id) { // Only show connection if within same conv. DialogueEntry destination = currentConversation.dialogueEntries.Find(e => e.id == link.destinationDialogueID); if (destination != null) { Vector3 start = new Vector3(entry.canvasRect.center.x, entry.canvasRect.center.y, 0); Vector3 end = new Vector3(destination.canvasRect.center.x, destination.canvasRect.center.y, 0); Color connectorColor = (link == selectedLink) ? new Color(0.5f, 0.75f, 1f, 1f) : Color.white; if (entry == currentRuntimeEntry) { connectorColor = IsValidRuntimeLink(link) ? Color.green : Color.red; } DrawLink(start, end, connectorColor); HandleConnectorEvents(link, start, end); } } } }
/// <summary> /// Gets the entrytaglocal string (localized version) of a dialogue entry. /// </summary> /// <param name="conversation">Dialogue entry's conversation.</param> /// <param name="entry">Dialogue entry.</param> /// <param name="entrytagFormat">Entrytag format.</param> /// <returns>Localized entrytag.</returns> public string GetEntrytaglocal(Conversation conversation, DialogueEntry entry, EntrytagFormat entrytagFormat) { return(GetEntrytag(conversation, entry, entrytagFormat) + "_" + Localization.language); }
private void DrawEntryNode(DialogueEntry entry) { bool isSelected = multinodeSelection.nodes.Contains(entry); Styles.Color nodeColor = (entry.id == 0) ? Styles.Color.Orange : database.IsPlayerID(entry.ActorID) ? Styles.Color.Blue : Styles.Color.Gray; if (entry == currentRuntimeEntry) { nodeColor = Styles.Color.Green; } string nodeLabel = GetDialogueEntryNodeText(entry); if (showActorNames) { GUIStyle nodeStyle = new GUIStyle(Styles.GetNodeStyle("node", nodeColor, isSelected)); nodeStyle.padding.top = 23; nodeStyle.padding.bottom = 0; GUI.Box(entry.canvasRect, nodeLabel, nodeStyle); } else { GUI.Box(entry.canvasRect, nodeLabel, Styles.GetNodeStyle("node", nodeColor, isSelected)); } }
/// <summary> /// Attempts to make a character bark. This is a coroutine; you must start it using /// StartCoroutine() or Unity will hang. Shows a line from the named conversation, plays /// the sequence, and sends OnBarkStart/OnBarkEnd messages to the participants. /// </summary> /// <param name='conversationTitle'> /// Title of conversation to pull bark lines from. /// </param> /// <param name='speaker'> /// Speaker performing the bark. /// </param> /// <param name='listener'> /// Listener that the bark is directed to; may be <c>null</c>. /// </param> /// <param name='barkHistory'> /// Bark history used to keep track of the most recent bark so this method can iterate /// through them in a specified order. /// </param> /// <param name='database'> /// The dialogue database to use. If <c>null</c>, uses DialogueManager.MasterDatabase. /// </param> public static IEnumerator Bark(string conversationTitle, Transform speaker, Transform listener, BarkHistory barkHistory, DialogueDatabase database = null, bool stopAtFirstValid = false) { if (CheckDontBarkDuringConversation()) { yield break; } bool barked = false; if (string.IsNullOrEmpty(conversationTitle) && DialogueDebug.logWarnings) { Debug.Log(string.Format("{0}: Bark (speaker={1}, listener={2}): conversation title is blank", new System.Object[] { DialogueDebug.Prefix, speaker, listener }), speaker); } if (speaker == null) { speaker = DialogueManager.instance.FindActorTransformFromConversation(conversationTitle, "Actor"); } if ((speaker == null) && DialogueDebug.logWarnings) { Debug.LogWarning(string.Format("{0}: Bark (speaker={1}, listener={2}): '{3}' speaker is null", new System.Object[] { DialogueDebug.Prefix, speaker, listener, conversationTitle })); } if (string.IsNullOrEmpty(conversationTitle) || (speaker == null)) { yield break; } IBarkUI barkUI = DialogueActor.GetBarkUI(speaker); //speaker.GetComponentInChildren(typeof(IBarkUI)) as IBarkUI; if ((barkUI == null) && DialogueDebug.logWarnings) { Debug.LogWarning(string.Format("{0}: Bark (speaker={1}, listener={2}): '{3}' speaker has no bark UI", new System.Object[] { DialogueDebug.Prefix, speaker, listener, conversationTitle }), speaker); } var firstValid = stopAtFirstValid || ((barkHistory == null) ? false : barkHistory.order == (BarkOrder.FirstValid)); ConversationModel conversationModel = new ConversationModel(database ?? DialogueManager.masterDatabase, conversationTitle, speaker, listener, DialogueManager.allowLuaExceptions, DialogueManager.isDialogueEntryValid, -1, firstValid); ConversationState firstState = conversationModel.firstState; if ((firstState == null) && DialogueDebug.logWarnings) { Debug.LogWarning(string.Format("{0}: Bark (speaker={1}, listener={2}): '{3}' has no START entry", new System.Object[] { DialogueDebug.Prefix, speaker, listener, conversationTitle }), speaker); } if ((firstState != null) && !firstState.hasAnyResponses && DialogueDebug.logWarnings) { Debug.LogWarning(string.Format("{0}: Bark (speaker={1}, listener={2}): '{3}' has no valid bark at this time", new System.Object[] { DialogueDebug.Prefix, speaker, listener, conversationTitle }), speaker); } if ((firstState != null) && firstState.hasAnyResponses) { try { Response[] responses = firstState.hasNPCResponse ? firstState.npcResponses : firstState.pcResponses; int index = (barkHistory ?? new BarkHistory(BarkOrder.Random)).GetNextIndex(responses.Length); DialogueEntry barkEntry = responses[index].destinationEntry; if ((barkEntry == null) && DialogueDebug.logWarnings) { Debug.LogWarning(string.Format("{0}: Bark (speaker={1}, listener={2}): '{3}' bark entry is null", new System.Object[] { DialogueDebug.Prefix, speaker, listener, conversationTitle }), speaker); } if (barkEntry != null) { var priority = GetEntryBarkPriority(barkEntry); if (priority < GetSpeakerCurrentBarkPriority(speaker)) { if (DialogueDebug.logInfo) { Debug.Log(string.Format("{0}: Bark (speaker={1}, listener={2}): '{3}' currently barking a higher priority bark", new System.Object[] { DialogueDebug.Prefix, speaker, listener, conversationTitle }), speaker); } yield break; } SetSpeakerCurrentBarkPriority(speaker, priority); barked = true; InformParticipants(DialogueSystemMessages.OnBarkStart, speaker, listener); ConversationState barkState = conversationModel.GetState(barkEntry, false); if (barkState == null) { if (DialogueDebug.logWarnings) { Debug.LogWarning(string.Format("{0}: Bark (speaker={1}, listener={2}): '{3}' can't find a valid dialogue entry", new System.Object[] { DialogueDebug.Prefix, speaker, listener, conversationTitle }), speaker); } yield break; } if (firstState.hasNPCResponse) { CharacterInfo tempInfo = barkState.subtitle.speakerInfo; barkState.subtitle.speakerInfo = barkState.subtitle.listenerInfo; barkState.subtitle.listenerInfo = tempInfo; } if (DialogueDebug.logInfo) { Debug.Log(string.Format("{0}: Bark (speaker={1}, listener={2}): '{3}'", new System.Object[] { DialogueDebug.Prefix, speaker, listener, barkState.subtitle.formattedText.text }), speaker); } InformParticipantsLine(DialogueSystemMessages.OnBarkLine, speaker, barkState.subtitle); // Show the bark subtitle: if (((barkUI == null) || !(barkUI as MonoBehaviour).enabled) && DialogueDebug.logWarnings) { Debug.LogWarning(string.Format("{0}: Bark (speaker={1}, listener={2}): '{3}' bark UI is null or disabled", new System.Object[] { DialogueDebug.Prefix, speaker, listener, barkState.subtitle.formattedText.text }), speaker); } if ((barkUI != null) && (barkUI as MonoBehaviour).enabled) { barkUI.Bark(barkState.subtitle); } // Start the sequence: var sequencer = PlayBarkSequence(barkState.subtitle, speaker, listener); LastSequencer = sequencer; // Wait until the sequence and subtitle are done: while (((sequencer != null) && sequencer.isPlaying) || ((barkUI != null) && barkUI.isPlaying)) { yield return(null); } if (sequencer != null) { GameObject.Destroy(sequencer); } } } finally { if (barked) { InformParticipants(DialogueSystemMessages.OnBarkEnd, speaker, listener); SetSpeakerCurrentBarkPriority(speaker, 0); } } } }
private void DrawNewLinkConnector() { if (isMakingLink && (linkSourceEntry != null)) { Vector3 start = new Vector3(linkSourceEntry.canvasRect.center.x, linkSourceEntry.canvasRect.center.y, 0); if ((linkTargetEntry != null) && Event.current.isMouse) { if (!linkTargetEntry.canvasRect.Contains(Event.current.mousePosition)) { linkTargetEntry = null; } } Vector3 end = (linkTargetEntry != null) ? new Vector3(linkTargetEntry.canvasRect.center.x, linkTargetEntry.canvasRect.center.y, 0) : new Vector3(Event.current.mousePosition.x, Event.current.mousePosition.y, 0); DrawLink(start, end, Color.white); } }
/// <summary> /// Forces the next state to link to a specific dialogue entry instead of its designed links. /// </summary> public void ForceNextStateToLinkToEntry(DialogueEntry entry) { forceLinkEntry = entry; }
private void DuplicateEntry(DialogueEntry entry) { if (entry == null || currentConversation == null) return; DialogueEntry newEntry = new DialogueEntry(entry); newEntry.id = GetNextDialogueEntryID(); foreach (var link in newEntry.outgoingLinks) { link.originDialogueID = newEntry.id; } currentConversation.dialogueEntries.Add(newEntry); newEntry.canvasRect.x = entry.canvasRect.x + 10f; newEntry.canvasRect.y = entry.canvasRect.y + entry.canvasRect.height + AutoHeightBetweenNodes; ApplyDialogueEntryTemplate(newEntry.fields); currentEntry = newEntry; inspectorSelection = currentEntry; InitializeDialogueTree(); ResetDialogueEntryText(); Repaint(); }
/// <summary> /// Returns whether the DialogueEntry passes through to evaluate children when its /// condition is false. /// </summary> /// <returns> /// <c>true</c> if this instance is passthrough on false; otherwise, <c>false</c>. /// </returns> /// <param name='entry'> /// The DialogueEntry to check. /// </param> public static bool IsPassthroughOnFalse(DialogueEntry entry) { return(string.Equals(entry.falseConditionAction, "Passthrough")); }
private void FinishMakingLink() { if ((linkSourceEntry != null) && (linkTargetEntry != null) && (linkSourceEntry != linkTargetEntry) && !LinkExists(linkSourceEntry, linkTargetEntry)) { Link link = new Link(); link.originConversationID = currentConversation.id; link.originDialogueID = linkSourceEntry.id; link.destinationConversationID = currentConversation.id; link.destinationDialogueID = linkTargetEntry.id; linkSourceEntry.outgoingLinks.Add(link); InitializeDialogueTree(); ResetDialogueEntryText(); Repaint(); } isMakingLink = false; linkSourceEntry = null; linkTargetEntry = null; }
private void EvaluateLinksAtPriority(ConditionPriority priority, DialogueEntry entry, List <Response> npcResponses, List <Response> pcResponses, List <DialogueEntry> visited) { if (entry != null) { foreach (Link link in entry.outgoingLinks) { DialogueEntry destinationEntry = database.GetDialogueEntry(link); if ((destinationEntry != null) && ((destinationEntry.conditionPriority == priority) || (link.priority == priority))) { CharacterType characterType = database.GetCharacterType(destinationEntry.ActorID); bool isValid = Lua.IsTrue(destinationEntry.conditionsString, DialogueDebug.LogInfo, allowLuaExceptions) && ((IsDialogueEntryValid == null) || IsDialogueEntryValid(destinationEntry)); if (isValid) { // Condition is true (or blank), so add this link: if (destinationEntry.isGroup) { // For groups, evaluate their links (after running the group node's Lua code): if (DialogueDebug.LogInfo) { Debug.Log(string.Format("{0}: Add Group ({1}): ID={2}:{3} '{4}'", new System.Object[] { DialogueDebug.Prefix, GetActorName(database.GetActor(destinationEntry.ActorID)), link.destinationConversationID, link.destinationDialogueID, destinationEntry.Title })); } Lua.Run(destinationEntry.userScript, DialogueDebug.LogInfo, allowLuaExceptions); for (int i = (int)ConditionPriority.High; i >= 0; i--) { int originalResponseCount = npcResponses.Count + pcResponses.Count;; EvaluateLinksAtPriority((ConditionPriority)i, destinationEntry, npcResponses, pcResponses, visited); if ((npcResponses.Count + pcResponses.Count) > originalResponseCount) { break; } } } else { // For regular entries, just add them: if (DialogueDebug.LogInfo) { Debug.Log(string.Format("{0}: Add Link ({1}): ID={2}:{3} '{4}'", new System.Object[] { DialogueDebug.Prefix, GetActorName(database.GetActor(destinationEntry.ActorID)), link.destinationConversationID, link.destinationDialogueID, GetLinkText(characterType, destinationEntry) })); } if (characterType == CharacterType.NPC) { // Add NPC response: npcResponses.Add(new Response(FormattedText.Parse(destinationEntry.SubtitleText, database.emphasisSettings), destinationEntry)); } else { // Add PC response, wrapping old responses in em tags if specified: string text = destinationEntry.ResponseButtonText; if (emTagForOldResponses != EmTag.None) { string simStatus = Lua.Run(string.Format("return Conversation[{0}].Dialog[{1}].SimStatus", new System.Object[] { destinationEntry.conversationID, destinationEntry.id })).AsString; bool isOldResponse = string.Equals(simStatus, "WasDisplayed"); if (isOldResponse) { text = string.Format("[em{0}]{1}[/em{0}]", (int)emTagForOldResponses, text); } } pcResponses.Add(new Response(FormattedText.Parse(text, database.emphasisSettings), destinationEntry)); DialogueLua.MarkDialogueEntryOffered(destinationEntry); } } } else { // Condition is false, so block or pass through according to destination entry's setting: if (LinkTools.IsPassthroughOnFalse(destinationEntry)) { if (DialogueDebug.LogInfo) { Debug.Log(string.Format("{0}: Passthrough on False Link ({1}): ID={2}:{3} '{4}' Condition='{5}'", new System.Object[] { DialogueDebug.Prefix, GetActorName(database.GetActor(destinationEntry.ActorID)), link.destinationConversationID, link.destinationDialogueID, GetLinkText(characterType, destinationEntry), destinationEntry.conditionsString })); } List <Response> linkNpcResponses = new List <Response>(); List <Response> linkPcResponses = new List <Response>(); EvaluateLinks(destinationEntry, linkNpcResponses, linkPcResponses, visited); npcResponses.AddRange(linkNpcResponses); pcResponses.AddRange(linkPcResponses); } else { if (DialogueDebug.LogInfo) { Debug.Log(string.Format("{0}: Block on False Link ({1}): ID={2}:{3} '{4}' Condition='{5}'", new System.Object[] { DialogueDebug.Prefix, GetActorName(database.GetActor(destinationEntry.ActorID)), link.destinationConversationID, link.destinationDialogueID, GetLinkText(characterType, destinationEntry), destinationEntry.conditionsString })); } } } } } } }
private void HandleNodeEvents(DialogueEntry entry) { switch (Event.current.type) { case EventType.mouseDown: if (entry.canvasRect.Contains(Event.current.mousePosition)) { if (IsRightMouseButtonEvent()) { currentEntry = entry; ShowNodeContextMenu(entry); Event.current.Use(); } else if (Event.current.button == LeftMouseButton) { newSelectedLink = null; if (isMakingLink) { FinishMakingLink(); } else { nodeToDrag = entry; dragged = false; if (!IsShiftDown() && ((multinodeSelection.nodes.Count <= 1) || !multinodeSelection.nodes.Contains(entry))) { SetCurrentEntry(entry); } } Event.current.Use(); } } break; case EventType.mouseUp: if (Event.current.button == LeftMouseButton) { if (!isMakingLink && entry.canvasRect.Contains(Event.current.mousePosition)) { newSelectedLink = null; if (isLassoing) { FinishLasso(); } else if (IsShiftDown()) { if (multinodeSelection.nodes.Contains(entry)) { RemoveEntryFromSelection(entry); } else { AddEntryToSelection(entry); } } else { if (!(dragged && (multinodeSelection.nodes.Count > 1))) { SetCurrentEntry(entry); } } nodeToDrag = null; dragged = false; Event.current.Use(); } } break; case EventType.mouseDrag: if ((entry == nodeToDrag)) { dragged = true; DragNodes(multinodeSelection.nodes); Event.current.Use(); } break; } if (isMakingLink && Event.current.isMouse) { if (entry.canvasRect.Contains(Event.current.mousePosition)) { linkTargetEntry = entry; } } }
// Update scene with information from entry public virtual void ChangeScene(DialogueEntry entry, List <CharacterInfo> entryActorsInfo) { // do nothing }
/// <summary> /// Initializes a new Response. /// </summary> /// <param name='formattedText'> /// Formatted text. /// </param> /// <param name='destinationEntry'> /// Destination entry. /// </param> public Response(FormattedText formattedText, DialogueEntry destinationEntry) { this.formattedText = formattedText; this.destinationEntry = destinationEntry; }