コード例 #1
0
        public static async Task <bool> ExportBoss(Classes.Boss Boss)
        {
            Microsoft.Win32.SaveFileDialog saveDialog = new Microsoft.Win32.SaveFileDialog()
            {
                DefaultExt = ".cfg",
                Filter     = "FF2 Config Boss File (*.cfg)|*.cfg"
            };

            bool?saveResult = saveDialog.ShowDialog();

            if (saveResult == true)
            {
                try
                {
                    using (var file = File.CreateText(saveDialog.FileName))
                    {
                        string cfg = "";

                        //"CFG Generated by" comment
                        cfg += "//This Configuration File was made using JPZV's FF2 Boss Editor" + NEWLINE;

                        //Root Start
                        cfg += "\"character\"" + NEWLINE + "{" + NEWLINE;

                        //Boss basic info
                        cfg += "//Boss Basic Info" + NEWLINE;
                        cfg += NodeCreator("name", Boss.Name, 1, 14, "Boss public name.");
                        cfg += NodeCreator("class", Boss.Class.ToString(), 1, 14, "Boss based TF2 class.");
                        cfg += NodeCreator("model", Boss.Model, 1, 14, "Boss model.");
                        cfg += NodeCreator("ragedamage", Boss.RageDamage.ToString(), 1, 14, "Boss rage damage formula. (Accepted operators in FreakFortressBat: n, +, -, *, /, ^)");
                        cfg += NodeCreator("ragedist", Boss.RageDist.ToString(), 1, 14, "Boss rage distance.");
                        cfg += NodeCreator("health_formula", Boss.Health, 1, 14, "Boss health formula. (Accepted operators: n, +, -, *, /, ^)");
                        cfg += NodeCreator("maxspeed", Boss.Speed.ToString(), 1, 14, "Boss max speed.");
                        cfg += NEWLINE;

                        //Boss description
                        cfg += "//Boss Description(s)" + NEWLINE;
                        foreach (Classes.Description desc in Boss.Descriptions)
                        {
                            cfg += NodeCreator(string.Format("description_{0}", desc.Lang), desc.Text.Replace("\r\n", "\n").Replace("\n", "\\n"), 1, 14);
                        }
                        cfg += NEWLINE;

                        //Weapons
                        int wepCount = 1;
                        cfg += "//Boss Weapon(s)" + NEWLINE;
                        foreach (Classes.Weapon wep in Boss.Weapons)
                        {
                            cfg += string.Format("\t\"weapon{0}\"", wepCount) + NEWLINE;
                            cfg += "\t{" + NEWLINE;
                            cfg += NodeCreator("name", wep.Class, 2, 10, "Weapon Class (Name).");
                            cfg += NodeCreator("index", wep.Index.ToString(), 2, 10, "Weapon Index.");
                            string attrStr = "";
                            foreach (Classes.Weapon.Attribute attr in wep.Attributes)
                            {
                                if (attrStr != "")
                                {
                                    attrStr += " ; ";
                                }
                                attrStr += string.Format("{0} ; {1}", attr.ID, attr.Arg);
                            }
                            cfg += NodeCreator("attributes", attrStr, 2, 10, "Weapon attributes.");
                            cfg += NodeCreator("show", wep.Visible ? "1" : "0", 2, 10, "Weapon visibility. (0: Invisible. 1: Visible)");
                            cfg += "\t}" + NEWLINE;
                            wepCount++;
                        }
                        cfg += NEWLINE;

                        //Abilities
                        int abiCount = 1;
                        cfg += "//Boss Ability(s)" + NEWLINE;
                        foreach (Classes.Ability abi in Boss.Abilities)
                        {
                            cfg += string.Format("\t\"ability{0}\"", abiCount) + NEWLINE;
                            cfg += "\t{" + NEWLINE;

                            int maxArgIndex   = abi.Arguments.Max(t => t.Index);
                            int interSepCount = maxArgIndex.ToString().Length + 3 > 11 ? maxArgIndex.ToString().Length + 3 : 11;

                            cfg += NodeCreator("name", abi.Name, 2, interSepCount, "Ability Name.") + NEWLINE;

                            foreach (Classes.Ability.Argument arg in abi.Arguments)
                            {
                                cfg += NodeCreator("arg" + arg.Index, arg.Value, 2, interSepCount, arg.Alias);
                            }

                            cfg += NEWLINE;

                            cfg += NodeCreator("plugin_name", abi.Plugin, 2, interSepCount, "Ability Plugin (without the extension).");
                            cfg += "\t}" + NEWLINE;
                            abiCount++;
                        }
                        cfg += NEWLINE;

                        //Sounds
                        //Music
                        cfg += "//Sound(s)" + NEWLINE;
                        int           i;
                        List <string> allSoundsPath = new List <string>();
                        cfg += "\t\"sound_bgm\"" + NEWLINE;
                        cfg += "\t{" + NEWLINE;
                        int maxMusicIndex = Boss.Sounds.Music.Count.ToString().Length + 6;
                        for (i = 0; i < Boss.Sounds.Music.Count; i++)
                        {
                            cfg += NodeCreator("path" + (i + 1).ToString(), RemoveSoundFromPath(Boss.Sounds.Music[i].Path), 2, maxMusicIndex, "Path relative to 'sound' folder.");
                            cfg += NodeCreator("time" + (i + 1).ToString(), Boss.Sounds.Music[i].Length.ToString(), 2, maxMusicIndex, "Music's length in seconds.");
                            cfg += NodeCreator("name" + (i + 1).ToString(), Boss.Sounds.Music[i].Name.ToString(), 2, maxMusicIndex, "Music's name.");
                            cfg += NodeCreator("artist" + (i + 1).ToString(), Boss.Sounds.Music[i].Artist.ToString(), 2, maxMusicIndex, "Music's artist.");
                            allSoundsPath.Add(Boss.Sounds.Music[i].Path);
                        }
                        cfg += "\t}" + NEWLINE;

                        //Startup
                        cfg += "\t\"sound_begin\"" + NEWLINE;
                        cfg += "\t{" + NEWLINE;
                        for (i = 0; i < Boss.Sounds.Startup.Count; i++)
                        {
                            cfg += NodeCreator((i + 1).ToString(), RemoveSoundFromPath(Boss.Sounds.Startup[i].Path), 2, 3, "Path relative to 'sound' folder.");
                            allSoundsPath.Add(Boss.Sounds.Startup[i].Path);
                        }
                        cfg += "\t}" + NEWLINE;

                        //Victory
                        cfg += "\t\"sound_win\"" + NEWLINE;
                        cfg += "\t{" + NEWLINE;
                        for (i = 0; i < Boss.Sounds.Victory.Count; i++)
                        {
                            cfg += NodeCreator((i + 1).ToString(), RemoveSoundFromPath(Boss.Sounds.Victory[i].Path), 2, 3, "Path relative to 'sound' folder.");
                            allSoundsPath.Add(Boss.Sounds.Victory[i].Path);
                        }
                        cfg += "\t}" + NEWLINE;

                        //LastMan
                        cfg += "\t\"sound_lastman\"" + NEWLINE;
                        cfg += "\t{" + NEWLINE;
                        for (i = 0; i < Boss.Sounds.LastMan.Count; i++)
                        {
                            cfg += NodeCreator((i + 1).ToString(), RemoveSoundFromPath(Boss.Sounds.LastMan[i].Path), 2, 3, "Path relative to 'sound' folder.");
                            allSoundsPath.Add(Boss.Sounds.LastMan[i].Path);
                        }
                        cfg += "\t}" + NEWLINE;

                        //Death
                        cfg += "\t\"sound_death\"" + NEWLINE;
                        cfg += "\t{" + NEWLINE;
                        for (i = 0; i < Boss.Sounds.Death.Count; i++)
                        {
                            cfg += NodeCreator((i + 1).ToString(), RemoveSoundFromPath(Boss.Sounds.Death[i].Path), 2, 3, "Path relative to 'sound' folder.");
                            allSoundsPath.Add(Boss.Sounds.Death[i].Path);
                        }
                        cfg += "\t}" + NEWLINE;

                        //Kill
                        cfg += "\t\"sound_hit\"" + NEWLINE;
                        cfg += "\t{" + NEWLINE;
                        for (i = 0; i < Boss.Sounds.KillPlayer.Count; i++)
                        {
                            cfg += NodeCreator((i + 1).ToString(), RemoveSoundFromPath(Boss.Sounds.KillPlayer[i].Path), 2, 3, "Path relative to 'sound' folder.");
                            allSoundsPath.Add(Boss.Sounds.KillPlayer[i].Path);
                        }
                        cfg += "\t}" + NEWLINE;

                        //Kill
                        cfg += "\t\"sound_kspree\"" + NEWLINE;
                        cfg += "\t{" + NEWLINE;
                        for (i = 0; i < Boss.Sounds.KillingSpree.Count; i++)
                        {
                            cfg += NodeCreator((i + 1).ToString(), RemoveSoundFromPath(Boss.Sounds.KillingSpree[i].Path), 2, 3, "Path relative to 'sound' folder.");
                            allSoundsPath.Add(Boss.Sounds.KillingSpree[i].Path);
                        }
                        cfg += "\t}" + NEWLINE;

                        //Ability
                        cfg += "\t\"sound_ability\"" + NEWLINE;
                        cfg += "\t{" + NEWLINE;
                        int maxAbiIndex = Boss.Sounds.Ability.Count.ToString().Length + 4;
                        for (i = 0; i < Boss.Sounds.Ability.Count; i++)
                        {
                            cfg += NodeCreator((i + 1).ToString(), RemoveSoundFromPath(Boss.Sounds.Ability[i].Path), 2, maxAbiIndex, "Path relative to 'sound' folder.");
                            if (Boss.Sounds.Ability[i].Slot != 0)
                            {
                                cfg += NodeCreator("slot" + (i + 1).ToString(), Boss.Sounds.Ability[i].Slot.ToString(), 2, maxAbiIndex, string.Format("Ability Slot {0}", Boss.Sounds.Ability[i].Slot));
                            }
                            allSoundsPath.Add(Boss.Sounds.Ability[i].Path);
                        }
                        cfg += "\t}" + NEWLINE;

                        //Catch
                        cfg += "\t\"catch_phrase\"" + NEWLINE;
                        cfg += "\t{" + NEWLINE;
                        for (i = 0; i < Boss.Sounds.CatchPhrase.Count; i++)
                        {
                            cfg += NodeCreator((i + 1).ToString(), RemoveSoundFromPath(Boss.Sounds.CatchPhrase[i].Path), 2, 3, "Path relative to 'sound' folder.");
                            allSoundsPath.Add(Boss.Sounds.CatchPhrase[i].Path);
                        }
                        cfg += "\t}" + NEWLINE;

                        //Backstab
                        cfg += "\t\"sound_stabbed\"" + NEWLINE;
                        cfg += "\t{" + NEWLINE;
                        for (i = 0; i < Boss.Sounds.Backstab.Count; i++)
                        {
                            cfg += NodeCreator((i + 1).ToString(), RemoveSoundFromPath(Boss.Sounds.Backstab[i].Path), 2, 3, "Path relative to 'sound' folder.");
                            allSoundsPath.Add(Boss.Sounds.Backstab[i].Path);
                        }
                        cfg += "\t}" + NEWLINE;

                        //Pre-Cache
                        cfg += "\t\"sound_precache\"" + NEWLINE;
                        cfg += "\t{" + NEWLINE;
                        for (i = 0; i < Boss.Sounds.Music.Count; i++)
                        {
                            cfg += NodeCreator((i + 1).ToString(), RemoveSoundFromPath(Boss.Sounds.Music[i].Path), 2, 3, "Path relative to 'sound' folder.");
                        }
                        cfg += "\t}" + NEWLINE;

                        cfg += NEWLINE;

                        //Downloads
                        List <string> allDownloadsPath = new List <string>(Boss.CustomFiles);
                        allDownloadsPath.AddRange(allSoundsPath);
                        List <string> fixedDownloadsPath = allDownloadsPath.GroupBy(t => t).Select(x => x.First()).ToList();
                        List <string> modDownloadPath    = new List <string>()
                        {
                            RemoveRootSlashFromPath(Boss.Model)
                        };
                        cfg += "//download(s)" + NEWLINE;
                        cfg += "\t\"download\"" + NEWLINE;
                        cfg += "\t{" + NEWLINE;
                        int maxDownloadIndex = fixedDownloadsPath.Count.ToString().Length;
                        for (i = 0; i < fixedDownloadsPath.Count; i++)
                        {
                            string fixedPath = fixedDownloadsPath[i].StartsWith("/") || fixedDownloadsPath[i].StartsWith("\\") ? RemoveRootSlashFromPath(fixedDownloadsPath[i]) : fixedDownloadsPath[i];
                            if (!fixedPath.StartsWith("models"))
                            {
                                cfg += NodeCreator((i + 1).ToString(), fixedPath, 2, maxDownloadIndex);
                            }
                            else if (fixedPath.EndsWith(".mdl"))
                            {
                                modDownloadPath.Add(fixedPath);
                            }
                        }
                        cfg += "\t}" + NEWLINE;
                        cfg += NEWLINE;

                        //Mod Download
                        cfg += "\t\"mod_download\"" + NEWLINE;
                        cfg += "\t{" + NEWLINE;
                        for (i = 0; i < modDownloadPath.Count; i++)
                        {
                            if (modDownloadPath[i].StartsWith("models"))
                            {
                                int mdlPos = modDownloadPath[i].IndexOf(".mdl");
                                if (mdlPos > 0)
                                {
                                    cfg += NodeCreator((i + 1).ToString(), modDownloadPath[i].Substring(0, mdlPos), 2, 3);
                                }
                            }
                        }
                        cfg += "\t}" + NEWLINE;

                        //Root ending
                        cfg += "}" + NEWLINE;

                        await file.WriteAsync(cfg);

                        return(true);
                    }
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine(ex.ToString());
                }
            }
            return(false);
        }
コード例 #2
0
        public static async Task <Classes.Boss> ImportBoss()
        {
            Microsoft.Win32.OpenFileDialog openDialog = new Microsoft.Win32.OpenFileDialog()
            {
                DefaultExt = ".cfg",
                Filter     = "FF2 Config Boss File (*.cfg)|*.cfg"
            };

            bool?openResult = openDialog.ShowDialog();

            if (openResult == true)
            {
                try
                {
                    using (StreamReader sr = new StreamReader(openDialog.FileName))
                    {
                        string cfg = await sr.ReadToEndAsync();

                        string json = "{" + NEWLINE;
                        foreach (string line in cfg.Split(new string[] { NEWLINE }, StringSplitOptions.None))
                        {
                            string neoLine = line.Replace("\\", "\\\\");
                            if (neoLine.Replace(" ", "").Replace("\t", "").StartsWith("//"))
                            {
                                continue;
                            }
                            Match keyValueRegex = Regex.Match(neoLine, "\"(.+?)\"[ \t]+\"(.*?)\"");
                            if (keyValueRegex.Success)
                            {
                                json += string.Format("\"{0}\": \"{1}\",{2}", keyValueRegex.Groups[1]?.Value.ToLower(), keyValueRegex.Groups[2], NEWLINE);
                                continue;
                            }
                            Match keyRegex = Regex.Match(neoLine, "\"(.+?)\"");
                            if (keyRegex.Success)
                            {
                                json += string.Format("\"{0}\":{1}", keyRegex.Groups[1]?.Value.ToLower(), NEWLINE);
                                continue;
                            }
                            if (neoLine.Replace(" ", "").Replace("\t", "").StartsWith("}"))
                            {
                                json += "}," + NEWLINE;
                                continue;
                            }
                            json += neoLine + NEWLINE;
                        }
                        json += NEWLINE + "}";

                        JObject openJson = JsonConvert.DeserializeObject <JObject>(json);

                        if (openJson["character"] is JObject boss)
                        {
                            Classes.Boss  openedBoss   = new Classes.Boss();
                            List <string> downloadList = new List <string>();
                            //Extracted from https://stackoverflow.com/questions/6522358/how-can-i-get-a-list-of-keys-from-json-net
                            foreach (string token in boss.Properties().Select(p => p.Name))
                            {
                                if (token == "name")
                                {
                                    openedBoss.Name = JTokenToString(boss[token]);
                                }
                                else if (token == "class")
                                {
                                    openedBoss.Class = JTokenToInt(boss[token]);
                                }
                                else if (token == "model")
                                {
                                    openedBoss.Model = JTokenToString(boss[token]);
                                }
                                else if (token == "ragedamage")
                                {
                                    openedBoss.RageDamage = JTokenToString(boss[token]);
                                }
                                else if (token == "ragedist")
                                {
                                    openedBoss.RageDist = JTokenToInt(boss[token]);
                                }
                                else if (token == "health_formula")
                                {
                                    openedBoss.Health = JTokenToString(boss[token]);
                                }
                                else if (token == "lives")
                                {
                                    openedBoss.Lives = JTokenToInt(boss[token]);
                                }
                                else if (token == "maxspeed")
                                {
                                    openedBoss.Speed = JTokenToInt(boss[token]);
                                }
                                else if (token == "sound_block_vo")
                                {
                                    openedBoss.BlockVoice = JTokenToInt(boss[token]) == 1;
                                }
                                else if (token.StartsWith("description"))
                                {
                                    Match descMatch = Regex.Match(token, "description_([a-z][a-z])");
                                    if (descMatch.Success && descMatch.Groups[1] != null && !string.IsNullOrWhiteSpace(descMatch.Groups[1].Value))
                                    {
                                        openedBoss.Descriptions.Add(new Classes.Description()
                                        {
                                            Lang = descMatch.Groups[1].Value,
                                            Text = JTokenToString(boss[token]).Replace("\\n\\n", "\\n").Replace("\\n", "\r\n")
                                        });
                                    }
                                }
                                else if (token.StartsWith("weapon") && boss[token] is JObject weapon)
                                {
                                    Classes.Weapon neoWeapon = new Classes.Weapon();
                                    foreach (string wepToken in weapon.Properties().Select(p => p.Name))
                                    {
                                        if (wepToken == "name")
                                        {
                                            neoWeapon.Class = JTokenToString(weapon[wepToken]);
                                        }
                                        else if (wepToken == "index")
                                        {
                                            neoWeapon.Index = JTokenToInt(weapon[wepToken]);
                                        }
                                        else if (wepToken == "show")
                                        {
                                            neoWeapon.Visible = JTokenToInt(weapon[wepToken]) == 1;
                                        }
                                        else if (wepToken == "attributes")
                                        {
                                            string[] attrs = JTokenToString(weapon[wepToken]).Split(';');
                                            for (int i = 0; i < attrs.Length; i += 2)
                                            {
                                                Classes.Weapon.Attribute neoAttr = new Classes.Weapon.Attribute(neoWeapon)
                                                {
                                                    ID = StringToInt(attrs[i])
                                                };
                                                if (i + 1 < attrs.Length && attrs[i + 1].IndexOf(".") >= 0)
                                                {
                                                    neoAttr.Arg = StringToDouble(attrs[i + 1]);
                                                }
                                                neoWeapon.Attributes.Add(neoAttr);
                                            }
                                        }
                                    }
                                    openedBoss.Weapons.Add(neoWeapon);
                                }
                                else if (token.StartsWith("ability") && boss[token] is JObject ability)
                                {
                                    Classes.Ability neoAbility = new Classes.Ability();
                                    foreach (string abiToken in ability.Properties().Select(p => p.Name))
                                    {
                                        if (abiToken == "name")
                                        {
                                            neoAbility.Name = JTokenToString(ability[abiToken]);
                                        }
                                        else if (abiToken == "plugin_name")
                                        {
                                            neoAbility.Plugin = JTokenToString(ability[abiToken]);
                                        }
                                        else if (abiToken.StartsWith("arg"))
                                        {
                                            Match indexMatch = Regex.Match(abiToken, "arg([0-9]+)");

                                            if (indexMatch.Success && indexMatch.Groups[1] != null && int.TryParse(indexMatch.Groups[1].Value, out int abiIndex))
                                            {
                                                Classes.Ability.Argument neoArg = new Classes.Ability.Argument()
                                                {
                                                    Index = abiIndex,
                                                    Value = JTokenToString(ability[abiToken])
                                                };
                                                neoAbility.Arguments.Add(neoArg);
                                            }
                                        }
                                    }
                                    openedBoss.Abilities.Add(neoAbility);
                                }
                                else if (token.StartsWith("sound_bgm") && boss[token] is JObject music)
                                {
                                    List <Classes.SoundPkg.MusicSound> neoMusicList = new List <Classes.SoundPkg.MusicSound>();
                                    foreach (string musicToken in music.Properties().Select(p => p.Name))
                                    {
                                        if (musicToken.StartsWith("path"))
                                        {
                                            Match indexMatch = Regex.Match(musicToken, "path([0-9]+)");
                                            if (indexMatch.Success && indexMatch.Groups[1] != null && int.TryParse(indexMatch.Groups[1].Value, out int musicIndex))
                                            {
                                                for (int i = 0; neoMusicList.Count < musicIndex; i++)
                                                {
                                                    neoMusicList.Add(new Classes.SoundPkg.MusicSound());
                                                }
                                                neoMusicList[musicIndex - 1].Path = "sound\\" + JTokenToString(music[musicToken]);
                                            }
                                        }
                                        else if (musicToken.StartsWith("time"))
                                        {
                                            Match indexMatch = Regex.Match(musicToken, "time([0-9]+)");
                                            if (indexMatch.Success && indexMatch.Groups[1] != null && int.TryParse(indexMatch.Groups[1].Value, out int musicIndex))
                                            {
                                                for (int i = 0; neoMusicList.Count < musicIndex; i++)
                                                {
                                                    neoMusicList.Add(new Classes.SoundPkg.MusicSound());
                                                }
                                                neoMusicList[musicIndex - 1].Length = JTokenToInt(music[musicToken]);
                                            }
                                        }
                                        else if (musicToken.StartsWith("name"))
                                        {
                                            Match indexMatch = Regex.Match(musicToken, "name([0-9]+)");
                                            if (indexMatch.Success && indexMatch.Groups[1] != null && int.TryParse(indexMatch.Groups[1].Value, out int musicIndex))
                                            {
                                                for (int i = 0; neoMusicList.Count < musicIndex; i++)
                                                {
                                                    neoMusicList.Add(new Classes.SoundPkg.MusicSound());
                                                }
                                                neoMusicList[musicIndex - 1].Name = JTokenToString(music[musicToken]);
                                            }
                                        }
                                        else if (musicToken.StartsWith("artist"))
                                        {
                                            Match indexMatch = Regex.Match(musicToken, "artist([0-9]+)");
                                            if (indexMatch.Success && indexMatch.Groups[1] != null && int.TryParse(indexMatch.Groups[1].Value, out int musicIndex))
                                            {
                                                for (int i = 0; neoMusicList.Count < musicIndex; i++)
                                                {
                                                    neoMusicList.Add(new Classes.SoundPkg.MusicSound());
                                                }
                                                neoMusicList[musicIndex - 1].Artist = JTokenToString(music[musicToken]);
                                            }
                                        }
                                    }
                                    openedBoss.Sounds.Music = new System.Collections.ObjectModel.ObservableCollection <Classes.SoundPkg.MusicSound>(neoMusicList);
                                }
                                else if (token.StartsWith("sound_begin") && boss[token] is JObject begin)
                                {
                                    foreach (string beginPath in begin.Properties().Select(p => p.Value))
                                    {
                                        openedBoss.Sounds.Startup.Add(new Classes.SoundPkg.Sound()
                                        {
                                            Path = "sound\\" + beginPath
                                        });
                                    }
                                }
                                else if (token.StartsWith("sound_win") && boss[token] is JObject win)
                                {
                                    foreach (string winPath in win.Properties().Select(p => p.Value))
                                    {
                                        openedBoss.Sounds.Victory.Add(new Classes.SoundPkg.Sound()
                                        {
                                            Path = "sound\\" + winPath
                                        });
                                    }
                                }
                                else if (token.StartsWith("sound_lastman") && boss[token] is JObject last)
                                {
                                    foreach (string lastPath in last.Properties().Select(p => p.Value))
                                    {
                                        openedBoss.Sounds.LastMan.Add(new Classes.SoundPkg.Sound()
                                        {
                                            Path = "sound\\" + lastPath
                                        });
                                    }
                                }
                                else if (token.StartsWith("sound_death") && boss[token] is JObject death)
                                {
                                    foreach (string deathPath in death.Properties().Select(p => p.Value))
                                    {
                                        openedBoss.Sounds.Death.Add(new Classes.SoundPkg.Sound()
                                        {
                                            Path = "sound\\" + deathPath
                                        });
                                    }
                                }
                                else if (token.StartsWith("sound_hit") && boss[token] is JObject kill)
                                {
                                    foreach (string killPath in kill.Properties().Select(p => p.Value))
                                    {
                                        openedBoss.Sounds.KillPlayer.Add(new Classes.SoundPkg.Sound()
                                        {
                                            Path = "sound\\" + killPath
                                        });
                                    }
                                }
                                else if (token.StartsWith("sound_kspree") && boss[token] is JObject spree)
                                {
                                    foreach (string spreePath in spree.Properties().Select(p => p.Value))
                                    {
                                        openedBoss.Sounds.KillingSpree.Add(new Classes.SoundPkg.Sound()
                                        {
                                            Path = "sound\\" + spreePath
                                        });
                                    }
                                }
                                else if (token.StartsWith("catch_phrase") && boss[token] is JObject phrase)
                                {
                                    foreach (string phrasePath in phrase.Properties().Select(p => p.Value))
                                    {
                                        openedBoss.Sounds.CatchPhrase.Add(new Classes.SoundPkg.Sound()
                                        {
                                            Path = "sound\\" + phrasePath
                                        });
                                    }
                                }
                                else if (token.StartsWith("sound_stabbed") && boss[token] is JObject stabbed)
                                {
                                    foreach (string stabbedPath in stabbed.Properties().Select(p => p.Value))
                                    {
                                        openedBoss.Sounds.Backstab.Add(new Classes.SoundPkg.Sound()
                                        {
                                            Path = "sound\\" + stabbedPath
                                        });
                                    }
                                }
                                else if (token.StartsWith("sound_ability") && boss[token] is JObject abiSound)
                                {
                                    List <Classes.SoundPkg.AbilitySound> neoAbilitySoundList = new List <Classes.SoundPkg.AbilitySound>();
                                    foreach (string abilityToken in abiSound.Properties().Select(p => p.Name))
                                    {
                                        if (abilityToken.StartsWith("slot"))
                                        {
                                            Match indexMatch = Regex.Match(abilityToken, "slot([0-9]+)");
                                            if (indexMatch.Success && indexMatch.Groups[1] != null && int.TryParse(indexMatch.Groups[1].Value, out int slotIndex))
                                            {
                                                for (int i = 0; neoAbilitySoundList.Count < slotIndex; i++)
                                                {
                                                    neoAbilitySoundList.Add(new Classes.SoundPkg.AbilitySound());
                                                }
                                                neoAbilitySoundList[slotIndex - 1].Slot = JTokenToInt(abiSound[abilityToken]);
                                            }
                                        }
                                        else
                                        {
                                            neoAbilitySoundList.Add(new Classes.SoundPkg.AbilitySound()
                                            {
                                                Path = "sound\\" + JTokenToString(abiSound[abilityToken])
                                            });
                                        }
                                    }
                                    openedBoss.Sounds.Ability = new System.Collections.ObjectModel.ObservableCollection <Classes.SoundPkg.AbilitySound>(neoAbilitySoundList);
                                }
                                else if (token == "download" && boss[token] is JObject download)
                                {
                                    foreach (string filePath in download.Properties().Select(p => p.Value))
                                    {
                                        if (!openedBoss.Sounds.Ability.Any(t => t.Path == filePath) &&
                                            !openedBoss.Sounds.Backstab.Any(t => t.Path == filePath) &&
                                            !openedBoss.Sounds.CatchPhrase.Any(t => t.Path == filePath) &&
                                            !openedBoss.Sounds.Death.Any(t => t.Path == filePath) &&
                                            !openedBoss.Sounds.KillingSpree.Any(t => t.Path == filePath) &&
                                            !openedBoss.Sounds.KillPlayer.Any(t => t.Path == filePath) &&
                                            !openedBoss.Sounds.LastMan.Any(t => t.Path == filePath) &&
                                            !openedBoss.Sounds.Music.Any(t => t.Path == filePath) &&
                                            !openedBoss.Sounds.Startup.Any(t => t.Path == filePath) &&
                                            !openedBoss.Sounds.Victory.Any(t => t.Path == filePath) &&
                                            !downloadList.Any(t => t == filePath))
                                        {
                                            downloadList.Add(filePath);
                                        }
                                    }
                                }
                            }
                            openedBoss.CustomFiles = new System.Collections.ObjectModel.ObservableCollection <string>(downloadList);
                            return(openedBoss);
                        }
                    }
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine(ex.ToString());
                }
            }
            return(null);
        }