/// <summary> /// Reads the DialogueEntries section. DialogueEntry is not a subclass of Asset, /// so we can't reuse the ReadAssets() code above. /// </summary> /// <param name="database">Dialogue database.</param> private void ReadDialogueEntries(DialogueDatabase database, bool add) { Debug.Log("Dialogue System CSV Importer: " + (add ? "Reading" : "Skipping") + " DialogueEntries section"); // Read field names and types: string[] fieldNames = GetValues(GetNextSourceLine()); string[] fieldTypes = GetValues(GetNextSourceLine()); // Keep reading until we reach another asset type heading or end of file: int safeguard = 0; while (!(IsSourceAtEnd() || AssetTypeHeadings.Contains(GetFirstField(PeekNextSourceLine())))) { safeguard++; if (safeguard > MaxIterations) { break; } string[] values = GetValues(GetNextSourceLine()); if (add) { // Create the dialogue entry: DialogueEntry entry = new DialogueEntry(); entry.fields = new List <Field>(); // We can ignore value[0] (entrytag). entry.conversationID = Tools.StringToInt(values[1]); entry.id = Tools.StringToInt(values[2]); entry.ActorID = Tools.StringToInt(values[3]); entry.ConversantID = Tools.StringToInt(values[4]); entry.Title = values[5]; entry.MenuText = values[6]; entry.DialogueText = values[7]; entry.isGroup = Tools.StringToBool(values[8]); entry.falseConditionAction = values[9]; entry.conditionPriority = ConditionPriorityUtility.StringToConditionPriority(values[10]); entry.conditionsString = values[11]; entry.userScript = values[12]; // Read the remaining values and assign them to the asset's fields: ReadAssetFields(fieldNames, fieldTypes, DialogueEntrySpecialValues, values, entry.fields); // Convert canvasRect field to entry position on node editor canvas: entry.UseCanvasRectField(); // Finally, add the asset: var conversation = database.GetConversation(entry.conversationID); if (conversation == null) { throw new InvalidDataException(string.Format("Conversation {0} referenced in entry {1} not found", entry.conversationID, entry.id)); } conversation.dialogueEntries.Add(entry); } } }
public static void FixConversationsLinkedToFirstEntry(DialogueDatabase database, bool resetNodePositions = false) { // If there's a link to a conversation's START entry, swap the participants. // This increases the likelihood that the NPC will "speak" the START line // so it doesn't present to the player as a blank response button. // NOTE: This also handles prefs.resetNodePositions if set. try { // First identify conversations whose START entries to fix: var conversationsToFix = new List <int>(); foreach (var conversation in database.conversations) { foreach (var entry in conversation.dialogueEntries) { // Also handle prefs.resetNodePositions: if (resetNodePositions) { entry.canvasRect = new Rect(0, 0, DialogueEntry.CanvasRectWidth, DialogueEntry.CanvasRectHeight); } // Check links: foreach (var link in entry.outgoingLinks) { if (link.destinationDialogueID == 0) // START { if (!conversationsToFix.Contains(link.destinationConversationID)) { conversationsToFix.Add(link.destinationConversationID); } } } } } // Then fix them: foreach (var conversationID in conversationsToFix) { var entry = database.GetConversation(conversationID).GetFirstDialogueEntry(); var temp = entry.ActorID; entry.ActorID = entry.ConversantID; entry.ConversantID = temp; } } catch (System.Exception e) { Debug.LogWarning("Error fixing up linked conversation: " + e.Message); } }
/// <summary> /// Initializes a new ConversationModel. /// </summary> /// <param name="database">The database to use.</param> /// <param name="title">The title of the conversation in the database.</param> /// <param name="actor">Actor.</param> /// <param name="conversant">Conversant.</param> /// <param name="allowLuaExceptions">If set to <c>true</c> allow Lua exceptions.</param> /// <param name="isDialogueEntryValid">Is dialogue entry valid.</param> /// <param name="initialDialogueEntryID">Initial dialogue entry ID (-1 to start at beginning).</param> /// <param name="stopAtFirstValid">If set to <c>true</c> stop at first valid link from the initial entry.</param> /// <param name="skipExecution">IF set to <c>true</c>, doesn't run the Lua Script or OnExecute event on the initial entry.</param> public ConversationModel(DialogueDatabase database, string title, Transform actor, Transform conversant, bool allowLuaExceptions, IsDialogueEntryValidDelegate isDialogueEntryValid, int initialDialogueEntryID = -1, bool stopAtFirstValid = false, bool skipExecution = false) { this.m_allowLuaExceptions = allowLuaExceptions; this.m_database = database; this.isDialogueEntryValid = isDialogueEntryValid; DisplaySettings displaySettings = DialogueManager.displaySettings; if (displaySettings != null) { if (displaySettings.cameraSettings != null) { m_entrytagFormat = displaySettings.cameraSettings.entrytagFormat; } if (displaySettings.inputSettings != null) { m_emTagForOldResponses = displaySettings.inputSettings.emTagForOldResponses; m_emTagForInvalidResponses = displaySettings.inputSettings.emTagForInvalidResponses; m_includeInvalidEntries = displaySettings.GetIncludeInvalidEntries(); } } Conversation conversation = database.GetConversation(title); if (conversation != null) { SetParticipants(conversation, actor, conversant); if (initialDialogueEntryID == -1) { firstState = GetState(conversation.GetFirstDialogueEntry(), true, stopAtFirstValid, skipExecution); FixFirstStateSequence(); } else { firstState = GetState(conversation.GetDialogueEntry(initialDialogueEntryID), true, stopAtFirstValid, skipExecution); } } else { firstState = null; if (DialogueDebug.logErrors) { Debug.LogWarning(string.Format("{0}: Conversation '{1}' not found in database.", new System.Object[] { DialogueDebug.Prefix, title })); } } }
/// <summary> /// Reads the DialogueEntries section. DialogueEntry is not a subclass of Asset, /// so we can't reuse the ReadAssets() code above. /// </summary> /// <param name="database">Dialogue database.</param> private void ReadDialogueEntries(DialogueDatabase database) { Debug.Log("Reading DialogueEntries section"); // Read field names and types: string[] fieldNames = GetValues(GetNextSourceLine()); string[] fieldTypes = GetValues(GetNextSourceLine()); // Keep reading until we reach another asset type heading or end of file: while (!(IsSourceAtEnd() || AssetTypeHeadings.Contains(PeekNextSourceLine()))) { string[] values = GetValues(GetNextSourceLine()); // Create the dialogue entry: DialogueEntry entry = new DialogueEntry(); entry.fields = new List <Field>(); // We can ignore value[0] (entrytag). entry.conversationID = Tools.StringToInt(values[1]); entry.id = Tools.StringToInt(values[2]); entry.ActorID = Tools.StringToInt(values[3]); entry.ConversantID = Tools.StringToInt(values[4]); entry.Title = values[5]; entry.DefaultMenuText = values[6]; entry.DefaultDialogueText = values[7]; entry.isGroup = Tools.StringToBool(values[8]); entry.falseConditionAction = values[9]; entry.conditionPriority = ConditionPriorityTools.StringToConditionPriority(values[10]); entry.conditionsString = values[11]; entry.userScript = values[12]; // Read the remaining values and assign them to the asset's fields: ReadAssetFields(fieldNames, fieldTypes, DialogueEntrySpecialValues, values, entry.fields); // Finally, add the asset: var conversation = database.GetConversation(entry.conversationID); if (conversation == null) { throw new InvalidDataException(string.Format("Conversation {0} referenced in entry {1} not found", entry.conversationID, entry.id)); } conversation.dialogueEntries.Add(entry); } }
/// <summary> /// Initializes a new ConversationModel. /// </summary> /// <param name='database'> /// The database to use. /// </param> /// <param name='title'> /// The title of the conversation in the database. /// </param> /// <param name='actor'> /// Actor. /// </param> /// <param name='conversant'> /// Conversant. /// </param> public ConversationModel(DialogueDatabase database, string title, Transform actor, Transform conversant, bool allowLuaExceptions, IsDialogueEntryValidDelegate isDialogueEntryValid) { this.allowLuaExceptions = allowLuaExceptions; this.database = database; this.IsDialogueEntryValid = isDialogueEntryValid; Conversation conversation = database.GetConversation(title); if (conversation != null) { SetParticipants(conversation, actor, conversant); FirstState = GetState(conversation.GetFirstDialogueEntry()); FixFirstStateSequence(); } else { FirstState = null; if (DialogueDebug.LogErrors) { Debug.LogWarning(string.Format("{0}: Conversation '{1}' not found in database.", new System.Object[] { DialogueDebug.Prefix, title })); } } DisplaySettings displaySettings = DialogueManager.DisplaySettings; if (displaySettings != null) { if (displaySettings.cameraSettings != null) { entrytagFormat = displaySettings.cameraSettings.entrytagFormat; } if (displaySettings.inputSettings != null) { emTagForOldResponses = displaySettings.inputSettings.emTagForOldResponses; } } }
public ConversationOverrideDisplaySettings GetConversationOverrideSettings(ConversationState state) { var conversation = m_database.GetConversation(GetConversationID(state)); return((conversation != null) ? conversation.overrideSettings : null); }
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); } } }