Core/HeroCatalog.cs
using System;
using System.Collections.Generic;
using System.Linq;

namespace Prototype;

public readonly record struct HeroSpec( string Id, string Name, string Role, string Passive, string Ultimate, Color Color );
public readonly record struct SkillSpec( string Id, string HeroId, string Name, string Description, int MaxRank, int Branch = 0, int Tier = 0, string Parent = "", string Icon = "shield" );

public sealed class ProgressionData
{
	public int SkillTreeVersion { get; set; }
	public int Insight { get; set; }
    public int Coins { get; set; }
    public bool CoinsMigrated { get; set; }
    public Dictionary<string, int> CoinReceipts { get; set; } = new();
	public string SelectedHero { get; set; } = "nomad";
	public Dictionary<string, int> SkillRanks { get; set; } = new();
}

public static class HeroCatalog
{
	public static readonly HeroSpec Warden = new( "warden", "THE WARDEN", "VANGUARD", "Stonebound: +25 maximum health and reduced contact damage.", "Aegis Pulse: temporary immunity and a radial knockback.", new Color( .25f, .78f, .92f ) );
	public static readonly HeroSpec Seer = new( "seer", "THE SEER", "ARCANIST", "Resonance: every fifth hit deals bonus arcane damage.", "Chrono Veil: greatly increases movement and fire rate for six seconds.", new Color( .72f, .38f, 1f ) );
	public static readonly HeroSpec Relic = new( "relic", "THE RELIC", "MARKSMAN", "Patient Hand: increased weapon damage and accuracy.", "Sun Lance: empowers shots with extreme damage for five seconds.", new Color( 1f, .66f, .18f ) );
	public static readonly HeroSpec Nomad = new( "nomad", "DASHER", "DASH SPECIALIST", "Wayfinder: faster movement and shorter dash cooldown.", "Dust Step: instantly refreshes dash and grants sustained haste.", new Color( .35f, .92f, .55f ) );
	public static IReadOnlyList<HeroSpec> All { get; } = new[] { Nomad };
	public static HeroSpec Get( string id ) => All.FirstOrDefault( hero => hero.Id == id ) is var found && !string.IsNullOrEmpty( found.Id ) ? found : Nomad;

	public static IReadOnlyList<SkillSpec> Skills { get; } = new[]
	{
        new SkillSpec("tree_heart", "nomad", "Stone Heart", "+10 maximum HP per rank.", 3, 0, 0, "", "shield"),
        new SkillSpec("tree_armor", "nomad", "Iron Will", "+5 defense per rank. Damage uses diminishing returns.", 3, 0, 1, "tree_heart", "shield"),
        new SkillSpec("tree_vitality", "nomad", "Deep Vitality", "+5 maximum HP and +2 defense per rank.", 3, 0, 2, "tree_armor", "plus"),
        new SkillSpec("tree_bastion", "nomad", "Bastion", "+10 maximum HP and +3 defense per rank.", 3, 0, 3, "tree_vitality", "shield"),
        new SkillSpec("tree_power", "nomad", "Runic Edge", "+5% weapon damage per rank.", 3, 1, 0, "", "trophy"),
        new SkillSpec("tree_haste", "nomad", "Quick Trigger", "+3% fire rate per rank.", 3, 1, 1, "tree_power", "plus"),
        new SkillSpec("tree_reload", "nomad", "Quick Hands", "+5% reload speed per rank.", 3, 1, 2, "tree_haste", "join"),
        new SkillSpec("tree_precision", "nomad", "Weapon Mastery", "+3% damage and +2% fire rate per rank.", 3, 1, 3, "tree_reload", "trophy"),
        new SkillSpec("tree_stride", "nomad", "Light Step", "+2% movement speed per rank.", 3, 2, 0, "", "join"),
        new SkillSpec("tree_dash", "nomad", "Wind Cut", "+5% dash recharge speed per rank.", 3, 2, 1, "tree_stride", "join"),
        new SkillSpec("tree_focus", "nomad", "Clear Mind", "+5% ultimate recharge speed per rank.", 3, 2, 2, "tree_dash", "skills"),
        new SkillSpec("tree_dust", "nomad", "Living Dust", "+0.4 seconds ultimate duration per rank.", 3, 2, 3, "tree_focus", "skills")
	};
	public static IEnumerable<SkillSpec> For( string heroId ) => Skills.Where( skill => skill.HeroId == heroId );
}