예제 #1
0
        public static GuildMetadata Parse(MemoryMappedFile m2dFile, IEnumerable <PackFileEntry> entries)
        {
            GuildMetadata guildMetadata = new GuildMetadata();

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

                // Parse XML
                XmlDocument document      = m2dFile.GetDocument(entry.FileHeader);
                XmlNodeList contributions = document.SelectNodes("/ms2/contribution");

                foreach (XmlNode contribution in contributions)
                {
                    string type  = contribution.Attributes["type"].Value;
                    int    value = int.Parse(contribution.Attributes["value"].Value);

                    guildMetadata.Contribution.Add(new GuildContribution(type, value));
                }
            }

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

                // Parse XML
                XmlDocument document = m2dFile.GetDocument(entry.FileHeader);
                XmlNodeList buffs    = document.SelectNodes("/ms2/guildBuff");

                foreach (XmlNode buff in buffs)
                {
                    int   id               = int.Parse(buff.Attributes["id"].Value);
                    byte  level            = byte.Parse(buff.Attributes["level"].Value);
                    int   effectId         = int.Parse(buff.Attributes["additionalEffectId"].Value);
                    byte  effectLevel      = byte.Parse(buff.Attributes["additionalEffectLevel"].Value);
                    byte  levelRequirement = byte.Parse(buff.Attributes["requireLevel"].Value);
                    int   upgradeCost      = int.Parse(buff.Attributes["upgradeCost"].Value);
                    int   cost             = int.Parse(buff.Attributes["cost"].Value);
                    short duration         = short.Parse(buff.Attributes["duration"].Value);

                    guildMetadata.Buff.Add(new GuildBuff(id, level, effectId, effectLevel, levelRequirement, upgradeCost, cost, duration));
                }
            }

            return(guildMetadata);
        }
예제 #2
0
        public static PrestigeMetadata Parse(MemoryMappedFile m2dFile, IEnumerable <PackFileEntry> entries)
        {
            PrestigeMetadata prestigeMetadata = new PrestigeMetadata();

            foreach (PackFileEntry entry in entries)
            {
                // Only check for reward for now, abilities will need to be added later
                if (!entry.Name.StartsWith("table/adventurelevelreward"))
                {
                    continue;
                }

                // Parse XML
                XmlDocument document = m2dFile.GetDocument(entry.FileHeader);
                XmlNodeList rewards  = document.SelectNodes("/ms2/reward");

                foreach (XmlNode reward in rewards)
                {
                    int    level = int.Parse(reward.Attributes["level"].Value);
                    string type  = reward.Attributes["type"].Value;
                    int    id    = int.Parse(reward.Attributes["id"].Value.Length == 0 ? "0" : reward.Attributes["id"].Value);
                    int    value = int.Parse(reward.Attributes["value"].Value);

                    prestigeMetadata.Rewards.Add(new PrestigeReward(level, type, id, value));
                }
            }

            return(prestigeMetadata);
        }
예제 #3
0
        public static List <MapEntityMetadata> Parse(MemoryMappedFile m2dFile, IEnumerable <PackFileEntry> entries)
        {
            List <MapEntityMetadata>    entities = new List <MapEntityMetadata>();
            Dictionary <string, string> maps     = new Dictionary <string, string>();

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

                string mapIdStr = Regex.Match(entry.Name, @"\d{8}").Value;
                if (string.IsNullOrEmpty(mapIdStr))
                {
                    continue;
                }
                int mapId = int.Parse(mapIdStr);
                if (maps.ContainsKey(mapIdStr))
                {
                    Console.WriteLine($"Duplicate {entry.Name} was already added as {maps[mapIdStr]}");
                    continue;
                }
                maps.Add(mapIdStr, entry.Name);

                MapEntityMetadata metadata    = new MapEntityMetadata(mapId);
                XmlDocument       document    = m2dFile.GetDocument(entry.FileHeader);
                XmlNodeList       mapEntities = document.SelectNodes("/game/entitySet/entity");

                foreach (XmlNode node in mapEntities)
                {
                    if (node.Attributes["name"].Value.Contains("SpawnPointPC"))
                    {
                        XmlNode playerCoord    = node.SelectSingleNode("property[@name='Position']");
                        XmlNode playerRotation = node.SelectSingleNode("property[@name='Rotation']");

                        string playerPositionValue = playerCoord?.FirstChild.Attributes["value"].Value ?? "0, 0, 0";
                        string playerRotationValue = playerRotation?.FirstChild.Attributes["value"].Value ?? "0, 0, 0";

                        metadata.PlayerSpawns.Add(new MapPlayerSpawn(ParseCoord(playerPositionValue), ParseCoord(playerRotationValue)));
                    }
                }

                //XmlNodeList nodes = document.SelectNodes("/game/entitySet/entity/property[@name='NpcList']");
                XmlNodeList nodes = document.SelectNodes("/game/entitySet/entity/property");
                foreach (XmlNode node in nodes)
                {
                    if (node.Attributes["name"].Value == "NpcList")
                    {
                        if (node.FirstChild != null)
                        {
                            XmlNode parent = node.ParentNode;
                            try
                            {
                                XmlNode coordNode    = parent.SelectSingleNode("property[@name='Position']");
                                XmlNode rotationNode = parent.SelectSingleNode("property[@name='Rotation']");

                                int    npcId         = int.Parse(node.FirstChild.Attributes["index"].Value);
                                string positionValue = coordNode?.FirstChild.Attributes["value"].Value ?? "0, 0, 0";
                                string rotationValue = rotationNode?.FirstChild.Attributes["value"].Value ?? "0, 0, 0";

                                CoordS position = ParseCoord(positionValue);
                                CoordS rotation = ParseCoord(rotationValue);
                                metadata.Npcs.Add(new MapNpc(npcId, position, rotation));
                            }
                            catch (Exception ex)
                            {
                                Console.WriteLine(ex);
                                Console.WriteLine(mapId);
                                Console.WriteLine("Failed NPC " + parent.InnerXml);
                            }
                        }
                    }
                    else if (node.Attributes["name"].Value == "PortalID")
                    {
                        XmlNode parent = node.ParentNode;
                        try
                        {
                            XmlNode visibleNode        = parent.SelectSingleNode("property[@name='IsVisible']");
                            XmlNode enabledNode        = parent.SelectSingleNode("property[@name='PortalEnable']");
                            XmlNode minimapVisibleNode = parent.SelectSingleNode("property[@name='MinimapIconVisible']");
                            XmlNode targetNode         = parent.SelectSingleNode("property[@name='TargetFieldSN']");
                            XmlNode coordNode          = parent.SelectSingleNode("property[@name='Position']");
                            XmlNode rotationNode       = parent.SelectSingleNode("property[@name='Rotation']");
                            if (targetNode == null)
                            {
                                continue;
                            }

                            if (!bool.TryParse(visibleNode?.FirstChild.Attributes["value"].Value,
                                               out bool visibleValue))
                            {
                                visibleValue = true;
                            }
                            if (!bool.TryParse(enabledNode?.FirstChild.Attributes["value"].Value,
                                               out bool enabledValue))
                            {
                                enabledValue = true;
                            }
                            if (!bool.TryParse(minimapVisibleNode?.FirstChild.Attributes["value"].Value,
                                               out bool minimapVisibleValue))
                            {
                                minimapVisibleValue = true;
                            }

                            int    target        = int.Parse(targetNode.FirstChild.Attributes["value"].Value);
                            int    portalId      = int.Parse(node.FirstChild.Attributes["value"].Value);
                            string positionValue = coordNode?.FirstChild.Attributes["value"].Value ?? "0, 0, 0";
                            string rotationValue = rotationNode?.FirstChild.Attributes["value"].Value ?? "0, 0, 0";


                            MapPortalFlag flags = visibleValue ? MapPortalFlag.Visible : MapPortalFlag.None;
                            flags |= enabledValue ? MapPortalFlag.Enabled : MapPortalFlag.None;
                            flags |= minimapVisibleValue ? MapPortalFlag.MinimapVisible : MapPortalFlag.None;

                            CoordS position = ParseCoord(positionValue);
                            CoordS rotation = ParseCoord(rotationValue);
                            metadata.Portals.Add(new MapPortal(portalId, flags, target, position, rotation));
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex);
                            Console.WriteLine(mapId);
                            Console.WriteLine("Failed NPC " + parent.InnerXml);
                        }
                    }
                }

                // No data on this map
                if (metadata.Npcs.Count == 0 && metadata.Portals.Count == 0 && metadata.PlayerSpawns.Count == 0)
                {
                    continue;
                }

                entities.Add(metadata);
            }

            return(entities);
        }
예제 #4
0
        public static List <ItemMetadata> Parse(MemoryMappedFile m2dFile, IEnumerable <PackFileEntry> entries)
        {
            List <ItemMetadata> items = new List <ItemMetadata>();

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

                ItemMetadata metadata = new ItemMetadata();
                string       itemId   = Path.GetFileNameWithoutExtension(entry.Name);

                if (items.Exists(item => item.Id.ToString() == itemId))
                {
                    //Console.WriteLine($"Duplicate {entry.Name} was already added.");
                    continue;
                }

                metadata.Id = int.Parse(itemId);
                Debug.Assert(metadata.Id > 0, $"Invalid Id {metadata.Id} from {itemId}");

                using XmlReader reader = m2dFile.GetReader(entry.FileHeader);
                while (reader.Read())
                {
                    if (reader.NodeType != XmlNodeType.Element)
                    {
                        continue;
                    }

                    if (reader.Name == "slot")
                    {
                        bool result = Enum.TryParse <ItemSlot>(reader["name"], out metadata.Slot);
                        if (!result && !string.IsNullOrEmpty(reader["name"]))
                        {
                            throw new ArgumentException("Failed to parse item slot:" + reader["name"]);
                        }
                    }

                    else if (reader.Name == "gem")
                    {
                        bool result = Enum.TryParse <GemSlot>(reader["system"], out metadata.Gem);
                        if (!result && !string.IsNullOrEmpty(reader["system"]))
                        {
                            throw new ArgumentException("Failed to parse item slot:" + reader["system"]);
                        }
                    }

                    else if (reader.Name == "property")
                    {
                        try
                        {
                            byte type    = byte.Parse(reader["type"]);
                            byte subType = byte.Parse(reader["subtype"]);
                            bool skin    = byte.Parse(reader["skin"]) != 0;
                            metadata.Tab        = GetTab(type, subType, skin);
                            metadata.IsTemplate = byte.Parse(reader["skinType"] ?? "0") == 99;
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine($"Failed {itemId}: {e.Message}");
                        }

                        metadata.SlotMax = int.Parse(reader["slotMax"]);
                    }

                    else if (reader.Name == "option")
                    {
                        int rarity = 1;

                        if (reader["constant"].Length == 1)
                        {
                            rarity = int.Parse(reader["constant"]);
                        }

                        metadata.Rarity = rarity;
                    }

                    else if (reader.Name == "function")
                    {
                        string contentType = reader["name"];

                        if (contentType != "OpenItemBox" && contentType != "SelectItemBox")
                        {
                            continue;
                        }

                        // selection boxes are SelectItemBox and 1,boxid
                        // normal boxes are OpenItemBox and 0,1,0,boxid
                        // fragments are OpenItemBox and 0,1,0,boxid,required_amount

                        List <string> parameters = new List <string>(reader["parameter"].Split(","));
                        // Remove empty params
                        parameters.RemoveAll(param => param.Length == 0);

                        if (parameters.Count < 2)
                        {
                            continue;
                        }

                        string boxId = contentType == "OpenItemBox" ? parameters[3] : parameters[1];

                        foreach (PackFileEntry innerEntry in entries)
                        {
                            if (!innerEntry.Name.StartsWith("table/individualitemdrop") && !innerEntry.Name.StartsWith("table/na/individualitemdrop"))
                            {
                                continue;
                            }

                            if (metadata.Content.Count > 0)
                            {
                                continue;
                            }

                            // Parse XML
                            XmlDocument document           = m2dFile.GetDocument(innerEntry.FileHeader);
                            XmlNodeList individualBoxItems = document.SelectNodes($"/ms2/individualDropBox[@individualDropBoxID={boxId}]");

                            foreach (XmlNode individualBoxItem in individualBoxItems)
                            {
                                int id            = int.Parse(individualBoxItem.Attributes["item"].Value);
                                int minAmount     = int.Parse(individualBoxItem.Attributes["minCount"].Value);
                                int maxAmount     = int.Parse(individualBoxItem.Attributes["maxCount"].Value);
                                int dropGroup     = int.Parse(individualBoxItem.Attributes["dropGroup"].Value);
                                int smartDropRate = string.IsNullOrEmpty(individualBoxItem.Attributes["smartDropRate"]?.Value) ? 0 : int.Parse(individualBoxItem.Attributes["smartDropRate"].Value);
                                int rarity        = string.IsNullOrEmpty(individualBoxItem.Attributes["PackageUIShowGrade"]?.Value) ? 0 : int.Parse(individualBoxItem.Attributes["PackageUIShowGrade"].Value);
                                int enchant       = string.IsNullOrEmpty(individualBoxItem.Attributes["enchantLevel"]?.Value) ? 0 : int.Parse(individualBoxItem.Attributes["enchantLevel"].Value);
                                int id2           = string.IsNullOrEmpty(individualBoxItem.Attributes["item2"]?.Value) ? 0 : int.Parse(individualBoxItem.Attributes["item2"].Value);

                                // Skip already existing item, this may need to check for locales but not certain
                                if (metadata.Content.Exists(content => content.Id == id))
                                {
                                    continue;
                                }

                                metadata.Content.Add(new ItemContent(id, minAmount, maxAmount, dropGroup, smartDropRate, rarity, enchant, id2));
                            }
                        }
                    }

                    else if (reader.Name == "MusicScore")
                    {
                        int playCount = int.Parse(reader["playCount"]);

                        metadata.PlayCount = playCount;
                    }

                    else if (reader.Name == "limit")
                    {
                        if (!string.IsNullOrEmpty(reader["recommendJobs"]))
                        {
                            List <string> temp = new List <string>(reader["recommendJobs"].Split(","));
                            foreach (string item in temp)
                            {
                                metadata.RecommendJobs.Add(int.Parse(item));
                            }
                        }
                    }
                }

                items.Add(metadata);
            }

            return(items);
        }
예제 #5
0
        public static List <SkillMetadata> Parse(MemoryMappedFile m2dFile, IEnumerable <PackFileEntry> entries)
        {
            List <SkillMetadata> skillList = new List <SkillMetadata>();

            foreach (PackFileEntry entry in entries)
            {
                // Parsing Skills
                if (entry.Name.StartsWith("skill"))
                {
                    string            skillId     = Path.GetFileNameWithoutExtension(entry.Name);
                    SkillMetadata     metadata    = new SkillMetadata();
                    List <SkillLevel> skillLevels = new List <SkillLevel>();

                    metadata.SkillId = int.Parse(skillId);
                    XmlDocument document = m2dFile.GetDocument(entry.FileHeader);
                    XmlNodeList levels   = document.SelectNodes("/ms2/level");
                    foreach (XmlNode level in levels)
                    {
                        // Getting all skills level
                        string feature    = level.Attributes["feature"] != null ? level.Attributes["feature"].Value : "";
                        int    levelValue = level.Attributes["value"].Value != null?int.Parse(level.Attributes["value"].Value) : 0;

                        int spirit = level.SelectSingleNode("consume/stat").Attributes["sp"] != null?int.Parse(level.SelectSingleNode("consume/stat").Attributes["sp"].Value) : 0;

                        float damageRate = level.SelectSingleNode("motion/attack/damageProperty") != null?float.Parse(level.SelectSingleNode("motion/attack/damageProperty").Attributes["rate"].Value) : 0;

                        skillLevels.Add(new SkillLevel(levelValue, spirit, damageRate, feature));
                    }
                    metadata.SkillLevels = skillLevels;
                    skillList.Add(metadata);
                }
                // Parsing SubSkills
                else if (entry.Name.StartsWith("table/job"))
                {
                    XmlDocument document = m2dFile.GetDocument(entry.FileHeader);
                    XmlNodeList jobs     = document.SelectNodes("/ms2/job");
                    foreach (XmlNode job in jobs)
                    {
                        if (job.Attributes["feature"] != null) // Getting attribute that just have "feature"
                        {
                            string feature = job.Attributes["feature"].Value;
                            if (feature == "JobChange_02") // Getting JobChange_02 skillList for now until better handle Awakening system.
                            {
                                XmlNode skills  = job.SelectSingleNode("skills");
                                int     jobCode = int.Parse(job.Attributes["code"].Value);
                                for (int i = 0; i < skills.ChildNodes.Count; i++)
                                {
                                    int           id    = int.Parse(skills.ChildNodes[i].Attributes["main"].Value);
                                    int[]         sub   = new int[0];
                                    SkillMetadata skill = skillList.Find(x => x.SkillId == id); // This find the skill in the SkillList
                                    skill.Job = jobCode;
                                    if (skills.ChildNodes[i].Attributes["sub"] != null)
                                    {
                                        if (skillList.Select(x => x.SkillId).Contains(id))
                                        {
                                            sub             = Array.ConvertAll(skills.ChildNodes[i].Attributes["sub"].Value.Split(","), int.Parse);
                                            skill.SubSkills = sub;
                                            for (int n = 0; n < sub.Length; n++)
                                            {
                                                if (skillList.Select(x => x.SkillId).Contains(sub[n]))
                                                {
                                                    skillList.Find(x => x.SkillId == sub[n]).Job = jobCode;
                                                }
                                            }
                                        }
                                    }
                                }
                                XmlNode learn = job.SelectSingleNode("learn");
                                for (int i = 0; i < learn.ChildNodes.Count; i++)
                                {
                                    int id = int.Parse(learn.ChildNodes[i].Attributes["id"].Value);
                                    skillList.Find(x => x.SkillId == id).Learned = 1;
                                }
                            }
                        }
                        else if (job.Attributes["code"].Value == "001")
                        {
                            XmlNode skills = job.SelectSingleNode("skills");

                            for (int i = 0; i < skills.ChildNodes.Count; i++)
                            {
                                int   id  = int.Parse(skills.ChildNodes[i].Attributes["main"].Value);
                                int[] sub = new int[0];
                                if (skills.ChildNodes[i].Attributes["sub"] != null)
                                {
                                    sub = Array.ConvertAll(skills.ChildNodes[i].Attributes["sub"].Value.Split(","), int.Parse);
                                }
                            }
                        }
                    }
                }
            }
            return(skillList);
        }
예제 #6
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);
        }
예제 #7
0
        public static List <SkillMetadata> Parse(MemoryMappedFile m2dFile, IEnumerable <PackFileEntry> entries)
        {
            List <SkillMetadata> skillList = new List <SkillMetadata>();

            foreach (PackFileEntry skill in entries)
            {
                if (!skill.Name.StartsWith("skill/10"))
                {
                    continue;
                }

                string             skillId    = Path.GetFileNameWithoutExtension(skill.Name);
                SkillMetadata      metadata   = new SkillMetadata();
                List <SkillMotion> motions    = new List <SkillMotion>();
                List <SkillLevel>  skillLevel = new List <SkillLevel>();

                metadata.SkillId = int.Parse(skillId);
                Debug.Assert(metadata.SkillId > 0, $"Invalid Id {metadata.SkillId} from {skillId}");

                //using XmlReader reader = m2dFile.GetReader(skill.FileHeader);
                XmlDocument document = m2dFile.GetDocument(skill.FileHeader);

                XmlNodeList basic = document.SelectNodes("/ms2/basic");
                foreach (XmlNode node in basic)
                {
                    if (node.Attributes.GetNamedItem("feature") != null)
                    {
                        // Get Rank
                        metadata.Feature = node.Attributes["feature"].Value;
                    }
                    XmlNode kinds = node.SelectSingleNode("kinds");
                    metadata.Type = kinds.Attributes["type"].Value != null?int.Parse(kinds.Attributes["type"].Value) : 0;

                    metadata.SubType = kinds.Attributes["subType"].Value != null?int.Parse(kinds.Attributes["subType"].Value) : 0;

                    metadata.RangeType = kinds.Attributes["rangeType"].Value != null?int.Parse(kinds.Attributes["rangeType"].Value) : 0;

                    metadata.Element = kinds.Attributes["element"].Value != null?int.Parse(kinds.Attributes["element"].Value) : 0;
                }

                XmlNodeList levels = document.SelectNodes("/ms2/level");
                foreach (XmlNode node in levels)
                {
                    int level = node.Attributes["value"].Value != null?int.Parse(node.Attributes["value"].Value) : 1;

                    XmlNode consume = node.SelectSingleNode("consume/stat");

                    int   spirit            = 0;
                    int   upgradeLevel      = 0;
                    int[] upgradeSkillId    = new int[0];
                    int[] upgradeSkillLevel = new int[0];

                    if (consume.Attributes.GetNamedItem("sp") != null)
                    {
                        spirit = int.Parse(consume.Attributes["sp"].Value);
                    }

                    XmlNode upgrade = node.SelectSingleNode("upgrade");
                    if (upgrade.Attributes != null)
                    {
                        if (upgrade.Attributes.GetNamedItem("level") != null)
                        {
                            upgradeLevel = int.Parse(upgrade.Attributes["level"].Value);
                        }
                        if (upgrade.Attributes.GetNamedItem("skillIDs") != null)
                        {
                            upgradeSkillId = Array.ConvertAll(upgrade.Attributes.GetNamedItem("skillIDs").Value.Split(","), int.Parse);
                        }
                        if (upgrade.Attributes.GetNamedItem("skillLevels") != null)
                        {
                            upgradeSkillLevel = Array.ConvertAll(upgrade.Attributes.GetNamedItem("skillLevels").Value.Split(","), int.Parse);
                        }
                    }

                    XmlNode motion = node.SelectSingleNode("motion/motionProperty");

                    string sequenceName  = "";
                    string motionEffect  = "";
                    string strTagEffects = "";

                    if (motion.Attributes != null)
                    {
                        if (motion.Attributes.GetNamedItem("sequenceName") != null)
                        {
                            sequenceName = motion.Attributes["sequenceName"].Value;
                        }
                        if (motion.Attributes.GetNamedItem("motionEffect") != null)
                        {
                            motionEffect = motion.Attributes["motionEffect"].Value;
                        }
                        if (motion.Attributes.GetNamedItem("strTagEffects") != null)
                        {
                            strTagEffects = motion.Attributes["strTagEffects"].Value;
                        }
                    }
                    motions.Add(new SkillMotion(sequenceName, motionEffect, strTagEffects));
                    metadata.SkillLevel.Add(new SkillLevel(level, spirit, upgradeLevel, upgradeSkillId, upgradeSkillLevel, motions));
                }

                skillList.Add(metadata);
            }
            return(skillList);
        }
예제 #8
0
        public static List <SkillMetadata> Parse(MemoryMappedFile m2dFile, IEnumerable <PackFileEntry> entries)
        {
            List <SkillMetadata> skillList = new List <SkillMetadata>();

            foreach (PackFileEntry skill in entries)
            {
                if (!skill.Name.StartsWith("skill"))
                {
                    continue;
                }

                string            skillId    = Path.GetFileNameWithoutExtension(skill.Name);
                SkillMetadata     metadata   = new SkillMetadata();
                List <SkillLevel> skillLevel = new List <SkillLevel>();

                metadata.SkillId = int.Parse(skillId);
                Debug.Assert(metadata.SkillId > 0, $"Invalid Id {metadata.SkillId} from {skillId}");

                //using XmlReader reader = m2dFile.GetReader(skill.FileHeader);
                XmlDocument document = m2dFile.GetDocument(skill.FileHeader);

                XmlNodeList basic = document.SelectNodes("/ms2/basic");
                foreach (XmlNode node in basic)
                {
                    if (node.Attributes.GetNamedItem("feature") != null)
                    {
                        // Get Rank
                        metadata.Feature = node.Attributes["feature"].Value;
                    }
                    XmlNode kinds = node.SelectSingleNode("kinds");
                    metadata.Type = kinds.Attributes["type"].Value != null?int.Parse(kinds.Attributes["type"].Value) : 0;

                    if (kinds.Attributes.GetNamedItem("subType") != null)
                    {
                        // Get Rank
                        metadata.SubType = kinds.Attributes["subType"].Value != null?int.Parse(kinds.Attributes["subType"].Value) : 0;
                    }
                    XmlNode stateAttr = node.SelectSingleNode("stateAttr");
                    if (stateAttr.Attributes.GetNamedItem("useDefaultSkill") != null)
                    {
                        // Get Rank
                        metadata.DefaultSkill = stateAttr.Attributes["useDefaultSkill"].Value != null?byte.Parse(stateAttr.Attributes["useDefaultSkill"].Value) : 0;
                    }
                }

                XmlNodeList levels = document.SelectNodes("/ms2/level");
                foreach (XmlNode node in levels)
                {
                    if (node.Attributes.GetNamedItem("feature") == null || node.Attributes.GetNamedItem("feature").Value == metadata.Feature)
                    {
                        int level = node.Attributes["value"].Value != null?int.Parse(node.Attributes["value"].Value) : 1;

                        XmlNode consume = node.SelectSingleNode("consume/stat");

                        int   spirit            = 0;
                        int   upgradeLevel      = 0;
                        int[] upgradeSkillId    = new int[0];
                        int[] upgradeSkillLevel = new int[0];

                        if (consume.Attributes.GetNamedItem("sp") != null)
                        {
                            spirit = int.Parse(consume.Attributes["sp"].Value);
                        }

                        XmlNode upgrade = node.SelectSingleNode("upgrade");
                        if (upgrade.Attributes != null)
                        {
                            if (upgrade.Attributes.GetNamedItem("level") != null)
                            {
                                upgradeLevel = int.Parse(upgrade.Attributes["level"].Value);
                            }
                            if (upgrade.Attributes.GetNamedItem("skillIDs") != null)
                            {
                                upgradeSkillId = Array.ConvertAll(upgrade.Attributes.GetNamedItem("skillIDs").Value.Split(","), int.Parse);
                            }
                            if (upgrade.Attributes.GetNamedItem("skillLevels") != null)
                            {
                                upgradeSkillLevel = Array.ConvertAll(upgrade.Attributes.GetNamedItem("skillLevels").Value.Split(","), int.Parse);
                            }
                        }
                        skillLevel.Add(new SkillLevel(level, spirit, upgradeLevel, upgradeSkillId, upgradeSkillLevel));
                        metadata.SkillLevel = skillLevel[0];
                    }
                }
                skillList.Add(metadata);
            }
            return(skillList);
        }
예제 #9
0
        public static List <ItemMetadata> Parse(MemoryMappedFile m2dFile, IEnumerable <PackFileEntry> entries)
        {
            List <ItemMetadata> items = new List <ItemMetadata>();

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

                ItemMetadata metadata = new ItemMetadata();
                string       itemId   = Path.GetFileNameWithoutExtension(entry.Name);

                if (items.Exists(item => item.Id.ToString() == itemId))
                {
                    //Console.WriteLine($"Duplicate {entry.Name} was already added.");
                    continue;
                }

                metadata.Id = int.Parse(itemId);
                Debug.Assert(metadata.Id > 0, $"Invalid Id {metadata.Id} from {itemId}");

                // Parse XML
                XmlDocument document = m2dFile.GetDocument(entry.FileHeader);
                XmlNode     item     = document.SelectSingleNode("ms2/environment");

                // Gear/Cosmetic slot
                XmlNode slots      = item.SelectSingleNode("slots");
                XmlNode slot       = slots.FirstChild;
                bool    slotResult = Enum.TryParse <ItemSlot>(slot.Attributes["name"].Value, out metadata.Slot);
                if (!slotResult && !string.IsNullOrEmpty(slot.Attributes["name"].Value))
                {
                    Console.WriteLine($"Failed to parse item slot for {itemId}: {slot.Attributes["name"].Value}");
                }
                int totalSlots = slots.SelectNodes("slot").Count;
                metadata.IsTwoHand = totalSlots > 1;

                // Badge slot
                XmlNode gem       = item.SelectSingleNode("gem");
                bool    gemResult = Enum.TryParse <GemSlot>(gem.Attributes["system"].Value, out metadata.Gem);
                if (!gemResult && !string.IsNullOrEmpty(gem.Attributes["system"].Value))
                {
                    Console.WriteLine($"Failed to parse badge slot for {itemId}: {gem.Attributes["system"].Value}");
                }

                // Inventory tab and max stack size
                XmlNode property = item.SelectSingleNode("property");
                try
                {
                    byte type    = byte.Parse(property.Attributes["type"].Value);
                    byte subType = byte.Parse(property.Attributes["subtype"].Value);
                    bool skin    = byte.Parse(property.Attributes["skin"].Value) != 0;
                    metadata.Tab        = GetTab(type, subType, skin);
                    metadata.IsTemplate = byte.Parse(property.Attributes["skinType"]?.Value ?? "0") == 99;
                }
                catch (Exception e)
                {
                    Console.WriteLine($"Failed to parse tab slot for {itemId}: {e.Message}");
                }
                metadata.StackLimit = int.Parse(property.Attributes["slotMax"].Value);

                // Rarity
                XmlNode option = item.SelectSingleNode("option");
                int     rarity = 1;
                if (option.Attributes["constant"].Value.Length == 1)
                {
                    rarity = int.Parse(option.Attributes["constant"].Value);
                }
                metadata.Rarity = rarity;

                // Item boxes
                XmlNode function    = item.SelectSingleNode("function");
                string  contentType = function.Attributes["name"].Value;
                if (contentType == "OpenItemBox" || contentType == "SelectItemBox")
                {
                    // selection boxes are SelectItemBox and 1,boxid
                    // normal boxes are OpenItemBox and 0,1,0,boxid
                    // fragments are OpenItemBox and 0,1,0,boxid,required_amount
                    List <string> parameters = new List <string>(function.Attributes["parameter"].Value.Split(","));
                    // Remove empty params
                    parameters.RemoveAll(param => param.Length == 0);

                    if (parameters.Count >= 2)
                    {
                        string boxId = contentType == "OpenItemBox" ? parameters[3] : parameters[1];

                        foreach (PackFileEntry innerEntry in entries)
                        {
                            if (!innerEntry.Name.StartsWith("table/individualitemdrop") && !innerEntry.Name.StartsWith("table/na/individualitemdrop"))
                            {
                                continue;
                            }

                            if (metadata.Content.Count > 0)
                            {
                                continue;
                            }

                            // Parse XML
                            XmlDocument innerDocument      = m2dFile.GetDocument(innerEntry.FileHeader);
                            XmlNodeList individualBoxItems = innerDocument.SelectNodes($"/ms2/individualDropBox[@individualDropBoxID={boxId}]");

                            foreach (XmlNode individualBoxItem in individualBoxItems)
                            {
                                int id            = int.Parse(individualBoxItem.Attributes["item"].Value);
                                int minAmount     = int.Parse(individualBoxItem.Attributes["minCount"].Value);
                                int maxAmount     = int.Parse(individualBoxItem.Attributes["maxCount"].Value);
                                int dropGroup     = int.Parse(individualBoxItem.Attributes["dropGroup"].Value);
                                int smartDropRate = string.IsNullOrEmpty(individualBoxItem.Attributes["smartDropRate"]?.Value) ? 0 : int.Parse(individualBoxItem.Attributes["smartDropRate"].Value);
                                int contentRarity = string.IsNullOrEmpty(individualBoxItem.Attributes["PackageUIShowGrade"]?.Value) ? 0 : int.Parse(individualBoxItem.Attributes["PackageUIShowGrade"].Value);
                                int enchant       = string.IsNullOrEmpty(individualBoxItem.Attributes["enchantLevel"]?.Value) ? 0 : int.Parse(individualBoxItem.Attributes["enchantLevel"].Value);
                                int id2           = string.IsNullOrEmpty(individualBoxItem.Attributes["item2"]?.Value) ? 0 : int.Parse(individualBoxItem.Attributes["item2"].Value);

                                // Skip already existing item
                                if (metadata.Content.Exists(content => content.Id == id))
                                {
                                    continue;
                                }

                                // Skip locales other than NA in table/na
                                if (innerEntry.Name.StartsWith("table/na/individualitemdrop") && individualBoxItem.Attributes["locale"] != null)
                                {
                                    if (!individualBoxItem.Attributes["locale"].Value.Equals("NA"))
                                    {
                                        continue;
                                    }
                                }

                                metadata.Content.Add(new ItemContent(id, minAmount, maxAmount, dropGroup, smartDropRate, contentRarity, enchant, id2));
                            }
                        }
                    }
                }

                // Music score charges
                XmlNode musicScore = item.SelectSingleNode("MusicScore");
                int     playCount  = int.Parse(musicScore.Attributes["playCount"].Value);
                metadata.PlayCount = playCount;

                // Recommended jobs
                XmlNode limit = item.SelectSingleNode("limit");
                if (!string.IsNullOrEmpty(limit.Attributes["recommendJobs"].Value))
                {
                    List <string> recommendJobs = new List <string>(limit.Attributes["recommendJobs"].Value.Split(","));
                    foreach (string recommendJob in recommendJobs)
                    {
                        metadata.RecommendJobs.Add(int.Parse(recommendJob));
                    }
                }

                items.Add(metadata);
            }

            return(items);
        }
예제 #10
0
        public static List <MapEntityMetadata> Parse(MemoryMappedFile m2dFile, IEnumerable <PackFileEntry> entries)
        {
            // Iterate over preset objects to later reference while iterating over exported maps
            Dictionary <string, string> mapObjects = new Dictionary <string, string>();

            foreach (PackFileEntry entry in entries)
            {
                if (!entry.Name.StartsWith("flat/presets/presets object/"))
                {
                    continue;
                }

                // Check if file is valid
                string objStr = entry.Name.ToLower();
                if (string.IsNullOrEmpty(objStr))
                {
                    continue;
                }
                if (mapObjects.ContainsKey(objStr))
                {
                    Console.WriteLine($"Duplicate {entry.Name} was already added as {mapObjects[objStr]}");
                    continue;
                }

                // Parse XML
                XmlDocument document      = m2dFile.GetDocument(entry.FileHeader);
                XmlElement  root          = document.DocumentElement;
                XmlNodeList objProperties = document.SelectNodes("/model/property");

                string objectName = root.Attributes["name"].Value.ToLower();

                foreach (XmlNode node in objProperties)
                {
                    // Storing only weapon item code for now, but there are other uses
                    if (node.Attributes["name"].Value.Contains("ObjectWeaponItemCode"))
                    {
                        string weaponId = node?.FirstChild.Attributes["value"].Value ?? "0";

                        if (!weaponId.Equals("0"))
                        {
                            mapObjects.Add(objectName, weaponId);
                        }
                    }
                }
            }

            // Iterate over map xblocks
            List <MapEntityMetadata>    entities = new List <MapEntityMetadata>();
            Dictionary <string, string> maps     = new Dictionary <string, string>();

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

                string mapIdStr = Regex.Match(entry.Name, @"\d{8}").Value;
                if (string.IsNullOrEmpty(mapIdStr))
                {
                    continue;
                }
                int mapId = int.Parse(mapIdStr);
                if (maps.ContainsKey(mapIdStr))
                {
                    Console.WriteLine($"Duplicate {entry.Name} was already added as {maps[mapIdStr]}");
                    continue;
                }
                maps.Add(mapIdStr, entry.Name);

                MapEntityMetadata metadata    = new MapEntityMetadata(mapId);
                XmlDocument       document    = m2dFile.GetDocument(entry.FileHeader);
                XmlNodeList       mapEntities = document.SelectNodes("/game/entitySet/entity");

                foreach (XmlNode node in mapEntities)
                {
                    string modelName = node.Attributes["modelName"].Value.ToLower();

                    if (node.Attributes["name"].Value.Contains("SpawnPointPC"))
                    {
                        XmlNode playerCoord    = node.SelectSingleNode("property[@name='Position']");
                        XmlNode playerRotation = node.SelectSingleNode("property[@name='Rotation']");

                        string playerPositionValue = playerCoord?.FirstChild.Attributes["value"].Value ?? "0, 0, 0";
                        string playerRotationValue = playerRotation?.FirstChild.Attributes["value"].Value ?? "0, 0, 0";

                        metadata.PlayerSpawns.Add(new MapPlayerSpawn(ParseCoord(playerPositionValue), ParseCoord(playerRotationValue)));
                    }
                    else if (mapObjects.ContainsKey(modelName))
                    {
                        string nameCoord = node.Attributes["name"].Value.ToLower();

                        Match coordMatch = Regex.Match(nameCoord, @"[\-]?\d+[,]\s[\-]?\d+[,]\s[\-]?\d+");

                        if (!coordMatch.Success)
                        {
                            continue;
                        }

                        CoordB coord = CoordB.Parse(coordMatch.Value, ", ");
                        metadata.Objects.Add(new MapObject(coord, int.Parse(mapObjects[modelName])));
                    }
                }

                //XmlNodeList nodes = document.SelectNodes("/game/entitySet/entity/property[@name='NpcList']");
                XmlNodeList nodes = document.SelectNodes("/game/entitySet/entity/property");
                foreach (XmlNode node in nodes)
                {
                    if (node.Attributes["name"].Value == "NpcList")
                    {
                        if (node.FirstChild != null)
                        {
                            XmlNode parent = node.ParentNode;
                            try
                            {
                                XmlNode coordNode    = parent.SelectSingleNode("property[@name='Position']");
                                XmlNode rotationNode = parent.SelectSingleNode("property[@name='Rotation']");

                                int    npcId         = int.Parse(node.FirstChild.Attributes["index"].Value);
                                string positionValue = coordNode?.FirstChild.Attributes["value"].Value ?? "0, 0, 0";
                                string rotationValue = rotationNode?.FirstChild.Attributes["value"].Value ?? "0, 0, 0";

                                CoordS position = ParseCoord(positionValue);
                                CoordS rotation = ParseCoord(rotationValue);
                                metadata.Npcs.Add(new MapNpc(npcId, position, rotation));
                            }
                            catch (Exception ex)
                            {
                                Console.WriteLine(ex);
                                Console.WriteLine(mapId);
                                Console.WriteLine("Failed NPC " + parent.InnerXml);
                            }
                        }
                    }
                    else if (node.Attributes["name"].Value == "PortalID")
                    {
                        XmlNode parent = node.ParentNode;
                        try
                        {
                            XmlNode visibleNode        = parent.SelectSingleNode("property[@name='IsVisible']");
                            XmlNode enabledNode        = parent.SelectSingleNode("property[@name='PortalEnable']");
                            XmlNode minimapVisibleNode = parent.SelectSingleNode("property[@name='MinimapIconVisible']");
                            XmlNode targetNode         = parent.SelectSingleNode("property[@name='TargetFieldSN']");
                            XmlNode coordNode          = parent.SelectSingleNode("property[@name='Position']");
                            XmlNode rotationNode       = parent.SelectSingleNode("property[@name='Rotation']");
                            if (targetNode == null)
                            {
                                continue;
                            }

                            if (!bool.TryParse(visibleNode?.FirstChild.Attributes["value"].Value,
                                               out bool visibleValue))
                            {
                                visibleValue = true;
                            }
                            if (!bool.TryParse(enabledNode?.FirstChild.Attributes["value"].Value,
                                               out bool enabledValue))
                            {
                                enabledValue = true;
                            }
                            if (!bool.TryParse(minimapVisibleNode?.FirstChild.Attributes["value"].Value,
                                               out bool minimapVisibleValue))
                            {
                                minimapVisibleValue = true;
                            }

                            int    target        = int.Parse(targetNode.FirstChild.Attributes["value"].Value);
                            int    portalId      = int.Parse(node.FirstChild.Attributes["value"].Value);
                            string positionValue = coordNode?.FirstChild.Attributes["value"].Value ?? "0, 0, 0";
                            string rotationValue = rotationNode?.FirstChild.Attributes["value"].Value ?? "0, 0, 0";


                            MapPortalFlag flags = visibleValue ? MapPortalFlag.Visible : MapPortalFlag.None;
                            flags |= enabledValue ? MapPortalFlag.Enabled : MapPortalFlag.None;
                            flags |= minimapVisibleValue ? MapPortalFlag.MinimapVisible : MapPortalFlag.None;

                            CoordS position = ParseCoord(positionValue);
                            CoordS rotation = ParseCoord(rotationValue);
                            metadata.Portals.Add(new MapPortal(portalId, flags, target, position, rotation));
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex);
                            Console.WriteLine(mapId);
                            Console.WriteLine("Failed NPC " + parent.InnerXml);
                        }
                    }
                }

                // No data on this map
                if (metadata.Npcs.Count == 0 && metadata.Portals.Count == 0 && metadata.PlayerSpawns.Count == 0)
                {
                    continue;
                }

                entities.Add(metadata);
            }

            return(entities);
        }