Decompiled source of WaysOfTheGods v3.5.2

WaysOfTheGods.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: IgnoresAccessChecksTo("assembly_guiutils")]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: AssemblyCompany("WaysOfTheGods")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("3.5.2.0")]
[assembly: AssemblyInformationalVersion("3.5.2+148b1b088e42ef213344bc176e3a01a78bd4d149")]
[assembly: AssemblyProduct("WaysOfTheGods")]
[assembly: AssemblyTitle("WaysOfTheGods")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("3.5.2.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ClassiDiValheim
{
	public class SpellDef
	{
		public string Name;

		public int UnlockLevel;

		public float Cooldown;

		public float StaminaCost;

		public string IconItem;

		public Action<Player, int> CastAction;

		public Func<int, string> Describe;

		public float CastTime;
	}
	public static class Abilities
	{
		private enum AscendantElement
		{
			Fire,
			Frost,
			Lightning,
			Earth,
			Blood,
			Pierce,
			Poison,
			Spirit,
			Bone,
			Wild,
			Nature,
			Holy
		}

		private enum AscendantMode
		{
			Burst,
			Field,
			Ward,
			Drain,
			Companion
		}

		private sealed class AscendantPath
		{
			public string OmenName;

			public string OmenFlavor;

			public string OmenIcon;

			public AscendantMode OmenMode;

			public string MythicName;

			public string MythicFlavor;

			public string MythicIcon;

			public AscendantMode MythicMode;

			public AscendantElement Element;
		}

		private enum RangerTrapKind
		{
			Snare,
			Explosive,
			Venom
		}

		private static readonly Dictionary<string, float> CooldownEnd = new Dictionary<string, float>();

		public static bool DebugUnlockAll;

		private static readonly SpellDef MageFireballBase = new SpellDef
		{
			Name = "Fireball",
			UnlockLevel = 1,
			Cooldown = 6f,
			StaminaCost = 20f,
			IconItem = "StaffFireball",
			CastAction = CastFireball,
			Describe = (int lvl) => $"Hurl a fireball ({AdjFireballDamage(lvl)} damage)"
		};

		private static readonly SpellDef MageIceShardsBase = new SpellDef
		{
			Name = "Ice Shards",
			UnlockLevel = 1,
			Cooldown = 10f,
			StaminaCost = 30f,
			IconItem = "StaffIceShards",
			CastAction = CastIceShards,
			Describe = (int lvl) => $"Fan of {IceShardCount()} freezing shards ({AdjIceShardDamage(lvl)} damage each)"
		};

		private static readonly SpellDef MageLightningBoltBase = new SpellDef
		{
			Name = "Lightning Bolt",
			UnlockLevel = 1,
			Cooldown = 12f,
			StaminaCost = 35f,
			IconItem = "StaffLightning",
			CastAction = CastLightningBolt,
			Describe = (int lvl) => $"Crackling projectile ({AdjLightningBoltDamage(lvl)} damage)"
		};

		private static readonly SpellDef[] MageFireBaseOnly = new SpellDef[1] { MageFireballBase };

		private static readonly SpellDef[] MageFrostBaseOnly = new SpellDef[1] { MageIceShardsBase };

		private static readonly SpellDef[] MageLightningBaseOnly = new SpellDef[1] { MageLightningBoltBase };

		public static readonly SpellDef[] PyromancerSpells = new SpellDef[5]
		{
			MageFireballBase,
			new SpellDef
			{
				Name = "Ring of Fire",
				UnlockLevel = 10,
				Cooldown = 20f,
				StaminaCost = 45f,
				IconItem = "SurtlingCore",
				CastAction = CastRingOfFire,
				Describe = (int lvl) => $"{RingCount()} fireballs in every direction ({AdjRingFireDamage(lvl)} damage each)"
			},
			new SpellDef
			{
				Name = "Flame Wave",
				UnlockLevel = 20,
				Cooldown = 12f,
				StaminaCost = 30f,
				IconItem = "Torch",
				CastAction = CastFlameWave,
				Describe = (int lvl) => $"A fan of 5 flames scorches everything ahead ({AdjFlameWaveDamage(lvl)} damage each)"
			},
			new SpellDef
			{
				Name = "Pillar of Flame",
				UnlockLevel = 35,
				Cooldown = 18f,
				StaminaCost = 40f,
				IconItem = "GoblinTotem",
				CastAction = CastPillarOfFlame,
				Describe = (int lvl) => $"A meteor crashes on the nearest foe ahead ({AdjPillarDamage(lvl)} damage" + (TalentSystem.Has(LP, "pyr_twinpillar") ? ", strikes a second enemy)" : ")")
			},
			new SpellDef
			{
				Name = "Meteor Shower",
				UnlockLevel = 45,
				Cooldown = 60f,
				StaminaCost = 80f,
				IconItem = "Obsidian",
				CastTime = 2.5f,
				CastAction = CastWrathOfTheGods,
				Describe = (int lvl) => $"{MeteorCount()} meteors rain in front of you ({AdjMeteorDamage(lvl)} damage each)"
			}
		};

		public static readonly SpellDef[] FlameSummonerSpells = new SpellDef[5]
		{
			MageFireballBase,
			new SpellDef
			{
				Name = "Summon Fire Imp",
				UnlockLevel = 10,
				Cooldown = 12f,
				StaminaCost = 30f,
				IconItem = "TrophySurtling",
				CastAction = CastSummonFireImp,
				Describe = (int lvl) => $"A fire imp fights at your side (max {FireImpCap()})"
			},
			new SpellDef
			{
				Name = "Burning Ground",
				UnlockLevel = 20,
				Cooldown = 20f,
				StaminaCost = 40f,
				IconItem = "Coal",
				CastAction = CastBurningGround,
				Describe = (int lvl) => $"Sets the ground ablaze ({BurningGroundRadius():0} m, {BurningGroundDuration():0} s, {AdjBurningTick(lvl)} fire/s)" + (TalentSystem.Has(LP, "smn_emberpact") ? " and mends your summons" : "")
			},
			new SpellDef
			{
				Name = "Summon Magma Elemental",
				UnlockLevel = 35,
				Cooldown = 45f,
				StaminaCost = 60f,
				IconItem = "Obsidian",
				CastAction = CastSummonMagmaElemental,
				Describe = (int lvl) => "An elite elemental of molten rock serves you (one at a time)"
			},
			new SpellDef
			{
				Name = "Legion of Cinders",
				UnlockLevel = 45,
				Cooldown = 90f,
				StaminaCost = 80f,
				IconItem = "SurtlingCore",
				CastTime = 2f,
				CastAction = CastLegionOfCinders,
				Describe = (int lvl) => $"{LegionCount()} fire imps burst from the earth for {LegionLifetime():0} s"
			}
		};

		public static readonly SpellDef[] CryomancerSpells = new SpellDef[5]
		{
			MageIceShardsBase,
			new SpellDef
			{
				Name = "Frost Nova",
				UnlockLevel = 10,
				Cooldown = 15f,
				StaminaCost = 30f,
				IconItem = "FreezeGland",
				CastAction = CastFrostNova,
				Describe = (int lvl) => $"Explosion of frost around you ({AdjFrostNovaDamage(lvl)} damage, {FrostNovaRadius():0} m)"
			},
			new SpellDef
			{
				Name = "Glacial Spike",
				UnlockLevel = 20,
				Cooldown = 8f,
				StaminaCost = 30f,
				IconItem = "Crystal",
				CastAction = CastGlacialSpike,
				Describe = (int lvl) => $"A massive spear of ice ({AdjGlacialSpikeDamage(lvl)} damage)"
			},
			new SpellDef
			{
				Name = "Blizzard",
				UnlockLevel = 35,
				Cooldown = 25f,
				StaminaCost = 55f,
				IconItem = "FreezeGland",
				CastTime = 1.5f,
				CastAction = CastBlizzard,
				Describe = (int lvl) => $"A blizzard rages ahead for {8} s ({AdjBlizzardTick(lvl)} frost/s, {BlizzardRadius():0} m)"
			},
			new SpellDef
			{
				Name = "Absolute Zero",
				UnlockLevel = 45,
				Cooldown = 60f,
				StaminaCost = 80f,
				IconItem = "TrophyDragonQueen",
				CastTime = 2.5f,
				CastAction = CastAbsoluteZero,
				Describe = (int lvl) => $"Winter itself erupts around you ({AdjAbsoluteZeroDamage(lvl)} damage, {10f:0} m)"
			}
		};

		public static readonly SpellDef[] FrostwardenSpells = new SpellDef[5]
		{
			MageIceShardsBase,
			new SpellDef
			{
				Name = "Rune Shield",
				UnlockLevel = 10,
				Cooldown = 60f,
				StaminaCost = 40f,
				IconItem = "StaffShield",
				CastAction = CastRuneShield,
				Describe = (int lvl) => $"Protective dome ({DomeRadius():0} m, {DomeDuration():0} s): armors whoever is inside, dissolves projectiles and repels enemies"
			},
			new SpellDef
			{
				Name = "Frost Armor",
				UnlockLevel = 20,
				Cooldown = 30f,
				StaminaCost = 30f,
				IconItem = "ArmorWolfChest",
				CastAction = CastFrostArmor,
				Describe = (int lvl) => $"A shell of living ice armors you for {FrostArmorDuration():0} s" + (TalentSystem.Has(LP, "fw_chillguard") ? " and bites attackers" : "")
			},
			new SpellDef
			{
				Name = "Winter's Grasp",
				UnlockLevel = 35,
				Cooldown = 20f,
				StaminaCost = 40f,
				IconItem = "FreezeGland",
				CastAction = CastWintersGrasp,
				Describe = (int lvl) => $"Freezes the ground ahead ({GraspRadius():0} m, {8f:0} s, {AdjGraspTick(lvl)} frost/s)"
			},
			new SpellDef
			{
				Name = "Fimbulwinter",
				UnlockLevel = 45,
				Cooldown = 90f,
				StaminaCost = 80f,
				IconItem = "TrophySGolem",
				CastTime = 2.5f,
				CastAction = CastFimbulwinter,
				Describe = (int lvl) => $"The great winter: a vast dome ({FimbulRadius():0} m, 20 s) and a killing frost ({AdjFimbulBlastDamage(lvl)} damage)"
			}
		};

		public static readonly SpellDef[] StormcallerSpells = new SpellDef[5]
		{
			MageLightningBoltBase,
			new SpellDef
			{
				Name = "Chain Lightning",
				UnlockLevel = 10,
				Cooldown = 8f,
				StaminaCost = 30f,
				IconItem = "Thunderstone",
				CastAction = CastChainLightning,
				Describe = (int lvl) => $"A bolt that leaps to {1 + ChainJumps()} enemies ({AdjChainDamage(lvl)} damage, fading each jump)"
			},
			new SpellDef
			{
				Name = "Static Field",
				UnlockLevel = 20,
				Cooldown = 18f,
				StaminaCost = 40f,
				IconItem = "Chain",
				CastAction = CastStaticField,
				Describe = (int lvl) => $"Electrifies the ground ahead ({FieldRadius():0} m, {FieldDuration():0} s, {AdjFieldTick(lvl)} lightning/s)"
			},
			new SpellDef
			{
				Name = "Lightning Storm",
				UnlockLevel = 35,
				Cooldown = 30f,
				StaminaCost = 60f,
				IconItem = "TrophyEikthyr",
				CastTime = 1.5f,
				CastAction = CastLightningStorm,
				Describe = (int lvl) => $"{StormBolts()} bolts strike nearby enemies ({AdjStormBoltDamage(lvl)} damage each)"
			},
			new SpellDef
			{
				Name = "Wrath of Thor",
				UnlockLevel = 45,
				Cooldown = 60f,
				StaminaCost = 80f,
				IconItem = "SledgeStagbreaker",
				CastTime = 2.5f,
				CastAction = CastWrathOfThor,
				Describe = (int lvl) => $"{12} godly bolts hammer everything around you ({AdjThorBoltDamage(lvl)} damage each)"
			}
		};

		public static readonly SpellDef[] TempestSpells = new SpellDef[5]
		{
			MageLightningBoltBase,
			new SpellDef
			{
				Name = "Blink",
				UnlockLevel = 10,
				Cooldown = 10f,
				StaminaCost = 25f,
				IconItem = "Feathers",
				CastAction = CastBlink,
				Describe = (int lvl) => $"You become lightning: flash {BlinkDistance():0} m forward" + (TalentSystem.Has(LP, "tm_slipstream") ? " and surge with power" : "")
			},
			new SpellDef
			{
				Name = "Storm Shroud",
				UnlockLevel = 20,
				Cooldown = 25f,
				StaminaCost = 30f,
				IconItem = "Wisp",
				CastAction = CastStormShroud,
				Describe = (int lvl) => $"Crackling static wraps you for {ShroudDuration():0} s: whoever strikes you gets zapped"
			},
			new SpellDef
			{
				Name = "Ball Lightning",
				UnlockLevel = 35,
				Cooldown = 20f,
				StaminaCost = 45f,
				IconItem = "Thunderstone",
				CastAction = CastBallLightning,
				Describe = (int lvl) => $"A roaming orb of lightning ({BallDuration():0} s, {AdjBallTick(lvl)} lightning per zap)"
			},
			new SpellDef
			{
				Name = "Eye of the Storm",
				UnlockLevel = 45,
				Cooldown = 60f,
				StaminaCost = 80f,
				IconItem = "TrophyEikthyr",
				CastTime = 2f,
				CastAction = CastEyeOfTheStorm,
				Describe = (int lvl) => $"The storm follows YOU for {10f:0} s, smiting foes within {EyeRadius():0} m ({AdjEyeBoltDamage(lvl)} damage)"
			}
		};

		private static readonly SpellDef BersCrushingBlow = new SpellDef
		{
			Name = "Crushing Blow",
			UnlockLevel = 1,
			Cooldown = 5f,
			StaminaCost = 15f,
			IconItem = "MaceBronze",
			CastAction = CastCrushingBlow,
			Describe = (int lvl) => $"A heavy blow smashes the ground ahead ({AdjCrushingBlowDamage(lvl)} blunt, {CrushingBlowRadius():0.#} m) — enemies stagger"
		};

		private static readonly SpellDef BersCleave = new SpellDef
		{
			Name = "Cleave",
			UnlockLevel = 1,
			Cooldown = 5f,
			StaminaCost = 15f,
			IconItem = "AxeIron",
			CastAction = CastCleave,
			Describe = (int lvl) => $"A wide arc cuts everything in front ({AdjCleaveDamage(lvl)} slash, {CleaveRadius():0.#} m)" + ((TalentSystem.Rank(LP, "re_bleed") > 0) ? " and makes them bleed" : "")
		};

		private static readonly SpellDef BersSpearThrow = new SpellDef
		{
			Name = "Spear Throw",
			UnlockLevel = 1,
			Cooldown = 6f,
			StaminaCost = 15f,
			IconItem = "SpearBronze",
			CastAction = CastSpearThrow,
			Describe = (int lvl) => $"Hurl an ancient spear ({AdjSpearThrowDamage(lvl)} pierce)"
		};

		private static readonly SpellDef[] BersCrushingBaseOnly = new SpellDef[1] { BersCrushingBlow };

		private static readonly SpellDef[] BersRendingBaseOnly = new SpellDef[1] { BersCleave };

		private static readonly SpellDef[] BersHuntingBaseOnly = new SpellDef[1] { BersSpearThrow };

		public static readonly SpellDef[] JuggernautSpells = new SpellDef[5]
		{
			BersCrushingBlow,
			new SpellDef
			{
				Name = "Iron Skin",
				UnlockLevel = 10,
				Cooldown = 60f,
				StaminaCost = 30f,
				IconItem = "ArmorIronChest",
				CastAction = CastIronSkin,
				Describe = (int lvl) => $"Your skin turns to iron: massive defense for {IronSkinDuration():0} s"
			},
			new SpellDef
			{
				Name = "War Cry",
				UnlockLevel = 20,
				Cooldown = 10f,
				StaminaCost = 20f,
				IconItem = "TrophyBoar",
				CastAction = CastWarCry,
				Describe = (int lvl) => $"Repels and damages nearby enemies ({AdjWarCryDamage(lvl)} blunt, {WarCryRadius():0.#} m)"
			},
			new SpellDef
			{
				Name = "Berserker Fury",
				UnlockLevel = 35,
				Cooldown = 45f,
				StaminaCost = 30f,
				IconItem = "TrophyWolf",
				CastAction = CastFury,
				Describe = (int lvl) => $"+{FuryPercent()}% damage and nearly free attacks for {FuryDuration():0} s"
			},
			new SpellDef
			{
				Name = "Titanic Slam",
				UnlockLevel = 45,
				Cooldown = 60f,
				StaminaCost = 60f,
				IconItem = "SledgeDemolisher",
				CastAction = CastTitanicSlam,
				Describe = (int lvl) => $"Leap skyward and crash down ({AdjSlamDamage(lvl)} blunt, {SlamRadius():0.#} m)"
			}
		};

		public static readonly SpellDef[] EarthshakerSpells = new SpellDef[5]
		{
			BersCrushingBlow,
			new SpellDef
			{
				Name = "Seismic Blow",
				UnlockLevel = 10,
				Cooldown = 12f,
				StaminaCost = 30f,
				IconItem = "SledgeIron",
				CastAction = CastSeismicBlow,
				Describe = (int lvl) => $"Make the earth tremble ({AdjSeismicDamage(lvl)} blunt, {SeismicRadius():0.#} m)"
			},
			new SpellDef
			{
				Name = "Fault Line",
				UnlockLevel = 20,
				Cooldown = 15f,
				StaminaCost = 35f,
				IconItem = "SledgeStagbreaker",
				CastAction = CastFaultLine,
				Describe = (int lvl) => $"The ground erupts in a line ahead ({AdjFaultLineDamage(lvl)} blunt, {FaultLineLength():0} m) — enemies stagger"
			},
			new SpellDef
			{
				Name = "War Cry",
				UnlockLevel = 35,
				Cooldown = 10f,
				StaminaCost = 20f,
				IconItem = "TrophyBoar",
				CastAction = CastWarCry,
				Describe = (int lvl) => $"Repels and damages nearby enemies ({AdjWarCryDamage(lvl)} blunt, {WarCryRadius():0.#} m)"
			},
			new SpellDef
			{
				Name = "Cataclysm",
				UnlockLevel = 45,
				Cooldown = 60f,
				StaminaCost = 60f,
				IconItem = "SledgeDemolisher",
				CastAction = CastCataclysm,
				Describe = (int lvl) => $"Leap and shatter the earth ({AdjCataclysmDamage(lvl)} blunt, {SlamRadius():0.#} m) — a second wave follows"
			}
		};

		public static readonly SpellDef[] ReaverSpells = new SpellDef[5]
		{
			BersCleave,
			new SpellDef
			{
				Name = "Whirlwind",
				UnlockLevel = 10,
				Cooldown = 25f,
				StaminaCost = 45f,
				IconItem = "AtgeirBlackmetal",
				CastAction = CastWhirlwind,
				Describe = (int lvl) => $"Spinning blades for {(float)WhirlTicks() * 0.5f:0.#} s ({AdjWhirlDamage(lvl)} slash per hit, {WhirlRadius():0.#} m)"
			},
			new SpellDef
			{
				Name = "Rend",
				UnlockLevel = 20,
				Cooldown = 10f,
				StaminaCost = 25f,
				IconItem = "KnifeBlackMetal",
				CastAction = CastRupture,
				Describe = (int lvl) => $"A savage cut ({AdjRuptureDamage(lvl)} slash) that bleeds for {RuptureBleedDuration():0} s"
			},
			new SpellDef
			{
				Name = "Iron Skin",
				UnlockLevel = 35,
				Cooldown = 60f,
				StaminaCost = 30f,
				IconItem = "ArmorIronChest",
				CastAction = CastIronSkin,
				Describe = (int lvl) => $"Your skin turns to iron: massive defense for {IronSkinDuration():0} s"
			},
			new SpellDef
			{
				Name = "Bloodbath",
				UnlockLevel = 45,
				Cooldown = 60f,
				StaminaCost = 60f,
				IconItem = "AxeBlackMetal",
				CastAction = CastBloodbath,
				Describe = (int lvl) => $"A storm of blades for {(float)BloodbathTicks() * 0.5f:0.#} s ({AdjBloodbathDamage(lvl)} slash per hit, {BloodbathRadius():0.#} m) — heals you per enemy struck"
			}
		};

		public static readonly SpellDef[] RavagerSpells = new SpellDef[5]
		{
			BersCleave,
			new SpellDef
			{
				Name = "Charge",
				UnlockLevel = 10,
				Cooldown = 8f,
				StaminaCost = 20f,
				IconItem = "AxeIron",
				CastAction = CastCharge,
				Describe = (int lvl) => $"Forward dash that tramples enemies ({AdjChargeDamage(lvl)} slash)"
			},
			new SpellDef
			{
				Name = "Execute",
				UnlockLevel = 20,
				Cooldown = 10f,
				StaminaCost = 25f,
				IconItem = "AxeBlackMetal",
				CastAction = CastExecute,
				Describe = (int lvl) => $"A brutal strike on the foe ahead ({AdjExecuteDamage(lvl)} slash, up to +{ExecuteBonusPercent()}% vs wounded enemies)"
			},
			new SpellDef
			{
				Name = "Berserker Fury",
				UnlockLevel = 35,
				Cooldown = 45f,
				StaminaCost = 30f,
				IconItem = "TrophyWolf",
				CastAction = CastFury,
				Describe = (int lvl) => $"+{FuryPercent()}% damage and nearly free attacks for {FuryDuration():0} s"
			},
			new SpellDef
			{
				Name = "Rampage",
				UnlockLevel = 45,
				Cooldown = 45f,
				StaminaCost = 55f,
				IconItem = "SwordIron",
				CastAction = CastRampage,
				Describe = (int lvl) => $"A frenzy of {RampageHits()} strikes on the enemy ahead ({AdjRampageDamage(lvl)} slash each)"
			}
		};

		public static readonly SpellDef[] LancerSpells = new SpellDef[5]
		{
			BersSpearThrow,
			new SpellDef
			{
				Name = "Charge",
				UnlockLevel = 10,
				Cooldown = 8f,
				StaminaCost = 20f,
				IconItem = "AxeIron",
				CastAction = CastCharge,
				Describe = (int lvl) => $"Lance forward, trampling enemies ({AdjChargeDamage(lvl)} pierce)"
			},
			new SpellDef
			{
				Name = "Spear Barrage",
				UnlockLevel = 20,
				Cooldown = 8f,
				StaminaCost = 25f,
				IconItem = "SpearChitin",
				CastAction = CastSpearBarrage,
				Describe = (int lvl) => $"Hurl a fan of {SpearVolleyCount()} spears ({AdjSpearVolleyDamage(lvl)} pierce each)"
			},
			new SpellDef
			{
				Name = "Impale",
				UnlockLevel = 35,
				Cooldown = 12f,
				StaminaCost = 35f,
				IconItem = "SpearChitin",
				CastAction = CastImpale,
				Describe = (int lvl) => $"A heavy spear runs through the foes ahead ({AdjImpaleDamage(lvl)} pierce)" + (TalentSystem.Has(LP, "la_impalepull") ? " and drags them to you" : "")
			},
			new SpellDef
			{
				Name = "Spear Storm",
				UnlockLevel = 45,
				Cooldown = 60f,
				StaminaCost = 80f,
				IconItem = "SpearBronze",
				CastTime = 0f,
				CastAction = CastSpearStorm,
				Describe = (int lvl) => $"{SpearStormCount()} spears rain from the sky ({AdjSpearStormDamage(lvl)} pierce each, {SpearStormRadius():0.#} m)"
			}
		};

		public static readonly SpellDef[] WarhoundSpells = new SpellDef[5]
		{
			BersSpearThrow,
			new SpellDef
			{
				Name = "Pounce",
				UnlockLevel = 10,
				Cooldown = 8f,
				StaminaCost = 20f,
				IconItem = "SpearChitin",
				CastAction = CastPounce,
				Describe = (int lvl) => $"Leap onto the nearest foe within {PounceRange():0} m ({AdjPounceDamage(lvl)} pierce)"
			},
			new SpellDef
			{
				Name = "Rapid Throw",
				UnlockLevel = 20,
				Cooldown = 10f,
				StaminaCost = 25f,
				IconItem = "SpearBronze",
				CastAction = CastRapidThrow,
				Describe = (int lvl) => $"Hurl {RapidThrowCount()} spears in quick succession ({AdjRapidThrowDamage(lvl)} pierce each)"
			},
			new SpellDef
			{
				Name = "Berserker Fury",
				UnlockLevel = 35,
				Cooldown = 45f,
				StaminaCost = 30f,
				IconItem = "TrophyWolf",
				CastAction = CastFury,
				Describe = (int lvl) => $"+{FuryPercent()}% damage and nearly free attacks for {FuryDuration():0} s"
			},
			new SpellDef
			{
				Name = "Wild Hunt",
				UnlockLevel = 45,
				Cooldown = 60f,
				StaminaCost = 50f,
				IconItem = "TrophyWolf",
				CastAction = CastWildHunt,
				Describe = (int lvl) => $"The hunt takes you: +{WildHuntPercent()}% attack, faster and tireless for {WildHuntDuration():0} s"
			}
		};

		public static readonly SpellDef[] NecromancerSpells = new SpellDef[8]
		{
			new SpellDef
			{
				Name = "Life Drain",
				UnlockLevel = 10,
				Cooldown = 8f,
				StaminaCost = 20f,
				IconItem = "Bloodbag",
				CastAction = CastLifeDrain,
				Describe = (int lvl) => $"Drain the life of nearby enemies ({AdjDrainDamage(lvl)} damage, {AdjDrainHeal(lvl)} HP healed per enemy hit)"
			},
			new SpellDef
			{
				Name = "Summon Skeleton",
				UnlockLevel = 20,
				Cooldown = 10f,
				StaminaCost = 30f,
				IconItem = "TrophySkeleton",
				CastAction = CastSummonSkeleton,
				Describe = (int lvl) => $"Raise a skeleton that fights for you (max {MaxSkeletons(lvl)})"
			},
			new SpellDef
			{
				Name = "Ooze Bomb",
				UnlockLevel = 30,
				Cooldown = 8f,
				StaminaCost = 25f,
				IconItem = "Ooze",
				CastAction = CastOozeBomb,
				Describe = (int lvl) => $"Throw a bomb that bursts into a poison cloud ({AdjOozeDamage(lvl)} poison damage)"
			},
			new SpellDef
			{
				Name = "Toxic Cloud",
				UnlockLevel = 40,
				Cooldown = 20f,
				StaminaCost = 40f,
				IconItem = "Guck",
				CastTime = 1.5f,
				CastAction = CastToxicCloud,
				Describe = (int lvl) => $"Bonemass miasma in front of you: {ToxicWaves()} waves of poison ({AdjToxicTick(lvl)} damage each, {ToxicRadius():0} m)"
			},
			new SpellDef
			{
				Name = "Spectral Wave",
				UnlockLevel = 50,
				Cooldown = 18f,
				StaminaCost = 45f,
				IconItem = "Entrails",
				CastAction = CastSpectralWave,
				Describe = (int lvl) => $"Wave of spirits that rends and repels ({AdjSpectralDamage(lvl)} damage, 8 m)"
			},
			new SpellDef
			{
				Name = "Bone Armor",
				UnlockLevel = 60,
				Cooldown = 60f,
				StaminaCost = 30f,
				IconItem = "BoneFragments",
				CastAction = CastBoneArmor,
				Describe = (int lvl) => $"Ancient bones armor you for {BoneArmorDuration():0} seconds"
			},
			new SpellDef
			{
				Name = "Putrid Rain",
				UnlockLevel = 70,
				Cooldown = 30f,
				StaminaCost = 60f,
				IconItem = "BombOoze",
				CastTime = 2f,
				CastAction = CastPutridRain,
				Describe = (int lvl) => $"{PutridBombs()} ooze bombs rain down in front of you ({AdjPutridDamage(lvl)} poison damage each)"
			},
			new SpellDef
			{
				Name = "Army of the Dead",
				UnlockLevel = 80,
				Cooldown = 90f,
				StaminaCost = 80f,
				IconItem = "TrophyDraugrElite",
				CastTime = 2.5f,
				CastAction = CastArmyOfTheDead,
				Describe = (int lvl) => $"{ArmyCount()} skeletons rise for {ArmyLifetime:0} s plus a spectral blast ({AdjSpectralDamage(lvl)} damage, 10 m)"
			}
		};

		public static readonly SpellDef[] OverlordSpells = new SpellDef[8]
		{
			new SpellDef
			{
				Name = "Life Drain",
				UnlockLevel = 10,
				Cooldown = 8f,
				StaminaCost = 20f,
				IconItem = "TrophySkeleton",
				CastAction = CastLifeDrain,
				Describe = (int lvl) => $"Drain the life of nearby enemies ({AdjDrainDamage(lvl)} damage, {AdjDrainHeal(lvl)} HP healed per enemy hit)"
			},
			new SpellDef
			{
				Name = "Summon Revenant",
				UnlockLevel = 20,
				Cooldown = 12f,
				StaminaCost = 35f,
				IconItem = "TrophySkeletonPoison",
				CastAction = CastSummonRevenant,
				Describe = (int lvl) => $"Raise an ELITE skeleton with fearsome strength (max {MaxSkeletons(lvl)} minions)"
			},
			new SpellDef
			{
				Name = "Ooze Bomb",
				UnlockLevel = 30,
				Cooldown = 8f,
				StaminaCost = 25f,
				IconItem = "Ooze",
				CastAction = CastOozeBomb,
				Describe = (int lvl) => $"Throw a bomb that bursts into a poison cloud ({AdjOozeDamage(lvl)} poison damage)"
			},
			new SpellDef
			{
				Name = "Toxic Cloud",
				UnlockLevel = 40,
				Cooldown = 20f,
				StaminaCost = 40f,
				IconItem = "Guck",
				CastTime = 1.5f,
				CastAction = CastToxicCloud,
				Describe = (int lvl) => $"Bonemass miasma in front of you: {ToxicWaves()} waves of poison ({AdjToxicTick(lvl)} damage each, {ToxicRadius():0} m)"
			},
			new SpellDef
			{
				Name = "Spectral Wave",
				UnlockLevel = 50,
				Cooldown = 15f,
				StaminaCost = 35f,
				IconItem = "TrophyWraith",
				CastAction = CastSpectralWave,
				Describe = (int lvl) => $"Wave of spirits that rends and repels ({AdjSpectralDamage(lvl)} damage, 8 m)"
			},
			new SpellDef
			{
				Name = "Bone Pact",
				UnlockLevel = 60,
				Cooldown = 60f,
				StaminaCost = 30f,
				IconItem = "BoneFragments",
				CastAction = CastBonePact,
				Describe = (int lvl) => $"Ancient bones armor you for {BoneArmorDuration():0} s while your minions are healed and enraged (+{PactBonusPercent()}% damage for {PactDuration():0} s)"
			},
			new SpellDef
			{
				Name = "Putrid Rain",
				UnlockLevel = 70,
				Cooldown = 30f,
				StaminaCost = 60f,
				IconItem = "BombOoze",
				CastTime = 2f,
				CastAction = CastPutridRain,
				Describe = (int lvl) => $"{PutridBombs()} ooze bombs rain down in front of you ({AdjPutridDamage(lvl)} poison damage each)"
			},
			new SpellDef
			{
				Name = "Endless Legion",
				UnlockLevel = 80,
				Cooldown = 90f,
				StaminaCost = 80f,
				IconItem = "TrophyDraugrElite",
				CastTime = 2.5f,
				CastAction = CastArmyOfTheDead,
				Describe = (int lvl) => $"{ArmyCount()} skeletons rise for {ArmyLifetime:0} s plus a spectral blast ({AdjSpectralDamage(lvl)} damage, 10 m)"
			}
		};

		private static readonly SpellDef NecroOozeBomb = new SpellDef
		{
			Name = "Ooze Bomb",
			UnlockLevel = 1,
			Cooldown = 8f,
			StaminaCost = 25f,
			IconItem = "Ooze",
			CastAction = CastOozeBomb,
			Describe = (int lvl) => $"Throw a bomb that bursts into a poison cloud ({AdjOozeDamage(lvl)} poison damage)"
		};

		private static readonly SpellDef NecroLifeDrain = new SpellDef
		{
			Name = "Life Drain",
			UnlockLevel = 1,
			Cooldown = 8f,
			StaminaCost = 20f,
			IconItem = "Bloodbag",
			CastAction = CastLifeDrain,
			Describe = (int lvl) => $"Drain the life of nearby enemies ({AdjDrainDamage(lvl)} spirit, {AdjDrainHeal(lvl)} HP per enemy)"
		};

		private static readonly SpellDef NecroSummonSkeleton = new SpellDef
		{
			Name = "Summon Skeleton",
			UnlockLevel = 1,
			Cooldown = 10f,
			StaminaCost = 30f,
			IconItem = "TrophySkeleton",
			CastAction = CastSummonSkeleton,
			Describe = (int lvl) => $"Raise a skeleton that fights for you (max {MaxSkeletons(lvl)})"
		};

		private static readonly SpellDef[] NecroPlagueBaseOnly = new SpellDef[1] { NecroOozeBomb };

		private static readonly SpellDef[] NecroSpiritBaseOnly = new SpellDef[1] { NecroLifeDrain };

		private static readonly SpellDef[] NecroBoneBaseOnly = new SpellDef[1] { NecroSummonSkeleton };

		public static readonly SpellDef[] PestilentSpells = new SpellDef[5]
		{
			NecroOozeBomb,
			new SpellDef
			{
				Name = "Toxic Cloud",
				UnlockLevel = 10,
				Cooldown = 20f,
				StaminaCost = 40f,
				IconItem = "Guck",
				CastAction = CastToxicCloud,
				Describe = (int lvl) => $"Bonemass miasma: {ToxicWaves()} waves of poison ({AdjToxicTick(lvl)} each, {ToxicRadius():0} m)"
			},
			new SpellDef
			{
				Name = "Putrid Rain",
				UnlockLevel = 20,
				Cooldown = 24f,
				StaminaCost = 55f,
				IconItem = "BombOoze",
				CastTime = 1.5f,
				CastAction = CastPutridRain,
				Describe = (int lvl) => $"{PutridBombs()} ooze bombs rain down ({AdjPutridDamage(lvl)} poison each)"
			},
			new SpellDef
			{
				Name = "Plague Nova",
				UnlockLevel = 35,
				Cooldown = 14f,
				StaminaCost = 40f,
				IconItem = "Guck",
				CastAction = CastPlagueNova,
				Describe = (int lvl) => $"A burst of toxin around you ({AdjPlagueNovaDamage(lvl)} poison, {PlagueNovaRadius():0} m)"
			},
			new SpellDef
			{
				Name = "Pandemic",
				UnlockLevel = 45,
				Cooldown = 60f,
				StaminaCost = 80f,
				IconItem = "TrophyBonemass",
				CastAction = CastPandemic,
				Describe = (int lvl) => $"A great festering field ({PandemicRadius():0} m, {PandemicDuration():0} s, {AdjPandemicTick(lvl)} poison/s)"
			}
		};

		public static readonly SpellDef[] BlightcallerSpells = new SpellDef[5]
		{
			NecroOozeBomb,
			new SpellDef
			{
				Name = "Plague Bolt",
				UnlockLevel = 10,
				Cooldown = 6f,
				StaminaCost = 20f,
				IconItem = "Guck",
				CastAction = CastPlagueBolt,
				Describe = (int lvl) => $"A fast bolt of venom ({AdjPlagueBoltDamage(lvl)} poison), piercing {PlagueBoltPierce()} enemies"
			},
			new SpellDef
			{
				Name = "Toxic Cloud",
				UnlockLevel = 20,
				Cooldown = 20f,
				StaminaCost = 40f,
				IconItem = "Guck",
				CastAction = CastToxicCloud,
				Describe = (int lvl) => $"Bonemass miasma: {ToxicWaves()} waves of poison ({AdjToxicTick(lvl)} each, {ToxicRadius():0} m)"
			},
			new SpellDef
			{
				Name = "Corrode",
				UnlockLevel = 35,
				Cooldown = 10f,
				StaminaCost = 30f,
				IconItem = "Entrails",
				CastAction = CastCorrode,
				Describe = (int lvl) => $"Rot the foe ahead: {AdjCorrodeDamage(lvl)} poison over {CorrodeDuration():0} s" + (TalentSystem.Has(LP, "bli_notable") ? ", spreading to a nearby enemy" : "")
			},
			new SpellDef
			{
				Name = "Putrid Rain",
				UnlockLevel = 45,
				Cooldown = 30f,
				StaminaCost = 60f,
				IconItem = "BombOoze",
				CastTime = 1.5f,
				CastAction = CastPutridRain,
				Describe = (int lvl) => $"{PutridBombs()} ooze bombs rain down ({AdjPutridDamage(lvl)} poison each)"
			}
		};

		public static readonly SpellDef[] ReaperSpells = new SpellDef[5]
		{
			NecroLifeDrain,
			new SpellDef
			{
				Name = "Spectral Wave",
				UnlockLevel = 10,
				Cooldown = 18f,
				StaminaCost = 45f,
				IconItem = "Entrails",
				CastAction = CastSpectralWave,
				Describe = (int lvl) => $"Wave of spirits that rends and repels ({AdjSpectralDamage(lvl)} spirit, 8 m)"
			},
			new SpellDef
			{
				Name = "Soul Rip",
				UnlockLevel = 20,
				Cooldown = 7f,
				StaminaCost = 20f,
				IconItem = "TrophyWraith",
				CastAction = CastSoulRip,
				Describe = (int lvl) => $"A spectral lance ({AdjSoulRipDamage(lvl)} spirit) that heals you {SoulRipHeal(lvl)} HP"
			},
			new SpellDef
			{
				Name = "Bone Armor",
				UnlockLevel = 35,
				Cooldown = 45f,
				StaminaCost = 30f,
				IconItem = "BoneFragments",
				CastAction = CastBoneArmor,
				Describe = (int lvl) => $"Ancient bones armor you for {BoneArmorDuration():0} s"
			},
			new SpellDef
			{
				Name = "Death Coil",
				UnlockLevel = 45,
				Cooldown = 45f,
				StaminaCost = 60f,
				IconItem = "TrophyDraugr",
				CastAction = CastDeathCoil,
				Describe = (int lvl) => $"A wave of death ({AdjDeathCoilDamage(lvl)} spirit, {DeathCoilRadius():0} m) that heals you"
			}
		};

		public static readonly SpellDef[] BansheeSpells = new SpellDef[5]
		{
			NecroLifeDrain,
			new SpellDef
			{
				Name = "Spectral Wave",
				UnlockLevel = 10,
				Cooldown = 18f,
				StaminaCost = 45f,
				IconItem = "Entrails",
				CastAction = CastSpectralWave,
				Describe = (int lvl) => $"Wave of spirits that rends and repels ({AdjSpectralDamage(lvl)} spirit, 8 m)"
			},
			new SpellDef
			{
				Name = "Wail",
				UnlockLevel = 20,
				Cooldown = 12f,
				StaminaCost = 35f,
				IconItem = "TrophyDraugr",
				CastAction = CastWail,
				Describe = (int lvl) => $"A ghastly scream ({AdjWailDamage(lvl)} spirit, {WailRadius():0} m) that hurls foes back"
			},
			new SpellDef
			{
				Name = "Spirit Nova",
				UnlockLevel = 35,
				Cooldown = 14f,
				StaminaCost = 40f,
				IconItem = "TrophyWraith",
				CastAction = CastSpiritNova,
				Describe = (int lvl) => $"A burst of spirits around you ({AdjSpiritNovaDamage(lvl)} spirit, {SpiritNovaRadius():0} m)"
			},
			new SpellDef
			{
				Name = "Spectral Storm",
				UnlockLevel = 45,
				Cooldown = 60f,
				StaminaCost = 80f,
				IconItem = "TrophyDraugrElite",
				CastAction = CastSpectralStorm,
				Describe = (int lvl) => $"{SpectralStormCount()} vengeful spirits rain down ({AdjSpectralStormDamage(lvl)} spirit each, {SpectralStormRadius():0} m)"
			}
		};

		public static readonly SpellDef[] BonelordSpells = new SpellDef[5]
		{
			NecroSummonSkeleton,
			new SpellDef
			{
				Name = "Bone Armor",
				UnlockLevel = 10,
				Cooldown = 45f,
				StaminaCost = 30f,
				IconItem = "BoneFragments",
				CastAction = CastBoneArmor,
				Describe = (int lvl) => $"Ancient bones armor you for {BoneArmorDuration():0} s"
			},
			new SpellDef
			{
				Name = "Raise Horde",
				UnlockLevel = 20,
				Cooldown = 18f,
				StaminaCost = 45f,
				IconItem = "TrophySkeletonPoison",
				CastTime = 1f,
				CastAction = CastRaiseHorde,
				Describe = (int lvl) => $"Instantly raise {RaiseHordeCount()} skeletons (up to max {MaxSkeletons(lvl)})"
			},
			new SpellDef
			{
				Name = "Army of the Dead",
				UnlockLevel = 35,
				Cooldown = 90f,
				StaminaCost = 80f,
				IconItem = "TrophyDraugrElite",
				CastTime = 2.5f,
				CastAction = CastArmyOfTheDead,
				Describe = (int lvl) => $"{ArmyCount()} skeletons rise for {ArmyLifetime:0} s plus a spectral blast ({AdjSpectralDamage(lvl)} damage, 10 m)"
			},
			new SpellDef
			{
				Name = "Bone Storm",
				UnlockLevel = 45,
				Cooldown = 40f,
				StaminaCost = 70f,
				IconItem = "TrophyDraugrElite",
				CastTime = 1f,
				CastAction = CastBoneStorm,
				Describe = (int lvl) => $"A whirling storm of bone shards around you ({BoneStormWaves()} waves, {AdjBoneStormDamage(lvl)} damage each, {BoneStormRadius():0} m)"
			}
		};

		public static readonly SpellDef[] DeathknightSpells = new SpellDef[5]
		{
			NecroSummonSkeleton,
			new SpellDef
			{
				Name = "Summon Revenant",
				UnlockLevel = 10,
				Cooldown = 12f,
				StaminaCost = 35f,
				IconItem = "TrophySkeletonPoison",
				CastAction = CastSummonRevenant,
				Describe = (int lvl) => $"Raise an ELITE skeleton with fearsome strength (max {MaxSkeletons(lvl)} minions)"
			},
			new SpellDef
			{
				Name = "Bone Armor",
				UnlockLevel = 20,
				Cooldown = 45f,
				StaminaCost = 30f,
				IconItem = "BoneFragments",
				CastAction = CastBoneArmor,
				Describe = (int lvl) => $"Ancient bones armor you for {BoneArmorDuration():0} s"
			},
			new SpellDef
			{
				Name = "Bone Pact",
				UnlockLevel = 35,
				Cooldown = 60f,
				StaminaCost = 40f,
				IconItem = "BoneFragments",
				CastAction = CastBonePact,
				Describe = (int lvl) => $"Ancient bones armor you for {BoneArmorDuration():0} s while your minions are healed and enraged (+{PactBonusPercent()}% damage for {PactDuration():0} s)"
			},
			new SpellDef
			{
				Name = "Death Pact",
				UnlockLevel = 45,
				Cooldown = 45f,
				StaminaCost = 60f,
				IconItem = "TrophyDraugr",
				CastAction = CastDeathPact,
				Describe = (int lvl) => $"A pact of death erupts around you ({AdjDeathPactDamage(lvl)} spirit, {DeathPactRadius():0} m) healing your minions" + (TalentSystem.Has(LP, "dk_capstone") ? " and you" : "")
			}
		};

		private static readonly SpellDef DruidRavenForm = new SpellDef
		{
			Name = "Raven Form",
			UnlockLevel = 1,
			Cooldown = 3f,
			StaminaCost = 10f,
			IconItem = "Feathers",
			CastAction = CastRavenForm,
			Describe = (int lvl) => $"Take raven shape and fly (Jump/Space rise, Crouch/Ctrl dive; {4f:0}/s stamina). Cannot attack; cast again to land."
		};

		private static readonly SpellDef DruidForestBlessingBase = new SpellDef
		{
			Name = "Forest Blessing",
			UnlockLevel = 1,
			Cooldown = 25f,
			StaminaCost = 25f,
			IconItem = "AncientSeed",
			CastAction = CastForestBlessing,
			Describe = (int lvl) => $"The wild empowers allies within {BlessingRadius():0} m for {ForestBlessingDuration():0} s"
		};

		private static readonly SpellDef DruidRegrowthBase = new SpellDef
		{
			Name = "Regrowth",
			UnlockLevel = 1,
			Cooldown = 12f,
			StaminaCost = 25f,
			IconItem = "Dandelion",
			CastAction = CastRegrowth,
			Describe = (int lvl) => $"Life surges: you and allies within {BlessingRadius():0} m recover {AdjRegrowthHeal(lvl)} HP"
		};

		private static readonly SpellDef[] DruidWildBaseOnly = new SpellDef[1] { DruidRavenForm };

		private static readonly SpellDef[] DruidWardenBaseOnly = new SpellDef[1] { DruidForestBlessingBase };

		private static readonly SpellDef[] DruidRestoBaseOnly = new SpellDef[1] { DruidRegrowthBase };

		public static readonly SpellDef[] WerewolfSpells = new SpellDef[5]
		{
			DruidRavenForm,
			new SpellDef
			{
				Name = "Wolf Form",
				UnlockLevel = 10,
				Cooldown = 6f,
				StaminaCost = 15f,
				IconItem = "TrophyWolf",
				CastAction = CastWolfForm,
				Describe = (int lvl) => "Take wolf shape: faster, fiercer claws. Cast again to revert."
			},
			new SpellDef
			{
				Name = "Savage Pounce",
				UnlockLevel = 20,
				Cooldown = 9f,
				StaminaCost = 25f,
				IconItem = "TrophyWolf",
				CastAction = CastSavagePounce,
				Describe = (int lvl) => $"Leap forward and rip ({AdjSavagePounceDamage(lvl)} slash, {SavagePounceRange():0} m)"
			},
			new SpellDef
			{
				Name = "Savage Rend",
				UnlockLevel = 35,
				Cooldown = 10f,
				StaminaCost = 30f,
				IconItem = "Entrails",
				CastAction = CastSavageRend,
				Describe = (int lvl) => $"Tear the foe ahead: {AdjSavageRendHit(lvl)} slash and bleeding ({AdjRendTick(lvl)}/s for {RendTicks()} s)"
			},
			new SpellDef
			{
				Name = "Blood Moon",
				UnlockLevel = 45,
				Cooldown = 60f,
				StaminaCost = 50f,
				IconItem = "TrophyWolf",
				CastAction = CastBloodMoon,
				Describe = (int lvl) => $"The pack's fury: +{BloodMoonAttack()}% attack for {BloodMoonDuration():0} s" + (TalentSystem.Has(LP, "ww_packlead") ? " (you and nearby allies)" : "")
			}
		};

		public static readonly SpellDef[] WerebearSpells = new SpellDef[5]
		{
			DruidRavenForm,
			new SpellDef
			{
				Name = "Bear Form",
				UnlockLevel = 10,
				Cooldown = 6f,
				StaminaCost = 15f,
				IconItem = "TrophyBoar",
				CastAction = CastBearForm,
				Describe = (int lvl) => "Take bear shape: heavy, armored, crushing paws. Cast again to revert."
			},
			new SpellDef
			{
				Name = "Maul",
				UnlockLevel = 20,
				Cooldown = 7f,
				StaminaCost = 25f,
				IconItem = "SledgeStagbreaker",
				CastAction = CastMaul,
				Describe = (int lvl) => $"A sweeping paw ({AdjMaulDamage(lvl)} blunt, {MaulRadius():0} m arc, heavy knockback)"
			},
			new SpellDef
			{
				Name = "Thunderous Roar",
				UnlockLevel = 35,
				Cooldown = 18f,
				StaminaCost = 35f,
				IconItem = "TrophyBoar",
				CastAction = CastThunderousRoar,
				Describe = (int lvl) => $"A deafening roar ({AdjRoarDamage(lvl)} blunt, {RoarRadius():0} m) that staggers foes"
			},
			new SpellDef
			{
				Name = "Feral Charge",
				UnlockLevel = 45,
				Cooldown = 20f,
				StaminaCost = 45f,
				IconItem = "SledgeStagbreaker",
				CastAction = CastFeralCharge,
				Describe = (int lvl) => $"Charge forward, trampling foes ({AdjFeralChargeDamage(lvl)} blunt, {FeralChargeRange():0} m)"
			}
		};

		public static readonly SpellDef[] SkaldSpells = new SpellDef[5]
		{
			DruidForestBlessingBase,
			new SpellDef
			{
				Name = "Wind's Grace",
				UnlockLevel = 10,
				Cooldown = 30f,
				StaminaCost = 30f,
				IconItem = "Feathers",
				CastAction = CastWindsGrace,
				Describe = (int lvl) => $"The wind carries allies within {BlessingRadius():0} m: far lighter running for {WindsGraceDuration():0} s"
			},
			new SpellDef
			{
				Name = "Nature's Fury",
				UnlockLevel = 20,
				Cooldown = 30f,
				StaminaCost = 45f,
				IconItem = "TrophyAbomination",
				CastAction = CastNaturesFury,
				Describe = (int lvl) => $"Allies within {NatureFuryRadius():0} m deal +{NatureFuryAttack()}% pierce and poison damage for {NatureFuryDuration():0} s"
			},
			new SpellDef
			{
				Name = "Forest's Embrace",
				UnlockLevel = 35,
				Cooldown = 30f,
				StaminaCost = 50f,
				IconItem = "Honey",
				CastAction = CastForestEmbrace,
				Describe = (int lvl) => $"The forest embraces allies within {BlessingRadius():0} m: {AdjEmbraceHeal(lvl)} HP and fast regeneration for {EmbraceDuration():0} s"
			},
			new SpellDef
			{
				Name = "War Song",
				UnlockLevel = 45,
				Cooldown = 60f,
				StaminaCost = 60f,
				IconItem = "AncientSeed",
				CastAction = CastWarSong,
				Describe = (int lvl) => $"A rallying anthem: allies within {WarSongRadius():0} m gain +{WarSongAttack()}% attack and +{WarSongArmor()} armor for {WarSongDuration():0} s"
			}
		};

		public static readonly SpellDef[] BeastmasterSpells = new SpellDef[5]
		{
			DruidForestBlessingBase,
			new SpellDef
			{
				Name = "Summon Wolf",
				UnlockLevel = 10,
				Cooldown = 10f,
				StaminaCost = 30f,
				IconItem = "TrophyWolf",
				CastAction = CastSummonWolf,
				Describe = (int lvl) => $"Call a wolf companion to fight for you (max {MaxCompanions()})"
			},
			new SpellDef
			{
				Name = "Summon Bear",
				UnlockLevel = 20,
				Cooldown = 14f,
				StaminaCost = 40f,
				IconItem = "TrophyBoar",
				CastAction = CastSummonBear,
				Describe = (int lvl) => $"Call a mighty bear companion: tough and fierce (max {MaxCompanions()})"
			},
			new SpellDef
			{
				Name = "Forest's Embrace",
				UnlockLevel = 35,
				Cooldown = 30f,
				StaminaCost = 50f,
				IconItem = "Honey",
				CastAction = CastForestEmbrace,
				Describe = (int lvl) => $"The forest embraces allies within {BlessingRadius():0} m: {AdjEmbraceHeal(lvl)} HP and fast regeneration for {EmbraceDuration():0} s"
			},
			new SpellDef
			{
				Name = "Call of the Wild",
				UnlockLevel = 45,
				Cooldown = 90f,
				StaminaCost = 80f,
				IconItem = "TrophyWolf",
				CastTime = 2f,
				CastAction = CastCallOfTheWild,
				Describe = (int lvl) => $"A wild pack answers: {WildPackCount()} wolves rush to your side for {ArmyLifetime:0} s"
			}
		};

		public static readonly SpellDef[] LifekeeperSpells = new SpellDef[5]
		{
			DruidRegrowthBase,
			new SpellDef
			{
				Name = "Healing Bloom",
				UnlockLevel = 10,
				Cooldown = 30f,
				StaminaCost = 40f,
				IconItem = "Raspberry",
				CastTime = 1.5f,
				CastAction = CastHealingBloom,
				Describe = (int lvl) => $"A meadow of healing flowers blooms ({BloomRadius():0} m, {BloomDuration():0} s): allies inside recover {AdjBloomHeal(lvl)} HP per second"
			},
			new SpellDef
			{
				Name = "Forest's Embrace",
				UnlockLevel = 20,
				Cooldown = 30f,
				StaminaCost = 50f,
				IconItem = "Honey",
				CastAction = CastForestEmbrace,
				Describe = (int lvl) => $"The forest embraces allies within {BlessingRadius():0} m: {AdjEmbraceHeal(lvl)} HP and fast regeneration for {EmbraceDuration():0} s"
			},
			new SpellDef
			{
				Name = "Wrath of Yggdrasil",
				UnlockLevel = 35,
				Cooldown = 75f,
				StaminaCost = 80f,
				IconItem = "YggdrasilWood",
				CastTime = 2.5f,
				CastAction = CastWrathOfYggdrasil,
				Describe = (int lvl) => $"The World Tree answers: allies recover {AdjYggdrasilHeal(lvl)} HP and enemies take {AdjYggdrasilDamage(lvl)} pierce + poison"
			},
			new SpellDef
			{
				Name = "Tranquility",
				UnlockLevel = 45,
				Cooldown = 60f,
				StaminaCost = 70f,
				IconItem = "Honey",
				CastTime = 1f,
				CastAction = CastTranquility,
				Describe = (int lvl) => $"A field of serenity ({TranquilityRadius():0} m): {AdjTranquilityBurst(lvl)} HP now, then {AdjTranquilityTick(lvl)} HP/s for {TranquilityDuration():0} s"
			}
		};

		public static readonly SpellDef[] GrovekeeperSpells = new SpellDef[5]
		{
			DruidRegrowthBase,
			new SpellDef
			{
				Name = "Healing Bloom",
				UnlockLevel = 10,
				Cooldown = 30f,
				StaminaCost = 40f,
				IconItem = "Raspberry",
				CastTime = 1.5f,
				CastAction = CastHealingBloom,
				Describe = (int lvl) => $"A meadow of healing flowers blooms ({BloomRadius():0} m, {BloomDuration():0} s): allies inside recover {AdjBloomHeal(lvl)} HP per second"
			},
			new SpellDef
			{
				Name = "Grasping Roots",
				UnlockLevel = 20,
				Cooldown = 15f,
				StaminaCost = 35f,
				IconItem = "Root",
				CastAction = CastGraspingRoots,
				Describe = (int lvl) => $"Roots erupt from the earth ({AdjRootsDamage(lvl)} pierce + poison, {RootsRadius():0} m) and hurl enemies away"
			},
			new SpellDef
			{
				Name = "Wind's Grace",
				UnlockLevel = 35,
				Cooldown = 30f,
				StaminaCost = 30f,
				IconItem = "Feathers",
				CastAction = CastWindsGrace,
				Describe = (int lvl) => $"The wind carries allies within {BlessingRadius():0} m: far lighter running for {WindsGraceDuration():0} s"
			},
			new SpellDef
			{
				Name = "Barkward",
				UnlockLevel = 45,
				Cooldown = 45f,
				StaminaCost = 50f,
				IconItem = "TrollHide",
				CastAction = CastBarkward,
				Describe = (int lvl) => $"Living bark shields allies within {BarkwardRadius():0} m: +{BarkwardArmor()} armor for {BarkwardDuration():0} s" + (TalentSystem.Has(LP, "gk_capstone") ? " and steady regeneration" : "")
			}
		};

		private static readonly SpellDef EinherThunderbolt = new SpellDef
		{
			Name = "Thunderbolt",
			UnlockLevel = 1,
			Cooldown = 5f,
			StaminaCost = 20f,
			IconItem = "StaffLightning",
			CastAction = CastThunderbolt,
			Describe = (int lvl) => $"Hurl a bolt of Thor's lightning ({AdjThunderboltDamage(lvl)} lightning)" + ((TalentSystem.Has(LP, "sto_notable") || TalentSystem.Has(LP, "thu_capstone")) ? ", chaining to a nearby foe" : "")
		};

		private static readonly SpellDef EinherSpearBase = new SpellDef
		{
			Name = "Spear of the Gods",
			UnlockLevel = 1,
			Cooldown = 6f,
			StaminaCost = 20f,
			IconItem = "SpearBronze",
			CastAction = CastSpearOfTheGods,
			Describe = (int lvl) => string.Format("Hurl a radiant spear ({0} pierce + {1} lightning)", AdjGodSpearPierce(lvl), Adj(GodSpearLightning(lvl), "lightning"))
		};

		private static readonly SpellDef EinherValkyrieBase = new SpellDef
		{
			Name = "Valkyrie's Blessing",
			UnlockLevel = 1,
			Cooldown = 30f,
			StaminaCost = 30f,
			IconItem = "TrophyValkyrie",
			CastAction = CastBattleBlessing,
			Describe = (int lvl) => $"Bless allies within {BlessingRadius():0} m: +15% damage and swift stamina for {BlessingDuration():0} s"
		};

		private static readonly SpellDef[] EinherStormBaseOnly = new SpellDef[1] { EinherThunderbolt };

		private static readonly SpellDef[] EinherSpearBaseOnly = new SpellDef[1] { EinherSpearBase };

		private static readonly SpellDef[] EinherValhallaBaseOnly = new SpellDef[1] { EinherValkyrieBase };

		public static readonly SpellDef[] ThundererSpells = new SpellDef[5]
		{
			EinherThunderbolt,
			new SpellDef
			{
				Name = "Judgement",
				UnlockLevel = 10,
				Cooldown = 14f,
				StaminaCost = 35f,
				IconItem = "Thunderstone",
				CastTime = 1.5f,
				CastAction = CastJudgement,
				Describe = (int lvl) => string.Format("{0} of Thor strike where you aim ({1} damage, {2:0} m)", (JudgementStrikes() > 1) ? (JudgementStrikes() + " bolts") : "A bolt", AdjJudgementDamage(lvl), JudgementRadius())
			},
			new SpellDef
			{
				Name = "Sky Dive",
				UnlockLevel = 20,
				Cooldown = 10f,
				StaminaCost = 25f,
				IconItem = "Feathers",
				CastAction = CastSkyDive,
				Describe = (int lvl) => $"Leap from the sky and crash down ({AdjSkyDiveDamage(lvl)} damage, {SkyDiveRadius():0} m)"
			},
			new SpellDef
			{
				Name = "Thunderclap",
				UnlockLevel = 35,
				Cooldown = 14f,
				StaminaCost = 40f,
				IconItem = "StaffLightning",
				CastAction = CastThunderclap,
				Describe = (int lvl) => $"A burst of lightning around you ({AdjThunderclapDamage(lvl)} lightning, {ThunderclapRadius():0} m)"
			},
			new SpellDef
			{
				Name = "Ragnarök",
				UnlockLevel = 45,
				Cooldown = 75f,
				StaminaCost = 80f,
				IconItem = "TrophyDragonQueen",
				CastTime = 2.5f,
				CastAction = CastRagnarok,
				Describe = (int lvl) => $"Ascend and crash down ({AdjRagnarokDamage(lvl)} damage, {RagnarokRadius():0} m), then {RagnarokBolts()} bolts chain across your foes"
			}
		};

		public static readonly SpellDef[] StormheraldSpells = new SpellDef[5]
		{
			EinherThunderbolt,
			new SpellDef
			{
				Name = "Judgement",
				UnlockLevel = 10,
				Cooldown = 14f,
				StaminaCost = 35f,
				IconItem = "Thunderstone",
				CastTime = 1.5f,
				CastAction = CastJudgement,
				Describe = (int lvl) => string.Format("{0} of Thor strike where you aim ({1} damage, {2:0} m)", (JudgementStrikes() > 1) ? (JudgementStrikes() + " bolts") : "A bolt", AdjJudgementDamage(lvl), JudgementRadius())
			},
			new SpellDef
			{
				Name = "Thunderstorm",
				UnlockLevel = 20,
				Cooldown = 24f,
				StaminaCost = 50f,
				IconItem = "Thunderstone",
				CastTime = 1f,
				CastAction = CastThunderstorm,
				Describe = (int lvl) => $"A raging storm field ({ThunderstormRadius():0} m, {ThunderstormDuration():0} s, {AdjThunderstormTick(lvl)} lightning/s)"
			},
			new SpellDef
			{
				Name = "Aegis of Valhalla",
				UnlockLevel = 35,
				Cooldown = 60f,
				StaminaCost = 35f,
				IconItem = "ShieldSilver",
				CastAction = CastAegis,
				Describe = (int lvl) => $"Divine shield for {AegisDuration():0} s and a pulse that repels nearby enemies"
			},
			new SpellDef
			{
				Name = "Ragnarök",
				UnlockLevel = 45,
				Cooldown = 75f,
				StaminaCost = 80f,
				IconItem = "TrophyDragonQueen",
				CastTime = 2.5f,
				CastAction = CastRagnarok,
				Describe = (int lvl) => $"Ascend and crash down ({AdjRagnarokDamage(lvl)} damage, {RagnarokRadius():0} m), then {RagnarokBolts()} bolts chain across your foes"
			}
		};

		public static readonly SpellDef[] SpearmasterSpells = new SpellDef[5]
		{
			EinherSpearBase,
			new SpellDef
			{
				Name = "Spear Volley",
				UnlockLevel = 10,
				Cooldown = 12f,
				StaminaCost = 40f,
				IconItem = "SpearChitin",
				CastAction = CastSpearVolley,
				Describe = (int lvl) => $"Fan of {VolleyCount()} radiant spears ({AdjVolleyDamage(lvl)} damage each)"
			},
			new SpellDef
			{
				Name = "Sky Dive",
				UnlockLevel = 20,
				Cooldown = 10f,
				StaminaCost = 25f,
				IconItem = "Feathers",
				CastAction = CastSkyDive,
				Describe = (int lvl) => $"Leap from the sky and crash down ({AdjSkyDiveDamage(lvl)} damage, {SkyDiveRadius():0} m)"
			},
			new SpellDef
			{
				Name = "Battle Blessing",
				UnlockLevel = 35,
				Cooldown = 30f,
				StaminaCost = 25f,
				IconItem = "MeadStaminaMedium",
				CastAction = CastBattleBlessing,
				Describe = (int lvl) => $"+{BlessingAttack()}% damage, swift stamina and cheap attacks for {BlessingDuration():0} s"
			},
			new SpellDef
			{
				Name = "Skyfall Spears",
				UnlockLevel = 45,
				Cooldown = 30f,
				StaminaCost = 60f,
				IconItem = "SpearChitin",
				CastTime = 1.5f,
				CastAction = CastSkyfallSpears,
				Describe = (int lvl) => $"{SkyfallCount()} divine spears rain down ({AdjSkyfallDamage(lvl)} pierce each)"
			}
		};

		public static readonly SpellDef[] ValkyrieKnightSpells = new SpellDef[5]
		{
			EinherSpearBase,
			new SpellDef
			{
				Name = "Sky Dive",
				UnlockLevel = 10,
				Cooldown = 10f,
				StaminaCost = 25f,
				IconItem = "Feathers",
				CastAction = CastSkyDive,
				Describe = (int lvl) => $"Leap from the sky and crash down ({AdjSkyDiveDamage(lvl)} damage, {SkyDiveRadius():0} m)"
			},
			new SpellDef
			{
				Name = "Battle Blessing",
				UnlockLevel = 20,
				Cooldown = 30f,
				StaminaCost = 25f,
				IconItem = "MeadStaminaMedium",
				CastAction = CastBattleBlessing,
				Describe = (int lvl) => $"+{BlessingAttack()}% damage, swift stamina and cheap attacks for {BlessingDuration():0} s"
			},
			new SpellDef
			{
				Name = "Judgement",
				UnlockLevel = 35,
				Cooldown = 14f,
				StaminaCost = 35f,
				IconItem = "Thunderstone",
				CastTime = 1.5f,
				CastAction = CastJudgement,
				Describe = (int lvl) => string.Format("{0} of Thor strike where you aim ({1} damage, {2:0} m)", (JudgementStrikes() > 1) ? (JudgementStrikes() + " bolts") : "A bolt", AdjJudgementDamage(lvl), JudgementRadius())
			},
			new SpellDef
			{
				Name = "Ragnarök",
				UnlockLevel = 45,
				Cooldown = 75f,
				StaminaCost = 80f,
				IconItem = "TrophyDragonQueen",
				CastTime = 2.5f,
				CastAction = CastRagnarok,
				Describe = (int lvl) => $"Ascend and crash down ({AdjRagnarokDamage(lvl)} damage, {RagnarokRadius():0} m), then {RagnarokBolts()} bolts chain across your foes"
			}
		};

		public static readonly SpellDef[] ValkyrieSpells = new SpellDef[5]
		{
			EinherValkyrieBase,
			new SpellDef
			{
				Name = "Aegis of the Host",
				UnlockLevel = 10,
				Cooldown = 60f,
				StaminaCost = 35f,
				IconItem = "ShieldSilver",
				CastAction = CastAegis,
				Describe = (int lvl) => $"Divine shield for {AegisDuration():0} s: allies within {ValkyrieRadius():0} m are protected AND empowered"
			},
			new SpellDef
			{
				Name = "Honor Guard",
				UnlockLevel = 20,
				Cooldown = 20f,
				StaminaCost = 50f,
				IconItem = "TrophyWraith",
				CastAction = CastCallTheFallen,
				Describe = (int lvl) => $"Summon honored spirits (max {SpiritCap()}) whose presence invigorates allies within {ValkyrieRadius():0} m"
			},
			new SpellDef
			{
				Name = "Valhalla's Grace",
				UnlockLevel = 35,
				Cooldown = 30f,
				StaminaCost = 50f,
				IconItem = "MeadHealthMedium",
				CastAction = CastValhallaGrace,
				Describe = (int lvl) => $"The Valkyries mend the host within {GraceRadius():0} m: {AdjGraceHeal(lvl)} HP and fast regeneration for {GraceDuration():0} s"
			},
			new SpellDef
			{
				Name = "Ragnarök",
				UnlockLevel = 45,
				Cooldown = 75f,
				StaminaCost = 80f,
				IconItem = "TrophyDragonQueen",
				CastTime = 2.5f,
				CastAction = CastRagnarok,
				Describe = (int lvl) => $"Ascend and crash down ({AdjRagnarokDamage(lvl)} damage, {RagnarokRadius():0} m), then {RagnarokBolts()} bolts chain across your foes"
			}
		};

		public static readonly SpellDef[] HeraldSpells = new SpellDef[5]
		{
			EinherValkyrieBase,
			new SpellDef
			{
				Name = "Call the Fallen",
				UnlockLevel = 10,
				Cooldown = 20f,
				StaminaCost = 50f,
				IconItem = "TrophyWraith",
				CastAction = CastCallTheFallen,
				Describe = (int lvl) => $"Summon fallen warriors that fight for you (max {SpiritCap()})"
			},
			new SpellDef
			{
				Name = "Soul Spear",
				UnlockLevel = 20,
				Cooldown = 6f,
				StaminaCost = 25f,
				IconItem = "SpearChitin",
				CastAction = CastSoulSpear,
				Describe = (int lvl) => $"Hurl a spear of souls ({AdjSoulSpearDamage(lvl)} spirit)" + (TalentSystem.Has(LP, "her_notable") ? ", piercing through foes" : "")
			},
			new SpellDef
			{
				Name = "Wail of the Fallen",
				UnlockLevel = 35,
				Cooldown = 14f,
				StaminaCost = 40f,
				IconItem = "TrophyWraith",
				CastAction = CastWailOfTheFallen,
				Describe = (int lvl) => $"A wail of the dead erupts around you ({AdjSoulWailDamage(lvl)} spirit, {SoulWailRadius():0} m)"
			},
			new SpellDef
			{
				Name = "Legion of Valhalla",
				UnlockLevel = 45,
				Cooldown = 90f,
				StaminaCost = 80f,
				IconItem = "TrophyDraugrElite",
				CastTime = 2f,
				CastAction = CastLegionOfValhalla,
				Describe = (int lvl) => $"{HeraldLegionCount()} spirit warriors rise for {HeraldLegionLifetime():0} s to fight at your side"
			}
		};

		public static readonly SpellDef[] EinherjarSpells = new SpellDef[8]
		{
			new SpellDef
			{
				Name = "Spear of the Gods",
				UnlockLevel = 10,
				Cooldown = 6f,
				StaminaCost = 20f,
				IconItem = "SpearBronze",
				CastAction = CastSpearOfTheGods,
				Describe = (int lvl) => string.Format("Hurl a radiant spear ({0} pierce + {1} lightning damage)", AdjGodSpearPierce(lvl), Adj(GodSpearLightning(lvl), "lightning"))
			},
			new SpellDef
			{
				Name = "Sky Dive",
				UnlockLevel = 20,
				Cooldown = 10f,
				StaminaCost = 25f,
				IconItem = "Feathers",
				CastAction = CastSkyDive,
				Describe = (int lvl) => $"Leap forward from the sky and crash down ({AdjSkyDiveDamage(lvl)} damage, 5 m)"
			},
			new SpellDef
			{
				Name = "Battle Blessing",
				UnlockLevel = 30,
				Cooldown = 30f,
				StaminaCost = 25f,
				IconItem = "MeadStaminaMedium",
				CastAction = CastBattleBlessing,
				Describe = (int lvl) => $"+15% damage, swift stamina and cheap attacks for {BlessingDuration():0} s"
			},
			new SpellDef
			{
				Name = "Judgement",
				UnlockLevel = 40,
				Cooldown = 14f,
				StaminaCost = 35f,
				IconItem = "Thunderstone",
				CastTime = 1.5f,
				CastAction = CastJudgement,
				Describe = (int lvl) => string.Format("{0} of Thor strikes where you aim ({1} damage, {2:0} m)", (JudgementStrikes() > 1) ? "2 bolts" : "A bolt", AdjJudgementDamage(lvl), JudgementRadius())
			},
			new SpellDef
			{
				Name = "Spear Volley",
				UnlockLevel = 50,
				Cooldown = 12f,
				StaminaCost = 40f,
				IconItem = "SpearChitin",
				CastAction = CastSpearVolley,
				Describe = (int lvl) => $"Fan of {VolleyCount()} radiant spears ({AdjVolleyDamage(lvl)} damage each)"
			},
			new SpellDef
			{
				Name = "Aegis of Valhalla",
				UnlockLevel = 60,
				Cooldown = 60f,
				StaminaCost = 35f,
				IconItem = "ShieldSilver",
				CastAction = CastAegis,
				Describe = (int lvl) => $"Divine shield for {AegisDuration():0} s and a pulse that repels nearby enemies"
			},
			new SpellDef
			{
				Name = "Call the Fallen",
				UnlockLevel = 70,
				Cooldown = 20f,
				StaminaCost = 50f,
				IconItem = "TrophyWraith",
				CastAction = CastCallTheFallen,
				Describe = (int lvl) => $"Summon fallen warriors that fight for you (max {SpiritCap()})"
			},
			new SpellDef
			{
				Name = "Ragnarök",
				UnlockLevel = 80,
				Cooldown = 75f,
				StaminaCost = 80f,
				IconItem = "TrophyDragonQueen",
				CastTime = 2.5f,
				CastAction = CastRagnarok,
				Describe = (int lvl) => $"Ascend and crash down ({AdjRagnarokDamage(lvl)} damage, 12 m), then {RagnarokBolts()} bolts chain across your foes"
			}
		};

		public static readonly SpellDef[] ChosenSpells = new SpellDef[8]
		{
			new SpellDef
			{
				Name = "Spear of the Gods",
				UnlockLevel = 10,
				Cooldown = 8f,
				StaminaCost = 25f,
				IconItem = "SpearBronze",
				CastAction = CastSpearOfTheGods,
				Describe = (int lvl) => string.Format("Hurl a radiant spear ({0} pierce + {1} lightning)", AdjGodSpearPierce(lvl), Adj(GodSpearLightning(lvl), "lightning"))
			},
			new SpellDef
			{
				Name = "Sky Dive",
				UnlockLevel = 20,
				Cooldown = 12f,
				StaminaCost = 25f,
				IconItem = "Feathers",
				CastAction = CastSkyDive,
				Describe = (int lvl) => $"Leap from the sky and crash down ({AdjSkyDiveDamage(lvl)} damage, 5 m)"
			},
			new SpellDef
			{
				Name = "Valkyrie's Blessing",
				UnlockLevel = 30,
				Cooldown = 30f,
				StaminaCost = 30f,
				IconItem = "TrophyValkyrie",
				CastAction = CastBattleBlessing,
				Describe = (int lvl) => $"Bless yourself and allies within {8f + ValkyrieReachBonus(LP):0} m: +15% damage, swift stamina and cheap attacks for {BlessingDuration():0} s"
			},
			new SpellDef
			{
				Name = "Judgement",
				UnlockLevel = 40,
				Cooldown = 14f,
				StaminaCost = 35f,
				IconItem = "Thunderstone",
				CastTime = 1.5f,
				CastAction = CastJudgement,
				Describe = (int lvl) => string.Format("{0} of Thor strikes where you aim ({1} damage, {2:0} m)", (JudgementStrikes() > 1) ? "2 bolts" : "A bolt", AdjJudgementDamage(lvl), JudgementRadius())
			},
			new SpellDef
			{
				Name = "Spear Volley",
				UnlockLevel = 50,
				Cooldown = 12f,
				StaminaCost = 40f,
				IconItem = "SpearChitin",
				CastAction = CastSpearVolley,
				Describe = (int lvl) => $"Fan of {VolleyCount()} radiant spears ({AdjVolleyDamage(lvl)} damage each)"
			},
			new SpellDef
			{
				Name = "Aegis of the Host",
				UnlockLevel = 60,
				Cooldown = 60f,
				StaminaCost = 35f,
				IconItem = "ShieldSilver",
				CastAction = CastAegis,
				Describe = (int lvl) => $"Divine shield for {AegisDuration():0} s: allies within {8f + ValkyrieReachBonus(LP):0} m are protected AND empowered"
			},
			new SpellDef
			{
				Name = "Honor Guard",
				UnlockLevel = 70,
				Cooldown = 20f,
				StaminaCost = 50f,
				IconItem = "TrophyWraith",
				CastAction = CastCallTheFallen,
				Describe = (int lvl) => $"Summon honored spirits (max {SpiritCap()}) — their presence invigorates allies within {6f + ValkyrieReachBonus(LP):0} m"
			},
			new SpellDef
			{
				Name = "Ragnarök",
				UnlockLevel = 80,
				Cooldown = 75f,
				StaminaCost = 80f,
				IconItem = "TrophyDragonQueen",
				CastTime = 2.5f,
				CastAction = CastRagnarok,
				Describe = (int lvl) => $"Ascend and crash down ({AdjRagnarokDamage(lvl)} damage, 12 m), then {RagnarokBolts()} bolts chain across your foes"
			}
		};

		public static readonly SpellDef[] GuardianSpells = new SpellDef[8]
		{
			new SpellDef
			{
				Name = "Shield Bash",
				UnlockLevel = 10,
				Cooldown = 6f,
				StaminaCost = 15f,
				IconItem = "ShieldBanded",
				CastAction = CastShieldBash,
				Describe = (int lvl) => $"Slam your shield forward ({AdjBashDamage(lvl)} damage) and force the foes you hit to face YOU"
			},
			new SpellDef
			{
				Name = "Challenge",
				UnlockLevel = 20,
				Cooldown = 14f,
				StaminaCost = 20f,
				IconItem = "ShieldWood",
				CastAction = CastChallenge,
				Describe = (int lvl) => $"Every enemy within {ChallengeRadius():0} m turns on you; your defiance grants bonus armor for 8 s"
			},
			new SpellDef
			{
				Name = "Shield Wall",
				UnlockLevel = 30,
				Cooldown = 60f,
				StaminaCost = 40f,
				IconItem = "ShieldIronTower",
				CastAction = CastShieldWall,
				Describe = (int lvl) => $"Skjaldborg! A golden dome ({ShieldWallRadius():0} m, {ShieldWallDuration():0} s): armors allies inside, shatters projectiles, repels enemies"
			},
			new SpellDef
			{
				Name = "Guardian's Leap",
				UnlockLevel = 40,
				Cooldown = 12f,
				StaminaCost = 25f,
				IconItem = "ShieldBronzeBuckler",
				CastAction = CastGuardianLeap,
				Describe = (int lvl) => $"Leap to your fellows ({AdjLeapDamage(lvl)} damage on landing) and shield allies around you for {RampartDuration():0} s"
			},
			new SpellDef
			{
				Name = "Iron Bulwark",
				UnlockLevel = 50,
				Cooldown = 45f,
				StaminaCost = 30f,
				IconItem = "ArmorPaddedCuirass",
				CastAction = CastIronBulwark,
				Describe = (int lvl) => $"Become an unmovable wall for {BulwarkDuration():0} s"
			},
			new SpellDef
			{
				Name = "Ground Slam",
				UnlockLevel = 60,
				Cooldown = 18f,
				StaminaCost = 35f,
				IconItem = "SledgeIron",
				CastAction = CastGroundSlam,
				Describe = (int lvl) => $"Shake the earth ({AdjStompDamage(lvl)} damage, {StompRadius():0} m) and taunt every enemy you hit"
			},
			new SpellDef
			{
				Name = "Living Fortress",
				UnlockLevel = 70,
				Cooldown = 45f,
				StaminaCost = 35f,
				IconItem = "ShieldSerpentscale",
				CastAction = CastLivingFortress,
				Describe = (int lvl) => $"Immense armor for {FortressDuration():0} s while your presence keeps taunting nearby enemies"
			},
			new SpellDef
			{
				Name = "Gjallarhorn",
				UnlockLevel = 80,
				Cooldown = 75f,
				StaminaCost = 80f,
				IconItem = "TankardOdin",
				CastAction = CastGjallarhorn,
				Describe = (int lvl) => $"Sound Heimdall's horn: {AdjHornDamage(lvl)} damage and a mighty blast ({HornRadius():0} m), while allies gain your rampart"
			}
		};

		public static readonly SpellDef[] DruidSpells = new SpellDef[8]
		{
			new SpellDef
			{
				Name = "Regrowth",
				UnlockLevel = 10,
				Cooldown = 12f,
				StaminaCost = 25f,
				IconItem = "Dandelion",
				CastAction = CastRegrowth,
				Describe = (int lvl) => $"Life surges anew: you and allies within {BlessingRadius():0} m recover {AdjRegrowthHeal(lvl)} HP"
			},
			new SpellDef
			{
				Name = "Thorn Burst",
				UnlockLevel = 20,
				Cooldown = 6f,
				StaminaCost = 15f,
				IconItem = "Thistle",
				CastAction = CastThornBurst,
				Describe = (int lvl) => $"A burst of thorns erupts in front of you ({AdjThornDamage(lvl)} pierce damage)"
			},
			new SpellDef
			{
				Name = "Forest Blessing",
				UnlockLevel = 30,
				Cooldown = 25f,
				StaminaCost = 25f,
				IconItem = "AncientSeed",
				CastAction = CastForestBlessing,
				Describe = (int lvl) => string.Format("The wild empowers allies within {0:0} m: +{1}% attack and swift stamina for {2:0} s", BlessingRadius(), TalentSystem.Has(LP, "dru_inspiring") ? 25 : 15, ForestBlessingDuration())
			},
			new SpellDef
			{
				Name = "Healing Bloom",
				UnlockLevel = 40,
				Cooldown = 30f,
				StaminaCost = 40f,
				IconItem = "Raspberry",
				CastTime = 1.5f,
				CastAction = CastHealingBloom,
				Describe = (int lvl) => $"A meadow of healing flowers blooms ({BloomRadius():0} m, {BloomDuration():0} s): allies standing inside recover {AdjBloomHeal(lvl)} HP per second"
			},
			new SpellDef
			{
				Name = "Wind's Grace",
				UnlockLevel = 50,
				Cooldown = 30f,
				StaminaCost = 30f,
				IconItem = "Feathers",
				CastAction = CastWindsGrace,
				Describe = (int lvl) => $"The wind carries allies within {BlessingRadius():0} m: far lighter running for {WindsGraceDuration():0} s"
			},
			new SpellDef
			{
				Name = "Grasping Roots",
				UnlockLevel = 60,
				Cooldown = 15f,
				StaminaCost = 35f,
				IconItem = "Root",
				CastAction = CastGraspingRoots,
				Describe = (int lvl) => $"Roots erupt from the earth ({AdjRootsDamage(lvl)} pierce + poison damage, {RootsRadius():0} m) and hurl enemies away"
			},
			new SpellDef
			{
				Name = "Forest's Embrace",
				UnlockLevel = 70,
				Cooldown = 30f,
				StaminaCost = 50f,
				IconItem = "Honey",
				CastAction = CastForestEmbrace,
				Describe = (int lvl) => $"The forest embraces allies within {BlessingRadius():0} m: {AdjEmbraceHeal(lvl)} HP recovered and fast regeneration for {EmbraceDuration():0} s"
			},
			new SpellDef
			{
				Name = "Wrath of Yggdrasil",
				UnlockLevel = 80,
				Cooldown = 75f,
				StaminaCost = 80f,
				IconItem = "YggdrasilWood",
				CastTime = 2.5f,
				CastAction = CastWrathOfYggdrasil,
				Describe = (int lvl) => $"The World Tree answers: allies recover {AdjYggdrasilHeal(lvl)} HP and gain its blessing, enemies take {AdjYggdrasilDamage(lvl)} pierce + poison damage from the erupting roots"
			}
		};

		public static readonly SpellDef[] VanguardSpells = new SpellDef[8]
		{
			new SpellDef
			{
				Name = "Skull Crusher",
				UnlockLevel = 10,
				Cooldown = 6f,
				StaminaCost = 15f,
				IconItem = "MaceBronze",
				CastAction = CastShieldBash,
				Describe = (int lvl) => $"A merciless shield slam ({AdjBashDamage(lvl)} damage, huge knockback)"
			},
			new SpellDef
			{
				Name = "Shattering Shout",
				UnlockLevel = 20,
				Cooldown = 8f,
				StaminaCost = 20f,
				IconItem = "Club",
				CastAction = CastShatteringShout,
				Describe = (int lvl) => $"A shout that shatters bone ({AdjShoutDamage(lvl)} damage in a 6 m wave of force)"
			},
			new SpellDef
			{
				Name = "Assault Leap",
				UnlockLevel = 30,
				Cooldown = 12f,
				StaminaCost = 25f,
				IconItem = "ShieldBronzeBuckler",
				CastAction = CastGuardianLeap,
				Describe = (int lvl) => string.Format("Leap into the fray ({0} damage on landing){1}", AdjLeapDamage(lvl), TalentSystem.Has(LP, "vg_leapfrenzy") ? " and fuel your frenzy (+15% attack)" : "")
			},
			new SpellDef
			{
				Name = "Rupture",
				UnlockLevel = 40,
				Cooldown = 18f,
				StaminaCost = 35f,
				IconItem = "SledgeIron",
				CastAction = CastGroundSlam,
				Describe = (int lvl) => string.Format("Tear the earth open ({0} damage, {1:0} m){2}", AdjStompDamage(lvl), StompRadius(), TalentSystem.Has(LP, "vg_aftershock") ? " — strikes twice" : "")
			},
			new SpellDef
			{
				Name = "Battle Plates",
				UnlockLevel = 50,
				Cooldown = 45f,
				StaminaCost = 30f,
				IconItem = "ArmorPaddedCuirass",
				CastAction = CastIronBulwark,
				Describe = (int lvl) => string.Format("War plates for {0:0} s{1}", BulwarkDuration(), TalentSystem.Has(LP, "vg_berserkplate") ? ", fueling your attacks (+10%)" : "")
			},
			new SpellDef
			{
				Name = "Shield Storm",
				UnlockLevel = 60,
				Cooldown = 20f,
				StaminaCost = 40f,
				IconItem = "ShieldIronSquare",
				CastAction = CastShieldStorm,
				Describe = (int lvl) => $"Spin with your shield out for 2 s ({AdjStormTickDamage(lvl)} damage per hit, 4 m)"
			},
			new SpellDef
			{
				Name = "Battle Frenzy",
				UnlockLevel = 70,
				Cooldown = 45f,
				StaminaCost = 35f,
				IconItem = "TrophyFenring",
				CastAction = CastLivingFortress,
				Describe = (int lvl) => string.Format("Immense armor and battle frenzy (+{0}% attack) for {1:0} s", TalentSystem.Has(LP, "vg_frenzyfort") ? 25 : 15, FortressDuration())
			},
			new SpellDef
			{
				Name = "Horn of War",
				UnlockLevel = 80,
				Cooldown = 75f,
				StaminaCost = 80f,
				IconItem = "TankardOdin",
				CastAction = CastGjallarhorn,
				Describe = (int lvl) => $"A devastating war blast ({AdjHornDamage(lvl)} damage, {HornRadius():0} m)"
			}
		};

		private static readonly SpellDef GuardShieldBash = new SpellDef
		{
			Name = "Shield Bash",
			UnlockLevel = 1,
			Cooldown = 6f,
			StaminaCost = 15f,
			IconItem = "ShieldBanded",
			CastAction = CastShieldBash,
			Describe = (int lvl) => $"Slam your shield forward ({AdjBashDamage(lvl)} damage) and force the foes you hit to face YOU"
		};

		private static readonly SpellDef VanSkullCrusher = new SpellDef
		{
			Name = "Skull Crusher",
			UnlockLevel = 1,
			Cooldown = 6f,
			StaminaCost = 15f,
			IconItem = "MaceBronze",
			CastAction = CastShieldBash,
			Describe = (int lvl) => $"A merciless shield slam ({AdjBashDamage(lvl)} damage, huge knockback)"
		};

		private static readonly SpellDef PalBlessingBase = new SpellDef
		{
			Name = "Blessing of Light",
			UnlockLevel = 1,
			Cooldown = 30f,
			StaminaCost = 25f,
			IconItem = "TrophyValkyrie",
			CastAction = CastBlessingOfLight,
			Describe = (int lvl) => $"Bless allies within {HolyRadius():0} m: +{BlessLightAttack()}% attack and +{BlessLightArmor()} armor for {HolyBuffDuration():0} s" + ((TalentSystem.Has(LP, "tmp_capstone") || TalentSystem.Has(LP, "pal_notable")) ? ", mending the wounded" : "")
		};

		private static readonly SpellDef[] GuardianBulwarkBaseOnly = new SpellDef[1] { GuardShieldBash };

		private static readonly SpellDef[] GuardianVanguardBaseOnly = new SpellDef[1] { VanSkullCrusher };

		private static readonly SpellDef[] GuardianPaladinBaseOnly = new SpellDef[1] { PalBlessingBase };

		public static readonly SpellDef[] TemplarSpells = new SpellDef[5]
		{
			PalBlessingBase,
			new SpellDef
			{
				Name = "Consecration",
				UnlockLevel = 10,
				Cooldown = 20f,
				StaminaCost = 40f,
				IconItem = "Honey",
				CastTime = 1f,
				CastAction = CastConsecration,
				Describe = (int lvl) => $"Hallow the ground ({HolyGroundRadius():0} m, {HolyGroundDuration():0} s): allies inside recover {AdjConsecrationHeal(lvl)} HP/s"
			},
			new SpellDef
			{
				Name = "Lay on Hands",
				UnlockLevel = 20,
				Cooldown = 20f,
				StaminaCost = 40f,
				IconItem = "MeadHealthMedium",
				CastAction = CastLayOnHands,
				Describe = (int lvl) => $"A surge of light: you and allies within {HolyRadius():0} m recover {AdjLayOnHandsHeal(lvl)} HP"
			},
			new SpellDef
			{
				Name = "Divine Shield",
				UnlockLevel = 35,
				Cooldown = 45f,
				StaminaCost = 35f,
				IconItem = "ShieldSilver",
				CastAction = CastDivineShield,
				Describe = (int lvl) => $"A radiant ward covers allies within {HolyRadius():0} m: +{DivineShieldArmor()} armor for {DivineShieldDuration():0} s"
			},
			new SpellDef
			{
				Name = "Beacon of Light",
				UnlockLevel = 45,
				Cooldown = 60f,
				StaminaCost = 70f,
				IconItem = "TrophyValkyrie",
				CastTime = 1f,
				CastAction = CastBeaconOfLight,
				Describe = (int lvl) => $"A beacon blazes ({HolyRadius():0} m): {AdjBeaconHeal(lvl)} HP now and fast regeneration for {BeaconDuration():0} s"
			}
		};

		public static readonly SpellDef[] LightbringerSpells = new SpellDef[5]
		{
			PalBlessingBase,
			new SpellDef
			{
				Name = "Smite",
				UnlockLevel = 10,
				Cooldown = 5f,
				StaminaCost = 20f,
				IconItem = "StaffLightning",
				CastAction = CastSmite,
				Describe = (int lvl) => $"Call down holy light ({AdjSmiteDamage(lvl)} spirit)" + (TalentSystem.Has(LP, "lbr_notable") ? ", piercing through foes" : "")
			},
			new SpellDef
			{
				Name = "Holy Nova",
				UnlockLevel = 20,
				Cooldown = 12f,
				StaminaCost = 35f,
				IconItem = "TrophyValkyrie",
				CastAction = CastHolyNova,
				Describe = (int lvl) => $"A burst of light around you ({AdjHolyNovaDamage(lvl)} spirit, {HolyNovaRadius():0} m)"
			},
			new SpellDef
			{
				Name = "Consecration",
				UnlockLevel = 35,
				Cooldown = 20f,
				StaminaCost = 40f,
				IconItem = "StaffLightning",
				CastTime = 1f,
				CastAction = CastConsecration,
				Describe = (int lvl) => $"Searing hallowed ground ({HolyGroundRadius():0} m, {HolyGroundDuration():0} s): enemies inside take {AdjConsecrationDamage(lvl)} spirit/s"
			},
			new SpellDef
			{
				Name = "Wrath of Light",
				UnlockLevel = 45,
				Cooldown = 60f,
				StaminaCost = 80f,
				IconItem = "TrophyDragonQueen",
				CastTime = 1.5f,
				CastAction = CastWrathOfLight,
				Describe = (int lvl) => $"The heavens answer ({AdjWrathDamage(lvl)} spirit, {WrathRadius():0} m)" + (TalentSystem.Has(LP, "lbr_wrathheal") ? " and heals you per foe struck" : "")
			}
		};

		public static readonly SpellDef[] WardenGuardSpells = new SpellDef[5]
		{
			GuardShieldBash,
			new SpellDef
			{
				Name = "Challenge",
				UnlockLevel = 10,
				Cooldown = 14f,
				StaminaCost = 20f,
				IconItem = "ShieldWood",
				CastAction = CastChallenge,
				Describe = (int lvl) => $"Every enemy within {ChallengeRadius():0} m turns on you; your defiance grants bonus armor for 8 s"
			},
			new SpellDef
			{
				Name = "Shield Wall",
				UnlockLevel = 20,
				Cooldown = 60f,
				StaminaCost = 40f,
				IconItem = "ShieldIronTower",
				CastAction = CastShieldWall,
				Describe = (int lvl) => $"Skjaldborg! A golden dome ({ShieldWallRadius():0} m, {ShieldWallDuration():0} s): armors allies inside, shatters projectiles, repels enemies"
			},
			new SpellDef
			{
				Name = "Living Fortress",
				UnlockLevel = 35,
				Cooldown = 45f,
				StaminaCost = 35f,
				IconItem = "ShieldSerpentscale",
				CastAction = CastLivingFortress,
				Describe = (int lvl) => $"Immense armor for {FortressDuration():0} s while your presence keeps taunting nearby enemies"
			},
			new SpellDef
			{
				Name = "Gjallarhorn",
				UnlockLevel = 45,
				Cooldown = 75f,
				StaminaCost = 80f,
				IconItem = "TankardOdin",
				CastAction = CastGjallarhorn,
				Describe = (int lvl) => $"Sound Heimdall's horn: {AdjHornDamage(lvl)} damage and a mighty blast ({HornRadius():0} m), while allies gain your rampart"
			}
		};

		public static readonly SpellDef[] SentinelSpells = new SpellDef[5]
		{
			GuardShieldBash,
			new SpellDef
			{
				Name = "Iron Bulwark",
				UnlockLevel = 10,
				Cooldown = 45f,
				StaminaCost = 30f,
				IconItem = "ArmorPaddedCuirass",
				CastAction = CastIronBulwark,
				Describe = (int lvl) => $"Become an unmovable wall for {BulwarkDuration():0} s"
			},
			new SpellDef
			{
				Name = "Challenge",
				UnlockLevel = 20,
				Cooldown = 14f,
				StaminaCost = 20f,
				IconItem = "ShieldWood",
				CastAction = CastChallenge,
				Describe = (int lvl) => $"Every enemy within {ChallengeRadius():0} m turns on you; your defiance grants bonus armor for 8 s"
			},
			new SpellDef
			{
				Name = "Thornplate",
				UnlockLevel = 35,
				Cooldown = 45f,
				StaminaCost = 30f,
				IconItem = "ShieldSerpentscale",
				CastAction = CastThornplate,
				Describe = (int lvl) => $"Spiked bulwark for {ThornplateDuration():0} s: attackers take {ThornplateReflect(lvl)} damage back"
			},
			new SpellDef
			{
				Name = "Gjallarhorn",
				UnlockLevel = 45,
				Cooldown = 75f,
				StaminaCost = 80f,
				IconItem = "TankardOdin",
				CastAction = CastGjallarhorn,
				Describe = (int lvl) => $"Sound Heimdall's horn: {AdjHornDamage(lvl)} damage and a mighty blast ({HornRadius():0} m), while allies gain your rampart"
			}
		};

		public static readonly SpellDef[] CrusherSpells = new SpellDef[5]
		{
			VanSkullCrusher,
			new SpellDef
			{
				Name = "Ground Slam",
				UnlockLevel = 10,
				Cooldown = 18f,
				StaminaCost = 35f,
				IconItem = "SledgeIron",
				CastAction = CastGroundSlam,
				Describe = (int lvl) => $"Shake the earth ({AdjStompDamage(lvl)} damage, {StompRadius():0} m)"
			},
			new SpellDef
			{
				Name = "Assault Leap",
				UnlockLevel = 20,
				Cooldown = 12f,
				StaminaCost = 25f,
				IconItem = "ShieldBronzeBuckler",
				CastAction = CastGuardianLeap,
				Describe = (int lvl) => $"Leap into the fray ({AdjLeapDamage(lvl)} damage on landing)"
			},
			new SpellDef
			{
				Name = "Shield Storm",
				UnlockLevel = 35,
				Cooldown = 20f,
				StaminaCost = 40f,
				IconItem = "ShieldIronSquare",
				CastAction = CastShieldStorm,
				Describe = (int lvl) => $"Spin with your shield out for 2 s ({AdjStormTickDamage(lvl)} damage per hit, 4 m)"
			},
			new SpellDef
			{
				Name = "Earthbreaker",
				UnlockLevel = 45,
				Cooldown = 45f,
				StaminaCost = 60f,
				IconItem = "SledgeDemolisher",
				CastTime = 1f,
				CastAction = CastEarthbreaker,
				Describe = (int lvl) => $"Shatter the ground ({AdjEarthbreakerDamage(lvl)} damage, {EarthbreakerRadius():0} m) with a devastating quake"
			}
		};

		public static readonly SpellDef[] WarbringerSpells = new SpellDef[5]
		{
			VanSkullCrusher,
			new SpellDef
			{
				Name = "Assault Leap",
				UnlockLevel = 10,
				Cooldown = 12f,
				StaminaCost = 25f,
				IconItem = "ShieldBronzeBuckler",
				CastAction = CastGuardianLeap,
				Describe = (int lvl) => $"Leap into the fray ({AdjLeapDamage(lvl)} damage on landing)"
			},
			new SpellDef
			{
				Name = "Battle Frenzy",
				UnlockLevel = 20,
				Cooldown = 45f,
				StaminaCost = 35f,
				IconItem = "TrophyFenring",
				CastAction = CastLivingFortress,
				Describe = (int lvl) => $"Immense armor and battle frenzy (+{FrenzyAttack()}% attack) for {FortressDuration():0} s"
			},
			new SpellDef
			{
				Name = "Shattering Shout",
				UnlockLevel = 35,
				Cooldown = 8f,
				StaminaCost = 20f,
				IconItem = "Club",
				CastAction = CastShatteringShout,
				Describe = (int lvl) => $"A shout that shatters bone ({AdjShoutDamage(lvl)} damage in a {ShoutRadius():0} m wave of force)"
			},
			new SpellDef
			{
				Name = "Horn of War",
				UnlockLevel = 45,
				Cooldown = 75f,
				StaminaCost = 80f,
				IconItem = "TankardOdin",
				CastAction = CastGjallarhorn,
				Describe = (int lvl) => $"A devastating war blast ({AdjHornDamage(lvl)} damage, {HornRadius():0} m)"
			}
		};

		public static readonly SpellDef[] ThornweaverSpells = new SpellDef[8]
		{
			new SpellDef
			{
				Name = "Thorn Burst",
				UnlockLevel = 10,
				Cooldown = 6f,
				StaminaCost = 15f,
				IconItem = "Thistle",
				CastAction = CastThornBurst,
				Describe = (int lvl) => $"A burst of thorns erupts in front of you ({AdjThornDamage(lvl)} pierce damage)"
			},
			new SpellDef
			{
				Name = "Thorn Sap",
				UnlockLevel = 20,
				Cooldown = 12f,
				StaminaCost = 25f,
				IconItem = "Dandelion",
				CastAction = CastRegrowth,
				Describe = (int lvl) => $"Life flows from the thorns: allies recover {AdjRegrowthHeal(lvl)} HP while enemies within 5 m are lashed ({AdjThornSapDamage(lvl)} pierce)"
			},
			new SpellDef
			{
				Name = "Forest Blessing",
				UnlockLevel = 30,
				Cooldown = 25f,
				StaminaCost = 25f,
				IconItem = "AncientSeed",
				CastAction = CastForestBlessing,
				Describe = (int lvl) => string.Format("The wild empowers allies within {0:0} m: +{1}% attack and swift stamina for {2:0} s", BlessingRadius(), TalentSystem.Has(LP, "dru_inspiring") ? 25 : 15, ForestBlessingDuration())
			},
			new SpellDef
			{
				Name = "Poison Bloom",
				UnlockLevel = 40,
				Cooldown = 30f,
				StaminaCost = 40f,
				IconItem = "Ooze",
				CastTime = 1.5f,
				CastAction = CastHealingBloom,
				Describe = (int lvl) => $"A venomous circle blooms ({BloomRadius():0} m, {BloomDuration():0} s): enemies inside are poisoned for {AdjBloomPoison(lvl)} per second"
			},
			new SpellDef
			{
				Name = "Wind's Grace",
				UnlockLevel = 50,
				Cooldown = 30f,
				StaminaCost = 30f,
				IconItem = "Feathers",
				CastAction = CastWindsGrace,
				Describe = (int lvl) => $"The wind carries allies within {BlessingRadius():0} m: far lighter running for {WindsGraceDuration():0} s"
			},
			new SpellDef
			{
				Name = "Grasping Roots",
				UnlockLevel = 60,
				Cooldown = 15f,
				StaminaCost = 35f,
				IconItem = "Root",
				CastAction = CastGraspingRoots,
				Describe = (int lvl) => $"Roots erupt from the earth ({AdjRootsDamage(lvl)} pierce + poison damage, {RootsRadius():0} m) and hurl enemies away"
			},
			new SpellDef
			{
				Name = "Nature's Fury",
				UnlockLevel = 70,
				Cooldown = 30f,
				StaminaCost = 50f,
				IconItem = "TrophyAbomination",
				CastAction = CastForestEmbrace,
				Describe = (int lvl) => $"Allies within {NatureFuryRadius():0} m deal +15% pierce and poison damage for {NatureFuryDuration():0} s"
			},
			new SpellDef
			{
				Name = "Wrath of Yggdrasil",
				UnlockLevel = 80,
				Cooldown = 75f,
				StaminaCost = 80f,
				IconItem = "YggdrasilWood",
				CastTime = 2.5f,
				CastAction = CastWrathOfYggdrasil,
				Describe = (int lvl) => $"The World Tree strikes: enemies take {AdjYggdrasilDamage(lvl)} pierce + poison damage from the erupting roots, allies recover {AdjYggdrasilHeal(lvl)} HP"
			}
		};

		private const int BlizzardWaves = 8;

		private const float AbsoluteZeroRadius = 10f;

		private const float GraspDuration = 8f;

		private const int ThorBolts = 12;

		private const float EyeDuration = 10f;

		public const int DomeStyleMage = 0;

		public const int DomeStyleGuardian = 1;

		private static readonly List<Character> FireMinions = new List<Character>();

		private static readonly List<Character> MagmaMinions = new List<Character>();

		private static readonly List<Character> FireArmy = new List<Character>();

		private const string FireImpPrefab = "Surtling";

		private static readonly string[] MagmaPrefabNames = new string[3] { "BlobLava", "Charred_Melee", "Surtling" };

		private static readonly List<Character> SpiritMinions = new List<Character>();

		private static readonly List<Character> Minions = new List<Character>();

		private static readonly List<Character> ArmyMinions = new List<Character>();

		private static readonly Dictionary<string, AscendantPath> AscendantPaths = BuildAscendantPaths();

		private static readonly Dictionary<string, SpellDef[]> ExpandedRosterCache = new Dictionary<string, SpellDef[]>();

		private static readonly Dictionary<PlayerClass, SpellDef> AscensionUltimates = new Dictionary<PlayerClass, SpellDef>();

		private static readonly SpellDef RangerMarkedShot = RangerSpell("Marked Shot", 1, 8f, 12f, "ArrowBronze", 0f, (int lvl) => $"A precise shot ({RangerDamage(13, lvl)} pierce)", CastMarkedShot);

		private static readonly SpellDef RangerEvasiveShot = RangerSpell("Evasive Shot", 1, 8f, 14f, "BowFineWood", 0f, (int lvl) => $"Loose an arrow ({RangerDamage(11, lvl)} pierce) and leap away", CastEvasiveShot);

		private static readonly SpellDef RangerSnareTrap = RangerSpell("Snare Trap", 1, 14f, 15f, "BronzeNails", 0f, (int lvl) => $"Set a hidden snare ({RangerDamage(10, lvl)} pierce, arms after 1 s)", CastSnareTrap);

		private static readonly SpellDef[] RangerMarksmanshipBaseOnly = new SpellDef[1] { RangerMarkedShot };

		private static readonly SpellDef[] RangerSkirmishingBaseOnly = new SpellDef[1] { RangerEvasiveShot };

		private static readonly SpellDef[] RangerWildernessBaseOnly = new SpellDef[1] { RangerSnareTrap };

		private static readonly SpellDef[] DeadeyeSpells = new SpellDef[5]
		{
			RangerMarkedShot,
			RangerSpell("Aimed Shot", 10, 13f, 20f, "BowHuntsman", 1f, (int lvl) => $"A carefully aimed arrow ({RangerDamage(25, lvl)} pierce)", CastAimedShot),
			RangerSpell("Hunter's Mark", 20, 22f, 24f, "TrophySerpent", 0f, (int lvl) => $"Mark and strike the nearest prey ({RangerDamage(30, lvl)} pierce)", CastHuntersMark),
			RangerSpell("Heartseeker", 40, 30f, 32f, "ArrowSilver", 1.2f, (int lvl) => $"A lethal shot that punishes wounded prey ({RangerDamage(45, lvl)} pierce)", CastHeartseeker),
			RangerSpell("One Shot", 60, 55f, 48f, "BowSpineSnap", 1.8f, (int lvl) => $"The hunt ends in one impossible arrow ({RangerDamage(72, lvl)} pierce)", CastOneShot)
		};

		private static readonly SpellDef[] ArbalistSpells = new SpellDef[5]
		{
			RangerMarkedShot,
			RangerSpell("Armor Breaker", 10, 14f, 22f, "CrossbowArbalest", 0.8f, (int lvl) => $"A crushing bolt ({RangerDamage(28, lvl)} pierce, heavy knockback)", CastArmorBreaker),
			RangerSpell("Pavise", 20, 28f, 25f, "ShieldIronTower", 0f, (int lvl) => "Brace behind a field shield: greatly increased armor for 12 s", CastPavise),
			RangerSpell("Siege Bolt", 40, 34f, 36f, "BoltCarapace", 1.3f, (int lvl) => $"A siege projectile detonates through a line ({RangerDamage(48, lvl)} pierce)", CastSiegeBolt),
			RangerSpell("Ballista Salvo", 60, 58f, 50f, "CrossbowRipper", 1.5f, (int lvl) => $"Fire seven heavy bolts in a disciplined salvo ({RangerDamage(22, lvl)} each)", CastBallistaSalvo)
		};

		private static readonly SpellDef[] PathfinderSpells = new SpellDef[5]
		{
			RangerEvasiveShot,
			RangerSpell("Quickstep", 10, 10f, 16f, "Feathers", 0f, (int lvl) => "Surge forward along a safe path", CastQuickstep),
			RangerSpell("Rapid Fire", 20, 22f, 26f, "BowFineWood", 0f, (int lvl) => $"Loose five arrows while moving ({RangerDamage(13, lvl)} each)", CastRapidFire),
			RangerSpell("Windrunner", 40, 35f, 30f, "MeadStaminaMedium", 0f, (int lvl) => "Move almost without stamina cost and recover breath for 12 s", CastWindrunner),
			RangerSpell("Ghost Trail", 60, 52f, 44f, "TrophyHare", 0f, (int lvl) => $"Become a streak of wind and fire seven arrows ({RangerDamage(18, lvl)} each)", CastGhostTrail)
		};

		private static readonly SpellDef[] VolleyMasterSpells = new SpellDef[5]
		{
			RangerEvasiveShot,
			RangerSpell("Split Shot", 10, 12f, 20f, "ArrowBronze", 0f, (int lvl) => $"Loose five arrows in a wide fan ({RangerDamage(10, lvl)} each)", CastSplitShot),
			RangerSpell("Arrow Rain", 20, 25f, 28f, "BowDraugrFang", 0f, (int lvl) => $"Twelve arrows rain over the target ground ({RangerDamage(12, lvl)} each)", CastArrowRain),
			RangerSpell("Suppressing Volley", 40, 36f, 38f, "ArrowCarapace", 0f, (int lvl) => $"Three ordered waves pin down a wide area ({RangerDamage(18, lvl)} per wave)", CastSuppressingVolley),
			RangerSpell("Skyfall Barrage", 60, 60f, 52f, "TrophyGjall", 1.2f, (int lvl) => $"Twenty-four arrows darken the sky ({RangerDamage(19, lvl)} each)", CastSkyfallBarrage)
		};

		private static readonly SpellDef[] TrapperSpells = new SpellDef[5]
		{
			RangerSnareTrap,
			RangerSpell("Caltrops", 10, 18f, 20f, "BronzeNails", 0f, (int lvl) => $"Scatter caltrops that strike in three pulses ({RangerDamage(9, lvl)} pierce)", CastCaltrops),
			RangerSpell("Explosive Trap", 20, 25f, 28f, "BombOoze", 0f, (int lvl) => $"Set an explosive ambush ({RangerDamage(30, lvl)} fire and blunt)", CastExplosiveTrap),
			RangerSpell("Venom Mine", 40, 34f, 36f, "Guck", 0f, (int lvl) => $"Set a poisonous mine ({RangerDamage(38, lvl)} poison and pierce)", CastVenomMine),
			RangerSpell("Grand Hunt", 60, 58f, 50f, "TrophyGoblinShaman", 0f, (int lvl) => $"Seed the hunting ground with five linked traps ({RangerDamage(26, lvl)} each)", CastGrandHunt)
		};

		private static readonly SpellDef[] FalconerSpells = new SpellDef[5]
		{
			RangerSnareTrap,
			RangerSpell("Falcon Strike", 10, 13f, 18f, "Feathers", 0f, (int lvl) => $"Your raptor dives onto the chosen prey ({RangerDamage(22, lvl)} pierce)", CastFalconStrike),
			RangerSpell("Scout's Mark", 20, 24f, 26f, "TrophyHatchling", 0f, (int lvl) => $"The raptor marks a target for three coordinated strikes ({RangerDamage(14, lvl)} each)", CastScoutsMark),
			RangerSpell("Wingstorm", 40, 36f, 38f, "TrophyDeathsquito", 0f, (int lvl) => $"A spiral of feathers tears nearby enemies ({RangerDamage(20, lvl)} per wave)", CastWingstorm),
			RangerSpell("Apex Companion", 60, 65f, 50f, "TrophySeeker", 1f, (int lvl) => "Call a temporary great raptor to hunt beside you for 35 s", CastApexCompanion)
		};

		private static bool AltSpec => GuardianOffense(LP);

		private static Player LP => Player.m_localPlayer;

		public static bool IsChanneling { get; private set; }

		public static float ChannelProgress { get; private set; }

		public static string ChannelSpellName { get; private set; }

		public static float ArmyLifetime => 60f + 15f * (float)(TalentSystem.Rank(LP, "bl_armylong") + TalentSystem.Rank(LP, "bm_calllong") + TalentSystem.Rank(LP, "her_legionlong"));

		public static SpellDef[] GetSpells(Player player)
		{
			if (TrainingHall.TryGetRoster(player, out var roster))
			{
				return roster;
			}
			PlayerClass playerClass = ClassSystem.GetClass(player);
			if (BranchSystem.Has(playerClass))
			{
				return SingleTreeRoster(player);
			}
			if (SpecSystem.HasSpecs(playerClass) && SpecSystem.GetSpec(player) == ClassSpec.Alternative)
			{
				switch (playerClass)
				{
				case PlayerClass.Guardian:
					return VanguardSpells;
				case PlayerClass.Druid:
					return ThornweaverSpells;
				case PlayerClass.Einherjar:
					return ChosenSpells;
				}
			}
			return GetSpells(playerClass);
		}

		private static SpellDef[] SingleTreeRoster(Player player)
		{
			int branch = BranchSystem.GetBranch(player);
			if (branch < 0)
			{
				return new SpellDef[0];
			}
			int subSpec = BranchSystem.GetSubSpec(player);
			PlayerClass playerClass = ClassSystem.GetClass(player);
			SpellDef[] array = playerClass switch
			{
				PlayerClass.Berserker => BerserkerRoster(branch, subSpec), 
				PlayerClass.Necromancer => NecromancerRoster(branch, subSpec), 
				PlayerClass.Druid => DruidRoster(branch, subSpec), 
				PlayerClass.Einherjar => EinherjarSingleRoster(branch, subSpec), 
				PlayerClass.Guardian => GuardianSingleRoster(branch, subSpec), 
				PlayerClass.Ranger => RangerRoster(branch, subSpec), 
				_ => MageRoster(branch, subSpec), 
			};
			if (subSpec < 0)
			{
				return array;
			}
			return ExpandSingleTreeRoster(player, playerClass, branch, subSpec, array);
		}

		private static bool GuardianOffense(Player player)
		{
			if (!SpecSystem.IsAlternative(player))
			{
				if (ClassSystem.GetClass(player) == PlayerClass.Guardian)
				{
					return BranchSystem.GetBranch(player) == 1;
				}
				return false;
			}
			return true;
		}

		private static SpellDef[] GuardianSingleRoster(int branch, int sub)
		{
			return branch switch
			{
				0 => sub switch
				{
					0 => WardenGuardSpells, 
					1 => SentinelSpells, 
					_ => GuardianBulwarkBaseOnly, 
				}, 
				1 => sub switch
				{
					0 => CrusherSpells, 
					1 => WarbringerSpells, 
					_ => GuardianVanguardBaseOnly, 
				}, 
				_ => sub switch
				{
					0 => TemplarSpells, 
					1 => LightbringerSpells, 
					_ => GuardianPaladinBaseOnly, 
				}, 
			};
		}

		private static SpellDef[] EinherjarSingleRoster(int branch, int sub)
		{
			return branch switch
			{
				0 => sub switch
				{
					0 => ThundererSpells, 
					1 => StormheraldSpells, 
					_ => EinherStormBaseOnly, 
				}, 
				1 => sub switch
				{
					0 => SpearmasterSpells, 
					1 => ValkyrieKnightSpells, 
					_ => EinherSpearBaseOnly, 
				}, 
				_ => sub switch
				{
					0 => ValkyrieSpells, 
					1 => HeraldSpells, 
					_ => EinherValhallaBaseOnly, 
				}, 
			};
		}

		private static SpellDef[] DruidRoster(int branch, int sub)
		{
			return branch switch
			{
				0 => sub switch
				{
					0 => WerewolfSpells, 
					1 => WerebearSpells, 
					_ => DruidWildBaseOnly, 
				}, 
				1 => sub switch
				{
					0 => SkaldSpells, 
					1 => BeastmasterSpells, 
					_ => DruidWardenBaseOnly, 
				}, 
				_ => sub switch
				{
					0 => LifekeeperSpells, 
					1 => GrovekeeperSpells, 
					_ => DruidRestoBaseOnly, 
				}, 
			};
		}

		private static SpellDef[] NecromancerRoster(int branch, int sub)
		{
			return branch switch
			{
				0 => sub switch
				{
					0 => PestilentSpells, 
					1 => BlightcallerSpells, 
					_ => NecroPlagueBaseOnly, 
				}, 
				1 => sub switch
				{
					0 => ReaperSpells, 
					1 => BansheeSpells, 
					_ => NecroSpiritBaseOnly, 
				}, 
				_ => sub switch
				{
					0 => BonelordSpells, 
					1 => DeathknightSpells, 
					_ => NecroBoneBaseOnly, 
				}, 
			};
		}

		private static SpellDef[] MageRoster(int branch, int sub)
		{
			return branch switch
			{
				0 => sub switch
				{
					0 => PyromancerSpells, 
					1 => FlameSummonerSpells, 
					_ => MageFireBaseOnly, 
				}, 
				1 => sub switch
				{
					0 => CryomancerSpells, 
					1 => FrostwardenSpells, 
					_ => MageFrostBaseOnly, 
				}, 
				_ => sub switch
				{
					0 => StormcallerSpells, 
					1 => TempestSpells, 
					_ => MageLightningBaseOnly, 
				}, 
			};
		}

		private static SpellDef[] BerserkerRoster(int branch, int sub)
		{
			return branch switch
			{
				0 => sub switch
				{
					0 => JuggernautSpells, 
					1 => EarthshakerSpells, 
					_ => BersCrushingBaseOnly, 
				}, 
				1 => sub switch
				{
					0 => ReaverSpells, 
					1 => RavagerSpells, 
					_ => BersRendingBaseOnly, 
				}, 
				_ => sub switch
				{
					0 => LancerSpells, 
					1 => WarhoundSpells, 
					_ => BersHuntingBaseOnly, 
				}, 
			};
		}

		public static SpellDef[] GetSpells(PlayerClass cls)
		{
			return cls switch
			{
				PlayerClass.Mage => PyromancerSpells, 
				PlayerClass.Berserker => JuggernautSpells, 
				PlayerClass.Necromancer => PestilentSpells, 
				PlayerClass.Einherjar => ThundererSpells, 
				PlayerClass.Guardian => WardenGuardSpells, 
				PlayerClass.Druid => WerewolfSpells, 
				PlayerClass.Ranger => DeadeyeSpells, 
				_ => new SpellDef[0], 
			};
		}

		public static SpellDef[] GetPreviewSpells(PlayerClass cls)
		{
			return GetPreviewSpells(cls, 0, 0);
		}

		public static SpellDef[] GetPreviewSpells(PlayerClass cls, int branch, int sub)
		{
			return ExpandSingleTreeRoster(null, cls, branch, sub, cls switch
			{
				PlayerClass.Berserker => BerserkerRoster(branch, sub), 
				PlayerClass.Necromancer => NecromancerRoster(branch, sub), 
				PlayerClass.Druid => DruidRoster(branch, sub), 
				PlayerClass.Einherjar => EinherjarSingleRoster(branch, sub), 
				PlayerClass.Guardian => GuardianSingleRoster(branch, sub), 
				PlayerClass.Ranger => RangerRoster(branch, sub), 
				_ => MageRoster(branch, sub), 
			});
		}

		private static int FireballDamage(int lvl)
		{
			return Progression.DmgInt(18, lvl);
		}

		private static int FrostNovaDamage(int lvl)
		{
			return Progression.DmgInt(14, lvl);
		}

		private static int IceShardDamage(int lvl)
		{
			return Progression.DmgInt(9, lvl);
		}

		private static int LightningBoltDamage(int lvl)
		{
			return Progression.DmgInt(24, lvl);
		}

		private static int RingFireDamage(int lvl)
		{
			return Progression.DmgInt(12, lvl);
		}

		private static int StormBoltDamage(int lvl)
		{
			return Progression.DmgInt(18, lvl);
		}

		private static int MeteorDamage(int lvl)
		{
			return Progression.DmgInt(28, lvl);
		}

		private static int WarCryDamage(int lvl)
		{
			return Progression.DmgInt(9, lvl);
		}

		private static int ChargeDamage(int lvl)
		{
			return Progression.DmgInt(12, lvl);
		}

		private static int SpearDamage(int lvl)
		{
			return Progression.DmgInt(21, lvl);
		}

		private static int SeismicDamage(int lvl)
		{
			return Progression.DmgInt(20, lvl);
		}

		private static int WhirlwindDamage(int lvl)
		{
			return Progression.DmgInt(12, lvl);
		}

		private static int SlamDamage(int lvl)
		{
			return Progression.DmgInt(26, lvl);
		}

		private static int GodSpearPierce(int lvl)
		{
			return Progression.DmgInt(15, lvl);
		}

		private static int GodSpearLightning(int lvl)
		{
			return Progression.DmgInt(9, lvl);
		}

		private static int SkyDiveDamage(int lvl)
		{
			return Progression.DmgInt(18, lvl);
		}

		private static int JudgementDamage(int lvl)
		{
			return Progression.DmgInt(24, lvl);
		}

		private static int VolleyDamage(int lvl)
		{
			return Progression.DmgInt(11, lvl);
		}

		private static int RagnarokDamage(int lvl)
		{
			return Progression.DmgInt(23, lvl);
		}

		private static int RagnarokBoltDamage(int lvl)
		{
			return Progression.DmgInt(13, lvl);
		}

		private static int AdjGodSpearPierce(int lvl)
		{
			return Mathf.RoundToInt((float)GodSpearPierce(lvl) * TalentSystem.Mult(LP, "einh_heavypoint", 1.3f) * TalentSystem.Mult(LP, "stc_sharpspears", 1.3f) * TalentSystem.Mult(LP, "spm_spearforce", 1.4f) * TalentSystem.DamageMult(LP, "pierce"));
		}

		private static int AdjSkyDiveDamage(int lvl)
		{
			return Mathf.RoundToInt((float)SkyDiveDamage(lvl) * TalentSystem.Mult(LP, "einh_crashdive", 1.4f) * TalentSystem.Mult(LP, "stc_skyhunter", 1.3f) * TalentSystem.Mult(LP, "thu_diveforce", 1.4f) * TalentSystem.Mult(LP, "spm_diveforce", 1.4f) * TalentSystem.Mult(LP, "vk_diveforce", 1.4f) * TalentSystem.DamageMult(LP, "blunt"));
		}

		private static float SkyDiveRadius()
		{
			return 5f + (TalentSystem.Has(LP, "vk_notable") ? 2f : 0f);
		}

		private static int AdjJudgementDamage(int lvl)
		{
			return Mathf.RoundToInt((float)JudgementDamage(lvl) * TalentSystem.Mult(LP, "stc_maim", 1.3f) * TalentSystem.Mult(LP, "thu_judgeforce", 1.5f) * TalentSystem.Mult(LP, "shr_judgeforce", 1.4f) * TalentSystem.Mult(LP, "vk_judgeforce", 1.5f) * TalentSystem.DamageMult(LP, "lightning"));
		}

		private static float JudgementRadius()
		{
			return 4f + (TalentSystem.Has(LP, "einh_farsight") ? 2f : 0f) + (TalentSystem.Has(LP, "thu_notable") ? 2f : 0f) + (float)TalentSystem.Rank(LP, "shr_judgewide") + (float)TalentSystem.Rank(LP, "vk_judgewide");
		}

		private static int JudgementStrikes()
		{
			if (!TalentSystem.Has(LP, "einh_stormherald") && !TalentSystem.Has(LP, "thu_judgetwin"))
			{
				return 1;
			}
			return 2;
		}

		private static int VolleyCount()
		{
			return (TalentSystem.Has(LP, "einh_twinspears") ? 7 : 5) + TalentSystem.Rank(LP, "spm_volleycount") + (TalentSystem.Has(LP, "spm_notable") ? 2 : 0) + (TalentSystem.Has(LP, "spm_capstone") ? 2 : 0);
		}

		private static int AdjVolleyDamage(int lvl)
		{
			return Mathf.RoundToInt((float)VolleyDamage(lvl) * TalentSystem.Mult(LP, "einh_piercingvolley", 1.3f) * TalentSystem.Mult(LP, "stc_volleymaster", 1.3f) * TalentSystem.Mult(LP, "spm_volleyforce", 1.5f) * TalentSystem.DamageMult(LP, "pierce"));
		}

		private static float ValhallaBuffMult()
		{
			return 1f + 0.05f * (float)TalentSystem.Rank(LP, "val_grace") + 0.03f * (float)TalentSystem.Rank(LP, "vlk_grace") + (TalentSystem.Has(LP, "val_notable") ? 0.15f : 0f) + (TalentSystem.Has(LP, "vlk_notable") ? 0.1f : 0f);
		}

		private static float BlessingDuration()
		{
			return ((TalentSystem.Has(LP, "einh_hymn") ? 20f : 12f) + 5f * (float)TalentSystem.Rank(LP, "cv_lingerblessing") + 5f * (float)TalentSystem.Rank(LP, "vk_blesslong") + (TalentSystem.HasSynergy(LP, "syn_warbanner") ? 5f : 0f)) * ValhallaBuffMult();
		}

		private static int BlessingAttack()
		{
			return 15 + 5 * (TalentSystem.Rank(LP, "spm_blessforce") + TalentSystem.Rank(LP, "vk_blessforce")) + (TalentSystem.Has(LP, "vlk_notable") ? 10 : 0) + 2 * TalentSystem.Rank(LP, "vlk_blessforce");
		}

		private static float AegisDuration()
		{
			return ((TalentSystem.Has(LP, "einh_extaegis") ? 30f : 20f) + 5f * (float)TalentSystem.Rank(LP, "cv_hostenduring") + 5f * (float)TalentSystem.Rank(LP, "shr_aegisforce") + 5f * (float)TalentSystem.Rank(LP, "vlk_aegisforce")) * ValhallaBuffMult();
		}

		private static float ValkyrieRadius()
		{
			return 8f + ValkyrieReachBonus(LP);
		}

		private static int GraceHeal(int lvl)
		{
			return Progression.HealInt(24, lvl);
		}

		private static float GraceRadius()
		{
			return ValkyrieRadius() + (float)TalentSystem.Rank(LP, "vlk_gracewide");
		}

		private static float GraceDuration()
		{
			return (10f + 3f * (float)TalentSystem.Rank(LP, "vlk_gracelong")) * ValhallaBuffMult();
		}

		private static int AdjGraceHeal(int lvl)
		{
			return Mathf.RoundToInt((float)GraceHeal(lvl) * (1f + 0.08f * (float)TalentSystem.Rank(LP, "vlk_graceforce")) * TalentSystem.HealMult(LP));
		}

		private static int SoulSpearDamage(int lvl)
		{
			return Progression.DmgInt(20, lvl);
		}

		private static int AdjSoulSpearDamage(int lvl)
		{
			return Mathf.RoundToInt((float)SoulSpearDamage(lvl) * TalentSystem.Mult(LP, "her_spearforce", 1.5f) * TalentSystem.DamageMult(LP, "spirit"));
		}

		private static int SoulWailDamage(int lvl)
		{
			return Progression.DmgInt(16, lvl);
		}

		private static float SoulWailRadius()
		{
			return 6f + (float)TalentSystem.Rank(LP, "her_wailwide");
		}

		private static int AdjSoulWailDamage(int lvl)
		{
			return Mathf.RoundToInt((float)SoulWailDamage(lvl) * TalentSystem.Mult(LP, "her_wailforce", 1.5f) * TalentSystem.DamageMult(LP, "spiri