/// <summary>
        ///
        /// </summary>
        /// <param name="entry"></param>
        /// <returns></returns>
        private static ScriptMetadata GetScript(DictionaryEntry entry)
        {
            if (!(entry.Key is string fileName))
            {
                return(null);
            }

            var version = GetVersionFromFileName(fileName);

            if (version == null)
            {
                return(null);
            }

            if (!(entry.Value is string script))
            {
                return(null);
            }

            if (string.IsNullOrEmpty(script))
            {
                return(null);
            }

            var scriptMetadata = new ScriptMetadata();

            scriptMetadata.FileName      = fileName;
            scriptMetadata.VersionString = version.ToString();
            scriptMetadata.Version       = version;
            scriptMetadata.ScriptText    = script;

            return(scriptMetadata);
        }
Beispiel #2
0
    public static void ExcessCatalystError(GameSession session, ItemEnchant itemEnchant)
    {
        int npcId = itemEnchant.Type switch
        {
            EnchantType.Ophelia => 11000508,
            _ => 11000510
        };
        ScriptMetadata scriptMetadata = ScriptMetadataStorage.GetNpcScriptMetadata(npcId);
        NpcScript      npcScript      = scriptMetadata?.NpcScripts.FirstOrDefault(x => x.Id == 31);

        if (npcScript is null)
        {
            return;
        }

        Script   script = ScriptLoader.GetScript($"Npcs/{npcId}", session);
        DynValue excessCatalystFunction = script.RunFunction("getExcessCatalystEventId");

        if (excessCatalystFunction is null)
        {
            return;
        }

        int eventId = (int)excessCatalystFunction.Number;

        if (eventId == 0)
        {
            return;
        }

        HandleNpcTalkEventType(session, npcScript, eventId);
    }
Beispiel #3
0
        private static DialogType GetDialogType(ScriptMetadata scriptMetadata, NpcTalk npcTalk, bool hasNextScript)
        {
            DialogType dialogType = DialogType.CloseNext1;
            Option     option     = scriptMetadata.Options.First(x => x.Id == npcTalk.ScriptId);

            if (option.Goto.Count == 0)
            {
                dialogType = DialogType.CloseNext1;
            }
            if (option.AmountContent > 1)
            {
                dialogType = DialogType.CloseNext;
            }

            if (!hasNextScript)
            {
                ScriptIdType type = (ScriptIdType)(npcTalk.ScriptId / 100);
                if (npcTalk.IsQuest)
                {
                    dialogType = type switch
                    {
                        ScriptIdType.Start => DialogType.AcceptDecline,
                        ScriptIdType.End => DialogType.QuestReward,
                        _ => DialogType.Close1,
                    };
                }
                else
                {
                    dialogType = DialogType.Close1;
                }
            }
            return(dialogType);
        }
Beispiel #4
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="scriptMetadata"></param>
 public MetadataScriptInfo(ScriptMetadata scriptMetadata)
 {
     ScriptMetadata = scriptMetadata;
     ScriptText     = scriptMetadata.ScriptText;
     MigrateName    = scriptMetadata.MigrateName;
     Version        = scriptMetadata.Version;
 }
 public override void InitFromRawDecompressed(byte[] decompressedBytes)
 {
     using (var decompressedStream = new BinaryReader(new MemoryStream(decompressedBytes)))
     {
         this.Resource = Read_ScriptMetadataResource(decompressedStream);
     }
 }
Beispiel #6
0
        private static int GetNextScript(ScriptMetadata scriptMetadata, NpcTalk npcTalk, int index)
        {
            if (npcTalk.IsQuest && npcTalk.ScriptId == 0)
            {
                QuestStatus questStatus = npcTalk.Quests[index];
                if (questStatus.Started)
                {
                    // Talking to npc that start the quest and condition is not completed
                    if (questStatus.StartNpcId == npcTalk.Npc.Id && questStatus.Condition.Count != questStatus.Condition.Count(x => x.Goal == x.Current))
                    {
                        return(200);
                    }
                    return(300); // Talking to npc that end the quest
                }
                return(100);     // Talking to npc that start the quest and isn't started
            }

            Option option = scriptMetadata.Options.First(x => x.Id == npcTalk.ScriptId);

            if (npcTalk.ScriptId == 0)
            {
                return(scriptMetadata.Options.First(x => x.Id > npcTalk.ScriptId).Id);
            }

            if (option.Goto.Count == 0)
            {
                return(npcTalk.ScriptId);
            }
            return(option.Goto[index]);
        }
Beispiel #7
0
    public static void TalkError(GameSession session, ItemEnchant itemEnchant)
    {
        int npcId = itemEnchant.Type switch
        {
            EnchantType.Ophelia => 11000508,
            _ => 11000510
        };
        ScriptMetadata scriptMetadata = ScriptMetadataStorage.GetNpcScriptMetadata(npcId);
        NpcScript      npcScript      = scriptMetadata?.NpcScripts.FirstOrDefault(x => x.Id == 31);

        if (npcScript is null)
        {
            return;
        }

        Script script  = ScriptLoader.GetScript($"Npcs/{npcId}", session);
        int    eventId = (int)script.RunFunction("getProcessEventId", PlayerHasIngredients(itemEnchant, session.Player.Inventory),
                                                 PlayerHasRequiredCatalysts(itemEnchant)).Number;

        if (eventId == 0)
        {
            return;
        }

        HandleNpcTalkEventType(session, npcScript, eventId);
    }
        private void ReadMonoBehaviours(PrefabMetadata metadata, string content)
        {
            var documents = content.Split(new string[] { "--- !u!114" }, StringSplitOptions.RemoveEmptyEntries);

            for (int i = 1; i < documents.Length; i++)
            {
                var document      = documents[i];
                var monoBehaviour = new MonoBehaviourMetadata();
                var script        = new ScriptMetadata
                {
                    FileId = ReadFileId(document, ScriptFileIdRegex),
                    Guid   = ReadString(document, ScriptGuidRegex, "guid")
                };
                script.FullName = m_scriptMetadataService.GetFullNameByFileId(script.FileId);

                if (String.IsNullOrEmpty(script.FullName))
                {
                    script.FullName = MetaFileService.GetFileNameByGuid(script.Guid);
                }

                monoBehaviour.Script = script;

                metadata.MonoBehaviours.Add(monoBehaviour);
            }
        }
        public void ReplaceGuid_OldAndNew_Replaced()
        {
            var fs         = MetadataBootstrap.FileSystem;
            var prefabPath = "PrefabSample1.ReplaceGuidTest.prefab";

            fs.CopyFile("PrefabSample1.prefab", prefabPath);

            var target = new YamlPrefabMetadataWriter(fs, MockRepository.GenerateMock <ILog>());

            var oldScript1 = new ScriptMetadata {
                FileId = 1363015578, Guid = "a184ae646778d4bf48c881bb73f2188a"
            };
            var oldScript2 = new ScriptMetadata {
                FileId = -1557964980, Guid = "a184ae646778d4bf48c881bb73f2188a"
            };

            target.ReplaceGuid(oldScript1, "1ReplaceGuidTest1", prefabPath);
            target.ReplaceGuid(oldScript2, "2ReplaceGuidTest2", prefabPath);

            var reader = new YamlPrefabMetadataReader(MetadataBootstrap.ScriptMetadataService, fs);
            var actual = reader.Read(prefabPath);

            Assert.AreEqual(2, actual.MonoBehaviours.Count);
            Assert.AreEqual("1ReplaceGuidTest1", actual.MonoBehaviours.First().Script.Guid);
            Assert.AreEqual("2ReplaceGuidTest2", actual.MonoBehaviours.Last().Script.Guid);
        }
Beispiel #10
0
        private static int GetNextScript(ScriptMetadata scriptMetadata, NpcTalk npcTalk, int index, ScriptLoader scriptLoader)
        {
            if (npcTalk.IsQuest && npcTalk.ScriptId == 0)
            {
                QuestStatus questStatus = npcTalk.Quests[index];
                if (questStatus.Started)
                {
                    // Talking to npc that start the quest and condition is not completed
                    if (questStatus.StartNpcId == npcTalk.Npc.Id && questStatus.Condition.Count != questStatus.Condition.Count(x => x.Completed))
                    {
                        return(200);
                    }
                    return(300); // Talking to npc that end the quest
                }
                return(100);     // Talking to npc that start the quest and isn't started
            }

            if (npcTalk.ScriptId == 0)
            {
                if (scriptLoader.Script != null)
                {
                    // Usually hardcoded functions to get the first script id which
                    // otherwise wouldn't be possible only with the xml data
                    DynValue result = scriptLoader.Call("getFirstScriptId");
                    if (result != null && result.Number != -1)
                    {
                        return((int)result.Number);
                    }
                }

                return(scriptMetadata.Options.First(x => x.Id > npcTalk.ScriptId).Id);
            }

            Option currentOption = scriptMetadata.Options.First(x => x.Id == npcTalk.ScriptId);

            if (currentOption.Contents[npcTalk.ContentIndex].Goto.Count == 0 ||
                currentOption?.Contents.Count > 1 && currentOption?.Contents.Count > npcTalk.ContentIndex + 1)
            {
                return(npcTalk.ScriptId);
            }

            // If content has goto fail, use the lua scripts to check the requirements
            if (currentOption.Contents[npcTalk.ContentIndex].GotoFail.Count > 0)
            {
                if (scriptLoader.Script != null)
                {
                    DynValue result = scriptLoader.Call("handleGotoFail", currentOption.Contents[npcTalk.ContentIndex].Goto[index]);
                    if (result == null)
                    {
                        return(0);
                    }

                    return((int)result.Number);
                }
            }

            // TODO: check for the requirements for goto

            return(currentOption.Contents[npcTalk.ContentIndex].Goto[index]);
        }
        private ScriptMetadata Read_ScriptMetadataResource(BinaryReader reader)
        {
            var result = new ScriptMetadata();

            result.Version = ReadVersion(reader, 5, 0x141115FB0); // C3038F16B1058B48

            if (result.Version < 2)
            {
                result.Parameters = new List <KeyValuePair <string, string> >();

                var ParameterCount = reader.ReadUInt32(); // skip
                for (int i = 0; i < ParameterCount; i++)
                {
                    var ParamKey   = ReadString(reader);
                    var ParamValue = ReadString(reader);

                    result.Parameters.Add(new KeyValuePair <string, string>(ParamKey, ParamValue));
                }

                return(result);
            }

            if (result.Version < 3)
            {
                result.SourceFileName = ReadString(reader);
            }

            result.Info   = ReadString(reader);
            result.Errors = ReadString(reader);
            result.Flags  = reader.ReadUInt32();

            if (result.Version >= 4)
            {
                result.ScriptClasses = Read_List(reader, Read_ScriptClass, 1, 0x1411D2370);
                result.DefaultScript = ReadString(reader);
            }
            else
            {
                result.Properties = Read_List(reader, Read_Property, 1, 0x1411D2360);
            }

            result.Tags = Read_List(reader, Read_ScriptTag, 1, 0x1411D2380);
            if (result.Version >= 5)
            {
                result.Tooltip = ReadString(reader);
            }

            return(result);
        }
Beispiel #12
0
        private static int GetFirstScriptId(ScriptLoader scriptLoader, ScriptMetadata scriptMetadata)
        {
            if (scriptLoader.Script != null)
            {
                // Usually hardcoded functions to get the first script id which
                // otherwise wouldn't be possible only with the xml data
                DynValue result = scriptLoader.Call("getFirstScriptId");
                if (result != null && result.Number != -1)
                {
                    return((int)result.Number);
                }
            }

            return(scriptMetadata.Options.First(x => x.Type == ScriptType.Script).Id);
        }
Beispiel #13
0
        /// <summary>
        /// Replaces the GUID.
        /// </summary>
        /// <param name="oldScript">Old script.</param>
        /// <param name="newGuid">New GUID.</param>
        /// <param name="fileName">File name.</param>
        public void ReplaceGuid(ScriptMetadata oldScript, string newGuid, string fileName)
        {
            m_log.Debug("Replacing guid from '{0}' to '{1}' on file '{2}'...", oldScript.Guid, newGuid, fileName);
            var content = m_fs.ReadAllText(fileName);
            var regex   = new Regex(@"(\{{fileID: {0}, guid: )({1})(, type: 3)".With(oldScript.FileId, oldScript.Guid), RegexOptions.Compiled | RegexOptions.IgnoreCase);

            content = regex.Replace(
                content,
                (m) =>
            {
                return("{0}{1}{2}".With(m.Groups[1].Value, newGuid, m.Groups[3].Value));
            });

            m_fs.WriteAllText(fileName, content);
        }
Beispiel #14
0
    public ScriptMetadata[] LoadScriptMetadata()
    {
        var list    = new List <ScriptMetadata>();
        var scripts = XUtil.GetScriptMap();

        using (var reader = OpenFile("properties", "scriptMetadata.txt"))
            using (var txt = new StreamReader(reader)) {
                string line;
                while ((line = txt.ReadLine()) != null)
                {
                    if (!line.HasValue() || line[0] == '#')
                    {
                        continue;
                    }
                    string[] fields = line.Split(';');
                    string   code   = fields[0]?.Trim();
                    if (!code.HasValue())
                    {
                        continue;
                    }
                    if (!scripts.TryGetValue(code, out WritingScript script))
                    {
                        throw new FormatException("Id " + code);
                    }
                    var cur = new ScriptMetadata();
                    cur.Script = script;
                    list.Add(cur);

                    code = fields[1].Trim();
                    if (int.TryParse(code, out int rank))
                    {
                        cur.Rank = rank;
                    }
                    code = fields[3].Trim();
                    if (code.HasValue())
                    {
                        cur.Territory = GetTerritory(code);
                    }
                    code = fields[4].Trim();
                    if (int.TryParse(code, out rank))
                    {
                        cur.Density = rank;
                    }
                }
            }
        return(list.ToArray());
    }
Beispiel #15
0
 private static int GetNextScript(ScriptMetadata scriptMetadata, NpcTalk npcTalk, int index)
 {
     if (npcTalk.IsQuest && npcTalk.ScriptId == 0)
     {
         if (npcTalk.Quests[index].Started)
         {
             // Talking to npc that start the quest and is started
             if (npcTalk.Quests[index].StartNpcId == npcTalk.Npc.Id)
             {
                 return(200);
             }
             else // Talking to npc that end the quest
             {
                 return(300);
             }
         }
         else // Talking to npc that start the quest and isn't started
         {
             return(100);
         }
     }
     else
     {
         Option option = scriptMetadata.Options.First(x => x.Id == npcTalk.ScriptId);
         if (npcTalk.ScriptId == 0)
         {
             return(scriptMetadata.Options.First(x => x.Id > npcTalk.ScriptId).Id);
         }
         else
         {
             if (option.Goto.Count == 0)
             {
                 return(npcTalk.ScriptId);
             }
             else
             {
                 return(option.Goto[index]);
             }
         }
     }
 }
Beispiel #16
0
        private static DialogType GetDialogType(ScriptMetadata scriptMetadata, NpcTalk npcTalk, bool hasNextScript)
        {
            DialogType dialogType = DialogType.None;
            Option     option     = scriptMetadata.Options.First(x => x.Id == npcTalk.ScriptId);

            // If npc has buttonSet by xmls, use it
            if (option.Contents[npcTalk.ContentIndex].ButtonSet != DialogType.None)
            {
                return(option.Contents[npcTalk.ContentIndex].ButtonSet);
            }

            if (option.Contents[npcTalk.ContentIndex].Goto.Count == 0)
            {
                dialogType = DialogType.CloseNext;
            }
            else
            {
                dialogType = DialogType.CloseNextWithDistractor;
            }

            if (!hasNextScript)
            {
                // Get the correct dialog type for the last quest content
                ScriptIdType type = (ScriptIdType)(npcTalk.ScriptId / 100);
                if (npcTalk.IsQuest)
                {
                    dialogType = type switch
                    {
                        ScriptIdType.Start => DialogType.AcceptDecline,
                        ScriptIdType.End => DialogType.QuestReward,
                        _ => DialogType.Close1,
                    };
                }
                else
                {
                    dialogType = DialogType.Close1;
                }
            }
            return(dialogType);
        }
    private static DialogType GetDialogType(ScriptMetadata scriptMetadata, NpcTalk npcTalk, bool hasNextScript)
    {
        Option  option  = scriptMetadata.Options.First(x => x.Id == npcTalk.ScriptId);
        Content content = option.Contents[npcTalk.ContentIndex];

        // If npc has buttonSet by xmls, use it
        if (content.ButtonSet != DialogType.None)
        {
            return(content.ButtonSet);
        }

        if (!hasNextScript)
        {
            // Get the correct dialog type for the last quest content
            ScriptIdType type = (ScriptIdType)(npcTalk.ScriptId / 100);
            if (npcTalk.IsQuest)
            {
                return(type switch
                {
                    ScriptIdType.Start => DialogType.AcceptDecline,
                    ScriptIdType.End => DialogType.QuestReward,
                    _ => DialogType.Close1
                });
Beispiel #18
0
        public static List <ScriptMetadata> ParseNpc(MemoryMappedFile m2dFile, IEnumerable <PackFileEntry> entries)
        {
            List <ScriptMetadata> scripts = new List <ScriptMetadata>();

            foreach (PackFileEntry entry in entries)
            {
                if (!entry.Name.StartsWith("script/npc"))
                {
                    continue;
                }

                ScriptMetadata metadata = new ScriptMetadata();
                string         npcID    = Path.GetFileNameWithoutExtension(entry.Name);
                XmlDocument    document = m2dFile.GetDocument(entry.FileHeader);
                foreach (XmlNode node in document.DocumentElement.ChildNodes)
                {
                    int        id                  = int.Parse(node.Attributes["id"].Value);
                    string     feature             = node.Attributes["feature"].Value;
                    int        randomPick          = string.IsNullOrEmpty(node.Attributes["randomPick"]?.Value) ? 0 : int.Parse(node.Attributes["randomPick"].Value);
                    int        popupState          = string.IsNullOrEmpty(node.Attributes["popupState"]?.Value) ? 0 : int.Parse(node.Attributes["popupState"].Value);
                    int        popupProp           = string.IsNullOrEmpty(node.Attributes["popupProp"]?.Value) ? 0 : int.Parse(node.Attributes["popupProp"].Value);
                    List <int> gotoConditionTalkID = new List <int>();
                    if (!string.IsNullOrEmpty(node.Attributes["popupProp"]?.Value))
                    {
                        foreach (string item in node.Attributes["popupProp"].Value.Split(","))
                        {
                            gotoConditionTalkID.Add(int.Parse(item));
                        }
                    }

                    List <Content> contents = new List <Content>();
                    foreach (XmlNode content in node.ChildNodes)
                    {
                        long   contentScriptID = string.IsNullOrEmpty(content.Attributes["text"]?.Value) ? 0 : long.Parse(content.Attributes["text"].Value.Substring(8, 16));
                        string voiceID         = string.IsNullOrEmpty(content.Attributes["voiceID"]?.Value) ? "" : content.Attributes["voiceID"].Value;
                        int    otherNpcTalk    = string.IsNullOrEmpty(content.Attributes["otherNpcTalk"]?.Value) ? 0 : int.Parse(content.Attributes["otherNpcTalk"].Value);
                        string leftIllust      = string.IsNullOrEmpty(content.Attributes["leftIllust"]?.Value) ? "" : content.Attributes["leftIllust"].Value;
                        string illust          = string.IsNullOrEmpty(content.Attributes["illust"]?.Value) ? "" : content.Attributes["illust"].Value;
                        string speakerIllust   = string.IsNullOrEmpty(content.Attributes["speakerIllust"]?.Value) ? "" : content.Attributes["speakerIllust"].Value;
                        bool   myTalk          = !string.IsNullOrEmpty(content.Attributes["myTalk"]?.Value);
                        byte   functionID      = string.IsNullOrEmpty(content.Attributes["functionID"]?.Value) ? 0 : byte.Parse(content.Attributes["functionID"].Value);

                        List <Distractor> distractors = new List <Distractor>();
                        List <Event>      events      = new List <Event>();
                        foreach (XmlNode distractor in content.ChildNodes)
                        {
                            if (distractor.Name == "event")
                            {
                                int eventid = string.IsNullOrEmpty(content.Attributes["id"]?.Value) ? 0 : int.Parse(content.Attributes["id"].Value);

                                List <Content> contents2 = new List <Content>();
                                foreach (XmlNode item in distractor.ChildNodes)
                                {
                                    long   contentScriptID2 = long.Parse(item.Attributes["text"].Value.Substring(8, 16));
                                    string voiceID2         = string.IsNullOrEmpty(item.Attributes["voiceID"]?.Value) ? "" : item.Attributes["voiceID"].Value;
                                    int    otherNpcTalk2    = string.IsNullOrEmpty(item.Attributes["otherNpcTalk"]?.Value) ? 0 : int.Parse(item.Attributes["otherNpcTalk"].Value);
                                    string leftIllust2      = string.IsNullOrEmpty(item.Attributes["leftIllust"]?.Value) ? "" : item.Attributes["leftIllust"].Value;
                                    string illust2          = string.IsNullOrEmpty(item.Attributes["illust"]?.Value) ? "" : item.Attributes["illust"].Value;
                                    string speakerIllust2   = string.IsNullOrEmpty(item.Attributes["speakerIllust"]?.Value) ? "" : item.Attributes["speakerIllust"].Value;
                                    bool   myTalk2          = !string.IsNullOrEmpty(item.Attributes["myTalk"]?.Value);
                                    byte   functionID2      = string.IsNullOrEmpty(item.Attributes["functionID"]?.Value) ? 0 : byte.Parse(item.Attributes["functionID"].Value);

                                    contents2.Add(new Content(contentScriptID2, voiceID2, functionID2, leftIllust2, speakerIllust2, otherNpcTalk2, myTalk2, illust2, null));
                                }
                                events.Add(new Event(eventid, contents2));
                            }
                            else
                            {
                                long       distractorScriptID = long.Parse(distractor.Attributes["text"].Value.Substring(8, 16));
                                List <int> goTo = new List <int>();
                                if (!string.IsNullOrEmpty(distractor.Attributes["goto"]?.Value))
                                {
                                    foreach (string item in distractor.Attributes["goto"].Value.Split(","))
                                    {
                                        goTo.Add(int.Parse(item));
                                    }
                                }
                                List <int> goToFail = new List <int>();
                                if (!string.IsNullOrEmpty(distractor.Attributes["gotoFail"]?.Value))
                                {
                                    foreach (string item in distractor.Attributes["gotoFail"].Value.Split(","))
                                    {
                                        goToFail.Add(int.Parse(item));
                                    }
                                }

                                distractors.Add(new Distractor(distractorScriptID, goTo, goToFail));
                            }
                        }

                        contents.Add(new Content(contentScriptID, voiceID, functionID, leftIllust, speakerIllust, otherNpcTalk, myTalk, illust, distractors));
                    }

                    metadata.Id            = int.Parse(npcID);
                    metadata.IsQuestScript = false;

                    if (node.Name == "select")
                    {
                        metadata.Selects[id] = new Select(id, contents);
                    }
                    else if (node.Name == "script")
                    {
                        metadata.Scripts[id] = new Script(id, feature, randomPick, gotoConditionTalkID, contents);
                    }
                    else if (node.Name == "monologue")
                    {
                        metadata.Monologues[id] = new Monologue(id, popupState, popupProp, contents);
                    }
                }

                scripts.Add(metadata);
            }

            return(scripts);
        }
Beispiel #19
0
        private static void HandleContinue(GameSession session, PacketReader packet)
        {
            NpcTalk npcTalk = session.Player.NpcTalk;

            if (npcTalk.Npc.IsBeauty())
            {
                HandleBeauty(session);
                return;
            }

            int index = packet.ReadInt(); // selection index

            // index is quest
            if (index <= npcTalk.Quests.Count - 1 && npcTalk.ScriptId == 0)
            {
                npcTalk.QuestId = npcTalk.Quests[index].Basic.Id;
                npcTalk.IsQuest = true;
            }

            ScriptMetadata scriptMetadata = npcTalk.IsQuest ? ScriptMetadataStorage.GetQuestScriptMetadata(npcTalk.QuestId) : ScriptMetadataStorage.GetNpcScriptMetadata(npcTalk.Npc.Id);
            ResponseType   responseType   = npcTalk.IsQuest ? ResponseType.Quest : ResponseType.Dialog;

            if (npcTalk.ScriptId != 0)
            {
                Option option = scriptMetadata.Options.First(x => x.Id == npcTalk.ScriptId);
                if (option.AmountContent <= npcTalk.ContentIndex && option.Goto.Count == 0)
                {
                    session.Send(NpcTalkPacket.Close());
                    return;
                }
            }

            // Find next script id
            int    nextScript = GetNextScript(scriptMetadata, npcTalk, index);
            Option option2    = scriptMetadata.Options.FirstOrDefault(x => x.Id == npcTalk.ScriptId);

            if (option2?.AmountContent > 1 && option2?.AmountContent > npcTalk.ContentIndex)
            {
                nextScript = npcTalk.ScriptId;
            }

            if (npcTalk.ScriptId != nextScript)
            {
                npcTalk.ContentIndex = 1;
            }
            else
            {
                npcTalk.ContentIndex++;
            }

            Option option1       = scriptMetadata.Options.First(x => x.Id == nextScript);
            bool   hasNextScript = option1.Goto.Count != 0;

            if (option1.AmountContent > npcTalk.ContentIndex)
            {
                hasNextScript = true;
            }
            npcTalk.ScriptId = nextScript;

            DialogType dialogType = GetDialogType(scriptMetadata, npcTalk, hasNextScript);

            session.Send(NpcTalkPacket.ContinueChat(nextScript, responseType, dialogType, npcTalk.ContentIndex - 1, npcTalk.QuestId));
        }
Beispiel #20
0
        private static void HandleRespond(GameSession session, PacketReader packet)
        {
            List <QuestStatus> npcQuests = new List <QuestStatus>();
            int objectId = packet.ReadInt();

            // Find if npc object id exists in field manager
            if (!session.FieldManager.State.Npcs.TryGetValue(objectId, out IFieldObject <Npc> npc))
            {
                return;
            }

            // Get all quests for this npc
            foreach (QuestStatus item in session.Player.QuestList.Where(x => !x.Completed))
            {
                if (npc.Value.Id == item.StartNpcId)
                {
                    npcQuests.Add(item);
                }
                if (item.Started && npc.Value.Id == item.CompleteNpcId && !npcQuests.Contains(item))
                {
                    npcQuests.Add(item);
                }
            }
            session.Player.NpcTalk = new NpcTalk(npc.Value, npcQuests);
            ScriptLoader scriptLoader = new ScriptLoader($"Npcs/{npc.Value.Id}", session);

            // If NPC is a shop, load and open the shop
            if (npc.Value.IsShop())
            {
                ShopHandler.HandleOpen(session, npc);
                return;
            }
            else if (npc.Value.IsBank())
            {
                session.Send(HomeBank.OpenBank());
                return;
            }
            else if (npc.Value.IsBeauty())
            {
                NpcMetadata npcTarget = NpcMetadataStorage.GetNpc(session.Player.NpcTalk.Npc.Id);
                if (npcTarget.ShopId == 507) // mirror
                {
                    session.Send(NpcTalkPacket.Respond(npc, NpcType.Default, DialogType.Beauty, 0));
                    HandleBeauty(session);
                    return;
                }

                session.Send(NpcTalkPacket.Respond(npc, NpcType.Default, DialogType.Beauty, 1));
                return;
            }

            // Check if npc has an exploration quest
            QuestHelper.UpdateExplorationQuest(session, npc.Value.Id.ToString(), "talk_in");

            // If npc has quests, send quests and talk option
            if (npcQuests.Count != 0)
            {
                session.Player.NpcTalk.ScriptId = 0;
                session.Send(QuestPacket.SendDialogQuest(objectId, npcQuests));
                session.Send(NpcTalkPacket.Respond(npc, NpcType.Unk2, DialogType.TalkOption, session.Player.NpcTalk.ScriptId));
                return;
            }

            ScriptMetadata scriptMetadata = ScriptMetadataStorage.GetNpcScriptMetadata(npc.Value.Id);

            if (!scriptMetadata.Options.Exists(x => x.Type == ScriptType.Script))
            {
                return;
            }

            int firstScriptId = GetFirstScriptId(scriptLoader, scriptMetadata);

            session.Player.NpcTalk.ScriptId = firstScriptId;

            Option option = scriptMetadata.Options.First(x => x.Id == firstScriptId);

            DialogType dialogType = DialogType.None;

            if (option.Contents[0].Goto.Count == 0)
            {
                dialogType = DialogType.Close1;
            }
            else
            {
                dialogType = DialogType.CloseNextWithDistractor;
            }

            session.Send(NpcTalkPacket.Respond(npc, NpcType.Unk3, dialogType, firstScriptId));

            // If npc has buttonset roulette, send roulette id 13.
            // TODO: Send the correct roulette id
            if (scriptMetadata.Options.Any(x => x.ButtonSet == "roulette"))
            {
                session.Send(NpcTalkPacket.Action(ActionType.OpenWindow, "RouletteDialog", "13"));
            }
        }
Beispiel #21
0
 public void AddMetadata(ScriptMetadata metadata)
 {
     ScriptData.Add(metadata);
 }
Beispiel #22
0
        private static void HandleContinue(GameSession session, int index)
        {
            NpcTalk npcTalk = session.Player.NpcTalk;

            if (npcTalk.Npc.IsBeauty())
            {
                HandleBeauty(session);
                return;
            }

            ScriptLoader scriptLoader = new ScriptLoader($"Npcs/{npcTalk.Npc.Id}", session);

            // index is quest
            if (index <= npcTalk.Quests.Count - 1 && npcTalk.ScriptId == 0)
            {
                npcTalk.QuestId = npcTalk.Quests[index].Basic.Id;
                npcTalk.IsQuest = true;
            }

            ScriptMetadata scriptMetadata = npcTalk.IsQuest ? ScriptMetadataStorage.GetQuestScriptMetadata(npcTalk.QuestId) : ScriptMetadataStorage.GetNpcScriptMetadata(npcTalk.Npc.Id);
            ResponseType   responseType   = npcTalk.IsQuest ? ResponseType.Quest : ResponseType.Dialog;

            if (npcTalk.ScriptId != 0)
            {
                Option option = scriptMetadata.Options.First(x => x.Id == npcTalk.ScriptId);

                // Find if player has quest condition for type "talk_in" and option id
                QuestHelper.UpdateQuest(session, npcTalk.Npc.Id.ToString(), "talk_in", option.Id.ToString());

                // If npc has no more options, close dialog
                if (option.Contents.Count <= npcTalk.ContentIndex + 1 && option.Contents[npcTalk.ContentIndex].Goto.Count == 0)
                {
                    session.Send(NpcTalkPacket.Close());
                    return;
                }
            }

            int nextScriptId = GetNextScript(scriptMetadata, npcTalk, index, scriptLoader);

            // If last script is different from next, reset content index, else increment content index
            if (npcTalk.ScriptId != nextScriptId)
            {
                npcTalk.ContentIndex = 0;
            }
            else
            {
                npcTalk.ContentIndex++;
            }

            Option nextScript    = scriptMetadata.Options.First(x => x.Id == nextScriptId);
            bool   hasNextScript = nextScript.Contents[npcTalk.ContentIndex].Goto.Count != 0;

            if (nextScript.Contents.Count > npcTalk.ContentIndex + 1)
            {
                hasNextScript = true;
            }
            npcTalk.ScriptId = nextScriptId;

            DialogType dialogType = GetDialogType(scriptMetadata, npcTalk, hasNextScript);

            session.Send(NpcTalkPacket.ContinueChat(nextScriptId, responseType, dialogType, npcTalk.ContentIndex, npcTalk.QuestId));
            // It appears if content has buttonset roulette, it's send again on every continue chat, unsure why since it doesn't break anything
        }
Beispiel #23
0
        private static void HandleRespond(GameSession session, PacketReader packet)
        {
            List <QuestStatus> npcQuests = new List <QuestStatus>();
            int objectId = packet.ReadInt();

            if (!session.FieldManager.State.Npcs.TryGetValue(objectId, out IFieldObject <Npc> npc))
            {
                return; // Invalid NPC
            }
            foreach (QuestStatus item in session.Player.QuestList.Where(x => !x.Completed))
            {
                if (npc.Value.Id == item.StartNpcId)
                {
                    npcQuests.Add(item);
                }
                if (item.Started && npc.Value.Id == item.CompleteNpcId && !npcQuests.Contains(item))
                {
                    npcQuests.Add(item);
                }
            }
            session.Player.NpcTalk = new NpcTalk(npc.Value, npcQuests);
            // If NPC is a shop, load and open the shop
            if (npc.Value.IsShop())
            {
                ShopHandler.HandleOpen(session, npc);
                return;
            }
            else if (npc.Value.IsBank())
            {
                session.Send(HomeBank.OpenBank());
                return;
            }
            else if (npc.Value.IsBeauty())
            {
                session.Send(NpcTalkPacket.Respond(npc, NpcType.Default, DialogType.Beauty, 1));
                return;
            }

            QuestHelper.UpdateExplorationQuest(session, npc.Value.Id.ToString(), "talk_in");

            if (npcQuests.Count != 0)
            {
                session.Player.NpcTalk.ScriptId = 0;
                session.Send(QuestPacket.SendDialogQuest(objectId, npcQuests));
                session.Send(NpcTalkPacket.Respond(npc, NpcType.Unk2, DialogType.TalkOption, session.Player.NpcTalk.ScriptId));
            }
            else
            {
                ScriptMetadata scriptMetadata = ScriptMetadataStorage.GetNpcScriptMetadata(npc.Value.Id);
                int            firstScript    = scriptMetadata.Options.First(x => x.Type == ScriptType.Script).Id;
                session.Player.NpcTalk.ScriptId = firstScript;

                Option option = scriptMetadata.Options.First(x => x.Id == firstScript);

                bool       hasNextScript = option.Goto.Count != 0;
                DialogType dialogType    = DialogType.CloseNext1;
                if (option.Goto.Count == 0)
                {
                    session.Player.NpcTalk.ContentIndex++;
                    dialogType = DialogType.CloseNext1;
                }

                if (!hasNextScript)
                {
                    dialogType = DialogType.Close1;
                }

                if (option.AmountContent > 1)
                {
                    dialogType = DialogType.CloseNext;
                }

                session.Send(NpcTalkPacket.Respond(npc, NpcType.Unk3, dialogType, firstScript));
            }
        }
Beispiel #24
0
    private static void HandleBegin(GameSession session, PacketReader packet)
    {
        int objectId = packet.ReadInt();
        List <QuestStatus> npcQuests = new();
        int contentIndex             = 0;

        // Find if npc object id exists in field manager
        if (!session.FieldManager.State.Npcs.TryGetValue(objectId, out Npc npc))
        {
            return;
        }

        // Get all quests for this npc
        foreach (QuestStatus item in session.Player.QuestData.Values.Where(x => x.State is not QuestState.Completed))
        {
            if (npc.Value.Id == item.StartNpcId)
            {
                npcQuests.Add(item);
            }

            if (item.State is QuestState.Started && npc.Value.Id == item.CompleteNpcId && !npcQuests.Contains(item))
            {
                npcQuests.Add(item);
            }
        }

        session.Player.NpcTalk = new(npc.Value, npcQuests);
        NpcTalk npcTalk = session.Player.NpcTalk;

        ScriptMetadata scriptMetadata = ScriptMetadataStorage.GetNpcScriptMetadata(npc.Value.Id);
        NpcKind        kind           = npc.Value.NpcMetadataBasic.Kind;

        // need to find script properly before continuing
        NpcScript npcScript = GetFirstScript(session, scriptMetadata, npcTalk, npcQuests);

        switch (kind)
        {
        // reputation NPCs only have UI Dialog Type even if they have quests to accept/accepted.
        case NpcKind.SkyLumiknightCommander:
        case NpcKind.SkyGreenHoodCommander:
        case NpcKind.SkyDarkWindCommander:
        case NpcKind.SkyMapleAllianceCommander:
        case NpcKind.SkyRoyalGuardCommander:
        case NpcKind.KritiasLumiknightCommander:
        case NpcKind.KritiasGreenHoodCommander:
        case NpcKind.KritiasMapleAllianceCommander:
        case NpcKind.Humanitas:
            npcTalk.DialogType = DialogType.UI;
            ShopHandler.HandleOpen(session, npc, npc.Value.Id);
            break;

        case NpcKind.BalmyShop:
        case NpcKind.FixedShop:
        case NpcKind.RotatingShop:
            ShopHandler.HandleOpen(session, npc, npc.Value.Id);
            break;

        case NpcKind.Storage:
        case NpcKind.BlackMarket:
        case NpcKind.Birthday:     // TODO: needs a special case? select if birthday. script if not
            npcTalk.DialogType = DialogType.UI;
            break;
        }

        npcTalk.ScriptId = npcScript?.Id ?? 0;
        ResponseSelection responseSelection = GetResponseSelection(kind, npcTalk.DialogType, contentIndex, npcScript);

        if (npcTalk.DialogType.HasFlag(DialogType.Quest))
        {
            session.Send(QuestPacket.SendDialogQuest(objectId, npcQuests));
        }

        QuestManager.OnTalkNpc(session.Player, npc.Value.Id, npcTalk.ScriptId);
        session.Send(NpcTalkPacket.Respond(npc, npcTalk.DialogType, contentIndex, responseSelection, npcTalk.ScriptId));

        if (npcScript != null)
        {
            npcTalk.TalkFunction(session, npcScript.Contents[npcTalk.ContentIndex].FunctionId, "preTalkActions");
        }
    }