using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using System.Web.Script.Serialization; using System.Windows.Media; namespace CapyLauncher { public class StatBonus { public string Prop; public double Value; } public class Anchor { public int Number; public int Max; public List Points = new List(); public List Stats = new List(); public string Label { get { switch (Number) { case 1: return "Basic ATK"; case 2: return "Skill"; case 3: return "Ultimate"; case 4: return "Talent"; case 5: return "Technique"; case 6: return "Ascension A2"; case 7: return "Ascension A4"; case 8: return "Ascension A6"; case 19: return "Memosprite skill"; case 20: return "Memosprite talent"; default: return Number >= 9 && Number <= 18 ? "Stat bonus " + (Number - 8) : "Extra " + Number; } } } } public class AvatarInfo { public int Id; public string Name; public int Rarity; public string Element; public string Path; public int MaxRank; public int Sp; public bool Enhanced; public List Anchors = new List(); public double[][] Growth = new double[7][]; public string Initials { get { var words = Name.Split(new[] { ' ', '(', ')', '•', '·' }, StringSplitOptions.RemoveEmptyEntries).Where(w => char.IsLetter(w[0])).ToList(); if (words.Count == 0) return "?"; if (words.Count == 1 || Name.Contains("(")) return words[0].Length > 1 ? char.ToUpperInvariant(words[0][0]) + words[0].Substring(1, 1) : words[0].ToUpperInvariant(); return string.Concat(words.Take(2).Select(w => char.ToUpperInvariant(w[0]))); } } } public class LightconeInfo { public int Id; public string Name; public int Rarity; public string Path; public double[][] Growth = new double[7][]; public List[] Passive = new List[5]; } public class RelicSetInfo { public int Id; public string Name; public bool Planar; public Dictionary Pieces = new Dictionary(); public Dictionary> Bonus = new Dictionary>(); } public class AffixInfo { public int Id; public string Prop; public string Property; public bool Percent; public double Base; public double PerLevel; public double Step; public int Steps; public string Format(double value) => Percent ? (value * 100).ToString("0.0") + "%" : Property == "SPD" ? value.ToString("0.0") : Math.Floor(value).ToString("0"); } public class Named { public int Id; public string Name; public string Extra; } public class Catalog { public string Version = ""; public List Avatars = new List(); public List Lightcones = new List(); public List RelicSets = new List(); public Dictionary> MainAffixes = new Dictionary>(); public List SubAffixes = new List(); public List Monsters = new List(); public List Stages = new List(); public List Buffs = new List(); public AvatarInfo Avatar(int id) => Avatars.FirstOrDefault(a => a.Id == id); public LightconeInfo Lightcone(int id) => Lightcones.FirstOrDefault(l => l.Id == id); public RelicSetInfo RelicSet(int id) => RelicSets.FirstOrDefault(r => r.Id == id); public AffixInfo Sub(int id) => SubAffixes.FirstOrDefault(s => s.Id == id); public AffixInfo Main(int slot, int id) => MainAffixes.TryGetValue(slot, out List list) ? list.FirstOrDefault(a => a.Id == id) : null; public static Catalog Load(string path) { var catalog = new Catalog(); var serializer = new JavaScriptSerializer { MaxJsonLength = int.MaxValue, RecursionLimit = 256 }; var root = (Dictionary)serializer.DeserializeObject(File.ReadAllText(path)); catalog.Version = Str(root, "version"); foreach (var a in Items(root, "avatars")) { var info = new AvatarInfo { Id = Int(a, "id"), Name = Str(a, "name"), Rarity = Int(a, "rarity"), Element = Str(a, "element"), Path = Str(a, "path"), MaxRank = Int(a, "max_rank"), Sp = Int(a, "sp"), Enhanced = Bool(a, "enhanced"), }; foreach (var anchor in Items(a, "anchors")) { info.Anchors.Add(new Anchor { Number = Int(anchor, "anchor"), Max = Int(anchor, "max"), Points = ((IEnumerable)anchor["points"]).Cast().Select(Convert.ToInt32).ToList(), Stats = Bonuses(anchor, "stats"), }); } info.Growth = Growth(a); catalog.Avatars.Add(info); } foreach (var l in Items(root, "lightcones")) { var cone = new LightconeInfo { Id = Int(l, "id"), Name = Str(l, "name"), Rarity = Int(l, "rarity"), Path = Str(l, "path"), Growth = Growth(l) }; if (l.TryGetValue("passive", out object passive) && passive is IEnumerable ranks) { int rank = 0; foreach (object level in ranks) { if (rank < 5) cone.Passive[rank++] = ((IEnumerable)level).Cast>().Select(Bonus).ToList(); } } catalog.Lightcones.Add(cone); } foreach (var s in Items(root, "relic_sets")) { var set = new RelicSetInfo { Id = Int(s, "id"), Name = Str(s, "name"), Planar = Bool(s, "planar") }; foreach (var piece in (Dictionary)s["pieces"]) set.Pieces[int.Parse(piece.Key)] = Convert.ToInt32(piece.Value); if (s.TryGetValue("bonus", out object bonus) && bonus is Dictionary pieces) { foreach (var need in pieces) set.Bonus[int.Parse(need.Key)] = ((IEnumerable)need.Value).Cast>().Select(Bonus).ToList(); } catalog.RelicSets.Add(set); } foreach (var slot in (Dictionary)root["main_affixes"]) catalog.MainAffixes[int.Parse(slot.Key)] = ((IEnumerable)slot.Value).Cast>().Select(Affix).ToList(); catalog.SubAffixes = Items(root, "sub_affixes").Select(Affix).ToList(); catalog.Monsters = Items(root, "monsters").Select(m => new Named { Id = Int(m, "id"), Name = Str(m, "name"), Extra = Rank(Str(m, "rank")) }).ToList(); catalog.Stages = Items(root, "stages").Select(m => new Named { Id = Int(m, "id"), Name = Str(m, "name"), Extra = Str(m, "type") }).ToList(); catalog.Buffs = Items(root, "buffs").Select(m => new Named { Id = Int(m, "id"), Name = Str(m, "name") }).ToList(); return catalog; } static StatBonus Bonus(Dictionary d) => new StatBonus { Prop = Str(d, "prop"), Value = Dbl(d, "value") }; static List Bonuses(Dictionary parent, string key) => Items(parent, key).Select(Bonus).ToList(); static double[][] Growth(Dictionary parent) { var growth = new double[7][]; if (parent.TryGetValue("growth", out object list) && list is IEnumerable steps) { int promotion = 0; foreach (object step in steps) { if (promotion < 7 && step is IEnumerable numbers) growth[promotion] = numbers.Cast().Select(Convert.ToDouble).ToArray(); promotion++; } } return growth; } static AffixInfo Affix(Dictionary a) => new AffixInfo { Id = Int(a, "id"), Prop = Str(a, "prop"), Property = Str(a, "property"), Percent = Bool(a, "percent"), Base = Dbl(a, "base"), PerLevel = Dbl(a, "per_level"), Step = Dbl(a, "step"), Steps = Int(a, "steps"), }; static string Rank(string rank) { if (rank.StartsWith("BigBoss")) return "Boss"; if (rank.StartsWith("LittleBoss")) return "Mini-boss"; if (rank.StartsWith("Elite")) return "Elite"; return rank.Length == 0 ? "" : "Minion"; } static IEnumerable> Items(Dictionary parent, string key) => parent.TryGetValue(key, out object list) && list is IEnumerable items ? items.Cast>() : Enumerable.Empty>(); static int Int(Dictionary d, string key) => d.TryGetValue(key, out object v) && v != null ? Convert.ToInt32(v) : 0; static double Dbl(Dictionary d, string key) => d.TryGetValue(key, out object v) && v != null ? Convert.ToDouble(v) : 0; static string Str(Dictionary d, string key) => d.TryGetValue(key, out object v) && v != null ? Convert.ToString(v) : ""; static bool Bool(Dictionary d, string key) => d.TryGetValue(key, out object v) && v is bool b && b; } public static class Palette { static readonly Dictionary Elements = new Dictionary { { "Fire", new[] { "#FF9A6B", "#FF5E7A" } }, { "Ice", new[] { "#9FE7FF", "#5FA8FF" } }, { "Lightning", new[] { "#E3A6FF", "#A16BFF" } }, { "Wind", new[] { "#A6F0C6", "#43C59E" } }, { "Quantum", new[] { "#8E8CFF", "#5A4BD8" } }, { "Imaginary", new[] { "#FFE38A", "#F2B544" } }, { "Physical", new[] { "#E6E6EE", "#A3A3B5" } }, }; public static Brush Element(string element) { string[] colors = Elements.TryGetValue(element ?? "", out string[] found) ? found : new[] { "#FF9AA2", "#D689FF" }; var brush = new LinearGradientBrush((Color)ColorConverter.ConvertFromString(colors[0]), (Color)ColorConverter.ConvertFromString(colors[1]), 45); brush.Freeze(); return brush; } public static Brush Solid(string element) { string[] colors = Elements.TryGetValue(element ?? "", out string[] found) ? found : new[] { "#FF9AA2" }; var brush = new SolidColorBrush((Color)ColorConverter.ConvertFromString(colors[0])); brush.Freeze(); return brush; } public static Brush Rarity(int rarity) { var brush = new SolidColorBrush((Color)ColorConverter.ConvertFromString(rarity >= 5 ? "#FFD58A" : rarity == 4 ? "#D689FF" : "#7DC8FF")); brush.Freeze(); return brush; } } }