/// <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);
            }
        }
Example #5
0
        /// <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);
                }
            }
        }