Files
CapySR/gui/Catalog.cs
T
2026-10-17 20:42:15 -07:00

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;
}
}
}