275 lines
12 KiB
C#
275 lines
12 KiB
C#
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<int> Points = new List<int>();
|
|
public List<StatBonus> Stats = new List<StatBonus>();
|
|
|
|
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<Anchor> Anchors = new List<Anchor>();
|
|
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<StatBonus>[] Passive = new List<StatBonus>[5];
|
|
}
|
|
|
|
public class RelicSetInfo
|
|
{
|
|
public int Id;
|
|
public string Name;
|
|
public bool Planar;
|
|
public Dictionary<int, int> Pieces = new Dictionary<int, int>();
|
|
public Dictionary<int, List<StatBonus>> Bonus = new Dictionary<int, List<StatBonus>>();
|
|
}
|
|
|
|
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<AvatarInfo> Avatars = new List<AvatarInfo>();
|
|
public List<LightconeInfo> Lightcones = new List<LightconeInfo>();
|
|
public List<RelicSetInfo> RelicSets = new List<RelicSetInfo>();
|
|
public Dictionary<int, List<AffixInfo>> MainAffixes = new Dictionary<int, List<AffixInfo>>();
|
|
public List<AffixInfo> SubAffixes = new List<AffixInfo>();
|
|
public List<Named> Monsters = new List<Named>();
|
|
public List<Named> Stages = new List<Named>();
|
|
public List<Named> Buffs = new List<Named>();
|
|
|
|
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<AffixInfo> 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<string, object>)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<object>().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<Dictionary<string, object>>().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<string, object>)s["pieces"])
|
|
set.Pieces[int.Parse(piece.Key)] = Convert.ToInt32(piece.Value);
|
|
if (s.TryGetValue("bonus", out object bonus) && bonus is Dictionary<string, object> pieces)
|
|
{
|
|
foreach (var need in pieces)
|
|
set.Bonus[int.Parse(need.Key)] = ((IEnumerable)need.Value).Cast<Dictionary<string, object>>().Select(Bonus).ToList();
|
|
}
|
|
catalog.RelicSets.Add(set);
|
|
}
|
|
foreach (var slot in (Dictionary<string, object>)root["main_affixes"])
|
|
catalog.MainAffixes[int.Parse(slot.Key)] = ((IEnumerable)slot.Value).Cast<Dictionary<string, object>>().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<string, object> d) => new StatBonus { Prop = Str(d, "prop"), Value = Dbl(d, "value") };
|
|
|
|
static List<StatBonus> Bonuses(Dictionary<string, object> parent, string key) => Items(parent, key).Select(Bonus).ToList();
|
|
|
|
static double[][] Growth(Dictionary<string, object> 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<object>().Select(Convert.ToDouble).ToArray();
|
|
promotion++;
|
|
}
|
|
}
|
|
return growth;
|
|
}
|
|
|
|
static AffixInfo Affix(Dictionary<string, object> 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<Dictionary<string, object>> Items(Dictionary<string, object> parent, string key) =>
|
|
parent.TryGetValue(key, out object list) && list is IEnumerable items ? items.Cast<Dictionary<string, object>>() : Enumerable.Empty<Dictionary<string, object>>();
|
|
|
|
static int Int(Dictionary<string, object> d, string key) => d.TryGetValue(key, out object v) && v != null ? Convert.ToInt32(v) : 0;
|
|
static double Dbl(Dictionary<string, object> d, string key) => d.TryGetValue(key, out object v) && v != null ? Convert.ToDouble(v) : 0;
|
|
static string Str(Dictionary<string, object> d, string key) => d.TryGetValue(key, out object v) && v != null ? Convert.ToString(v) : "";
|
|
static bool Bool(Dictionary<string, object> d, string key) => d.TryGetValue(key, out object v) && v is bool b && b;
|
|
}
|
|
|
|
public static class Palette
|
|
{
|
|
static readonly Dictionary<string, string[]> Elements = new Dictionary<string, string[]>
|
|
{
|
|
{ "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;
|
|
}
|
|
}
|
|
}
|