Пример #1
0
        /// <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 Converter: " + (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.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);

                    // 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);
                }
            }
        }
Пример #2
0
        protected bool MatchesVoicePreference(Voice voice, VoicePreference voicePreference)
        {
            var gender        = (voice.Gender == Crosstales.RTVoice.Model.Enum.Gender.FEMALE) ? Gender.Female : Gender.Male; // string.Equals(voice.Gender, "Female", System.StringComparison.OrdinalIgnoreCase) ? Gender.Female : Gender.Male;
            var age           = Tools.StringToInt(voice.Age);
            var matchesName   = string.IsNullOrEmpty(voicePreference.name) || string.Equals(voicePreference.name, voice.Name);
            var matchesGender = (gender == voicePreference.gender);
            var matchesAge    = (voicePreference.minAge <= age && age <= voicePreference.maxAge);

            return(matchesName && matchesGender && matchesAge);
        }
Пример #3
0
        /// <summary>
        /// Reads a section of assets such as Actors, Items, etc.
        /// </summary>
        /// <param name="assets">List of assets to populate.</param>
        /// <typeparam name="T">The type of asset.</typeparam>
        private void ReadAssets <T>(List <T> assets, bool add) where T : Asset, new()
        {
            string typeName       = typeof(T).Name;
            bool   isActorSection = (typeof(T) == typeof(Actor));

            Debug.Log(string.Format("Dialogue System CSV Importer: {0} {1} section", (add ? "Reading" : "Skipping"), typeName));

            // Read field names and types:
            string[] fieldNames = GetValues(GetNextSourceLine());
            string[] fieldTypes = GetValues(GetNextSourceLine());

            // Set up ignore list for values that aren't actual fields:
            List <string> ignore = isActorSection ? ActorSpecialValues : DefaultSpecialValues;

            // 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 asset:
                    T asset = new T();
                    asset.id     = Tools.StringToInt(values[0]);
                    asset.fields = new List <Field>();

                    // Preprocess a couple extra values for actors:
                    if (isActorSection)
                    {
                        FindActorPortraits(asset as Actor, values[1], values[2]);
                    }

                    // Read the remaining values and assign them to the asset's fields:
                    ReadAssetFields(fieldNames, fieldTypes, ignore, values, asset.fields);

                    // If the database already has an old asset with the same ID, delete it first:
                    assets.RemoveAll(a => a.id == asset.id);

                    // Finally, add the asset:
                    assets.Add(asset);
                }
            }
        }
Пример #4
0
        private static ChatMapper.Item ItemToCmp(DialogueSystem.Item item)
        {
            ChatMapper.Item cmpItem = new ChatMapper.Item();
            cmpItem.ID     = item.id;
            cmpItem.Fields = FieldsToCmp(item.fields);
            AddRequiredItemFields(cmpItem.Fields);
            Field entryCount = Field.Lookup(item.fields, "Entry Count");

            if (entryCount != null)
            {
                maxEntryCount = Mathf.Max(maxEntryCount, Tools.StringToInt(entryCount.value));
            }
            return(cmpItem);
        }
Пример #5
0
        public Voice GetVoice(string voiceName, string gender, int minAge, int maxAge)
        {
            var culture         = Localization.Language;
            var availableVoices = string.IsNullOrEmpty(culture) ? Speaker.Voices : Speaker.VoicesForCulture(culture);

            foreach (var availableVoice in availableVoices)
            {
                var matchesName   = string.IsNullOrEmpty(voiceName) || string.Equals(voiceName, availableVoice.Name);
                var matchesGender = string.Equals(gender, availableVoice.Gender.ToString(), System.StringComparison.OrdinalIgnoreCase);
                var age           = Tools.StringToInt(availableVoice.Age);
                var matchesAge    = (minAge == 0 && maxAge == 0) || (minAge <= age && age <= maxAge);
                if (matchesName && matchesGender && matchesAge)
                {
                    return(availableVoice);
                }
            }
            return((availableVoices != null && availableVoices.Count > 0) ? availableVoices[0] : null);
        }
        /// <summary>
        /// Reads the OutgoingLinks section. Again, Link is not a subclass of Asset,
        /// so we can't reuse the ReadAssets() method.
        /// </summary>
        /// <param name="database">Dialogue database.</param>
        private void ReadOutgoingLinks(DialogueDatabase database)
        {
            Debug.Log("Reading OutgoingLinks section");
            GetNextSourceLine();             // Headings
            GetNextSourceLine();             // Types

            // Keep reading until we reach another asset type heading or end of file:
            while (!(IsSourceAtEnd() || AssetTypeHeadings.Contains(PeekNextSourceLine())))
            {
                string[] values = GetValues(GetNextSourceLine());
                var      link   = new Link(Tools.StringToInt(values[0]), Tools.StringToInt(values[1]),
                                           Tools.StringToInt(values[2]), Tools.StringToInt(values[3]));
                var entry = database.GetDialogueEntry(link.originConversationID, link.originDialogueID);
                if (entry == null)
                {
                    throw new InvalidDataException(string.Format("Dialogue entry {0}.{1} referenced in link not found", link.originConversationID, link.originDialogueID));
                }
                entry.outgoingLinks.Add(link);
            }
        }
Пример #7
0
        public void AssignPortraitSprite(AssignSpriteDelegate assignSprite)
        {
            var originalDebugLevel = DialogueDebug.level; // Suppress logging for Lua return Actor[].Current_Portrait.

            DialogueDebug.level = DialogueDebug.DebugLevel.Warning;
            string imageName = DialogueLua.GetActorField(Name, DialogueSystemFields.CurrentPortrait).asString;

            DialogueDebug.level = originalDebugLevel;
            if (string.IsNullOrEmpty(imageName))
            {
                assignSprite(GetPortraitSprite(1));
            }
            else if (imageName.StartsWith("pic="))
            {
                assignSprite(GetPortraitSprite(Tools.StringToInt(imageName.Substring("pic=".Length))));
            }
            else
            {
                DialogueManager.LoadAsset(imageName, typeof(Texture2D),
                                          (asset) => { assignSprite(UITools.CreateSprite(asset as Texture2D)); });
            }
        }
Пример #8
0
        /// @endcond

        /// <summary>
        /// Gets the value with the specified string key. Returns a standard type such as
        /// <c>string</c>, <c>float</c>, <c>bool</c>, or <c>null</c>. If the value
        /// is a table, it returns a LuaTableWrapper around it.
        /// </summary>
        /// <param name="key">Key.</param>
        public object this[string key]
        {
            get
            {
                if (luaTable == null)
                {
                    if (DialogueDebug.logErrors)
                    {
                        Debug.LogError(string.Format("{0}: Lua table is null; lookup[{1}] failed", new object[] { DialogueDebug.Prefix, key }));
                    }
                    return(null);
                }
                LuaValue luaValue = LuaNil.Nil;
                if (luaTable.Length > 0)
                {
                    // Get list value:
                    luaValue = luaTable.GetValue(Tools.StringToInt(key));
                }
                else
                {
                    // Get dictionary value:
                    LuaValue luaValueKey = luaTable.GetKey(key);
                    if (luaValueKey == LuaNil.Nil)
                    {
                        //--- Suppressed: if (DialogueDebug.LogErrors) Debug.LogError(string.Format("{0}: Lua table does not contain key [{1}]", new string[] { DialogueDebug.Prefix, key }));
                        return(null);
                    }
                    luaValue = luaTable.GetValue(key);
                }
                if (luaValue is LuaTable)
                {
                    return(new LuaTableWrapper(luaValue as LuaTable));
                }
                else
                {
                    return(LuaInterpreterExtensions.LuaValueToObject(luaValue));
                }
            }
        }
Пример #9
0
        public Sprite GetPortraitSprite()
        {
            //--- Was: return UITools.GetSprite(portrait, spritePortrait);
            //--- Instead, check for override set by SetPortrait():
            var originalDebugLevel = DialogueDebug.level; // Suppress logging for Lua return Actor[].Current_Portrait.

            DialogueDebug.level = DialogueDebug.DebugLevel.Warning;
            string imageName = DialogueLua.GetActorField(Name, DialogueSystemFields.CurrentPortrait).asString;

            DialogueDebug.level = originalDebugLevel;
            if (string.IsNullOrEmpty(imageName))
            {
                return(GetPortraitSprite(1));
            }
            else if (imageName.StartsWith("pic="))
            {
                return(GetPortraitSprite(Tools.StringToInt(imageName.Substring("pic=".Length))));
            }
            else
            {
                return(UITools.CreateSprite(DialogueManager.LoadAsset(imageName) as Texture2D));
            }
        }
        /// <summary>
        /// Reads a section of assets such as Actors, Items, etc.
        /// </summary>
        /// <param name="assets">List of assets to populate.</param>
        /// <typeparam name="T">The type of asset.</typeparam>
        private void ReadAssets <T>(List <T> assets) where T : Asset, new()
        {
            string typeName       = typeof(T).Name;
            bool   isActorSection = (typeof(T) == typeof(Actor));

            Debug.Log(string.Format("Reading {0} section", typeName));

            // Read field names and types:
            string[] fieldNames = GetValues(GetNextSourceLine());
            string[] fieldTypes = GetValues(GetNextSourceLine());

            // Set up ignore list for values that aren't actual fields:
            List <string> ignore = isActorSection ? ActorSpecialValues : DefaultSpecialValues;

            // Keep reading until we reach another asset type heading or end of file:
            while (!(IsSourceAtEnd() || AssetTypeHeadings.Contains(PeekNextSourceLine())))
            {
                string[] values = GetValues(GetNextSourceLine());

                // Create the asset:
                T asset = new T();
                asset.id     = Tools.StringToInt(values[0]);
                asset.fields = new List <Field>();

                // Preprocess a couple extra values for actors:
                if (isActorSection)
                {
                    FindActorPortraits(asset as Actor, values[1], values[2]);
                }

                // Read the remaining values and assign them to the asset's fields:
                ReadAssetFields(fieldNames, fieldTypes, ignore, values, asset.fields);

                // Finally, add the asset:
                assets.Add(asset);
            }
        }
Пример #11
0
        /// <summary>
        /// Reads the OutgoingLinks section. Again, Link is not a subclass of Asset,
        /// so we can't reuse the ReadAssets() method.
        /// </summary>
        /// <param name="database">Dialogue database.</param>
        private void ReadOutgoingLinks(DialogueDatabase database, bool add)
        {
            Debug.Log("Dialogue System CSV Importer: " + (add ? "Reading" : "Skipping") + " OutgoingLinks section");
            GetNextSourceLine(); // Headings
            GetNextSourceLine(); // Types

            // 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)
                {
                    var link = new Link(Tools.StringToInt(values[0]), Tools.StringToInt(values[1]),
                                        Tools.StringToInt(values[2]), Tools.StringToInt(values[3]));
                    link.priority = ConditionPriorityUtility.StringToConditionPriority(values[4]);
                    var entry = database.GetDialogueEntry(link.originConversationID, link.originDialogueID);
                    if (entry == null)
                    {
                        Debug.LogWarning(string.Format("Dialogue System: CSV import error: dialogue entry {0}.{1} referenced in an outgoing link was not found.", link.originConversationID, link.originDialogueID));
                        numWarnings++;
                    }
                    else
                    {
                        entry.outgoingLinks.Add(link);
                    }
                }
            }
        }
Пример #12
0
 /// <summary>
 /// A static utility method that looks up a field in a list and returns its int value.
 /// </summary>
 /// <param name='fields'>
 /// A list of fields.
 /// </param>
 /// <param name='title'>
 /// Title of the field.
 /// </param>
 /// <returns>
 /// The value of the field, or <c>0</c> if the field doesn't exist or isn't an int.
 /// </returns>
 public static int LookupInt(List <Field> fields, string title)
 {
     return(Tools.StringToInt(LookupValue(fields, title)));
 }
Пример #13
0
        /// <summary>
        /// When loading a game, load the dialogue entry records and resume the conversation.
        /// </summary>
        public virtual void OnApplyPersistentData()
        {
            if (DontLoadInThisScene())
            {
                Debug.Log("OnApplyPersistentData Dont Load in this scene: " + SceneManager.GetActiveScene().buildIndex);
            }
            if (DontLoadInThisScene())
            {
                return;
            }
            records.Clear();
            if (!DialogueLua.DoesVariableExist(currentDialogueEntryRecords))
            {
                return;
            }
            StopAllCoroutines();

            // Load dialogue entry records:
            var s = DialogueLua.GetVariable(currentDialogueEntryRecords).AsString;

            if (Debug.isDebugBuild)
            {
                Debug.Log("TextlineDialogueUI.OnApplyPersistentData: Restoring current conversation from " + currentDialogueEntryRecords + ": " + s);
            }
            var ints       = s.Split(';');
            var numRecords = Tools.StringToInt(ints[0]);

            for (int i = 0; i < numRecords; i++)
            {
                var conversationID = Tools.StringToInt(ints[1 + i * 2]);
                var entryID        = Tools.StringToInt(ints[2 + i * 2]);
                records.Add(new DialogueEntryRecord(conversationID, entryID));
            }

            // If we have records, resume the conversation:
            if (records.Count == 0)
            {
                return;
            }
            var lastRecord = records[records.Count - 1];

            if (lastRecord.conversationID >= 0 && lastRecord.entryID > 0)
            {
                UnityEngine.UI.Button lastContinueButton = null;
                try
                {
                    // Resume conversation:
                    //if (dontRepeatLastSequence) isLoadingGame = true;
                    isLoadingGame = true;
                    var conversation        = DialogueManager.MasterDatabase.GetConversation(lastRecord.conversationID);
                    var actorName           = DialogueLua.GetVariable(currentConversationActor).AsString;
                    var conversantName      = DialogueLua.GetVariable(currentConversationConversant).AsString;
                    var actor               = GameObject.Find(actorName);
                    var conversant          = GameObject.Find(conversantName);
                    var actorTransform      = (actor != null) ? actor.transform : null;
                    var conversantTransform = (conversant != null) ? conversant.transform : null;
                    if (Debug.isDebugBuild)
                    {
                        Debug.Log("Resuming '" + conversation.Title + "' at entry " + lastRecord.entryID);
                    }
                    DialogueManager.StopConversation();
                    var lastEntry        = DialogueManager.MasterDatabase.GetDialogueEntry(lastRecord.conversationID, lastRecord.entryID);
                    var originalSequence = lastEntry.Sequence; // Handle last entry's sequence differently if end entry.
                    npcPreDelaySettings.CopyTo(npcPreDelaySettingsCopy);
                    pcPreDelaySettings.CopyTo(pcPreDelaySettingsCopy);
                    npcPreDelaySettings.basedOnTextLength = false;
                    npcPreDelaySettings.additionalSeconds = 0;
                    pcPreDelaySettings.basedOnTextLength  = false;
                    pcPreDelaySettings.additionalSeconds  = 0;
                    var isEndEntry = lastEntry.Sequence.Contains("WaitForMessage(Forever)") || lastEntry.outgoingLinks.Count == 0;
                    if (isEndEntry)
                    {
                        if (!lastEntry.Sequence.Contains("WaitForMessage(Forever)"))
                        {
                            lastEntry.Sequence = "WaitForMessage(Forever); " + lastEntry.Sequence;
                        }
                    }
                    else if (dontRepeatLastSequence)
                    {
                        lastEntry.Sequence = "None()";
                    }
                    else
                    {
                        lastEntry.Sequence = "Delay(0.1)";
                    }
                    skipNextRecord = true;
                    isInPreDelay   = false;
                    DialogueManager.StartConversation(conversation.Title, actorTransform, conversantTransform, lastRecord.entryID);
                    lastContinueButton = continueButton;
                    lastEntry.Sequence = originalSequence;
                    npcPreDelaySettingsCopy.CopyTo(npcPreDelaySettings);
                    pcPreDelaySettingsCopy.CopyTo(pcPreDelaySettings);

                    // Populate UI with previous records:
                    var lastInstance = (instantiatedMessages.Count > 0) ? instantiatedMessages[instantiatedMessages.Count - 1] : null;
                    instantiatedMessages.Remove(lastInstance);
                    DestroyInstantiatedMessages();
                    for (int i = 0; i < records.Count - 1; i++)
                    {
                        var entry         = DialogueManager.MasterDatabase.GetDialogueEntry(records[i].conversationID, records[i].entryID);
                        var speakerInfo   = DialogueManager.ConversationModel.GetCharacterInfo(entry.ActorID);
                        var listenerInfo  = DialogueManager.ConversationModel.GetCharacterInfo(entry.ConversantID);
                        var formattedText = FormattedText.Parse(entry.currentDialogueText, DialogueManager.MasterDatabase.emphasisSettings);
                        var subtitle      = new Subtitle(speakerInfo, listenerInfo, null, formattedText, "None()", entry.ResponseMenuSequence, entry);
                        AddMessage(subtitle);
                    }
                    if (lastInstance != null)
                    {
                        instantiatedMessages.Add(lastInstance);
                        lastInstance.transform.SetAsLastSibling();
                    }
                }
                finally
                {
                    isLoadingGame = false;
                    scrollRect.verticalNormalizedPosition = 0;
                    continueButton = lastContinueButton;
                    if (shouldShowContinueButton && lastContinueButton != null)
                    {
                        lastContinueButton.gameObject.SetActive(true);
                    }
                }
            }
            ScrollToBottom();
        }