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 CastAction; public Func 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 CooldownEnd = new Dictionary(); 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 FireMinions = new List(); private static readonly List MagmaMinions = new List(); private static readonly List FireArmy = new List(); private const string FireImpPrefab = "Surtling"; private static readonly string[] MagmaPrefabNames = new string[3] { "BlobLava", "Charred_Melee", "Surtling" }; private static readonly List SpiritMinions = new List(); private static readonly List Minions = new List(); private static readonly List ArmyMinions = new List(); private static readonly Dictionary AscendantPaths = BuildAscendantPaths(); private static readonly Dictionary ExpandedRosterCache = new Dictionary(); private static readonly Dictionary AscensionUltimates = new Dictionary(); 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, "spirit")); } private static int HeraldLegionCount() { return 4 + TalentSystem.Rank(LP, "her_legioncount"); } private static float HeraldLegionLifetime() { return 60f + 15f * (float)TalentSystem.Rank(LP, "her_legionlong"); } private static int SpiritCap() { return 2 + (TalentSystem.Has(LP, "einh_twinfallen") ? 1 : 0) + TalentSystem.Rank(LP, "cv_honorlegion") + TalentSystem.Rank(LP, "vlk_honorcap") + TalentSystem.Rank(LP, "her_fallencap") + (TalentSystem.Has(LP, "her_capstone") ? 1 : 0); } private static int AdjRagnarokDamage(int lvl) { return Mathf.RoundToInt((float)RagnarokDamage(lvl) * TalentSystem.Mult(LP, "einh_worldbreaker", 1.4f) * TalentSystem.Mult(LP, "stc_soulburst", 1.3f) * TalentSystem.Mult(LP, "stc_capstone", 1.2f) * TalentSystem.Mult(LP, "thu_ragforce", 1.4f) * TalentSystem.Mult(LP, "shr_ragforce", 1.4f) * TalentSystem.Mult(LP, "vk_ragforce", 1.4f) * TalentSystem.Mult(LP, "vlk_ragforce", 1.4f) * TalentSystem.DamageMult(LP, "blunt")); } private static int RagnarokBolts() { return (TalentSystem.Has(LP, "einh_endlessstorm") ? 10 : 6) + TalentSystem.Rank(LP, "shr_ragbolts"); } private static float RagnarokRadius() { return 12f + (TalentSystem.Has(LP, "shr_ragwide") ? 2f : 0f); } private static int ThunderboltDamage(int lvl) { return Progression.DmgInt(20, lvl); } private static int AdjThunderboltDamage(int lvl) { return Mathf.RoundToInt((float)ThunderboltDamage(lvl) * TalentSystem.Mult(LP, "thu_boltforce", 1.4f) * TalentSystem.DamageMult(LP, "lightning")); } private static int ThunderclapDamage(int lvl) { return Progression.DmgInt(18, lvl); } private static float ThunderclapRadius() { return 6f + (float)TalentSystem.Rank(LP, "thu_clapwide"); } private static int AdjThunderclapDamage(int lvl) { return Mathf.RoundToInt((float)ThunderclapDamage(lvl) * TalentSystem.Mult(LP, "thu_clapforce", 1.5f) * TalentSystem.DamageMult(LP, "lightning")); } private static float ThunderstormTick(int lvl) { return Progression.Dmg(7f, lvl); } private static float ThunderstormRadius() { return 8f + (float)TalentSystem.Rank(LP, "shr_stormwide") + (TalentSystem.Has(LP, "shr_capstone") ? 3f : 0f); } private static float ThunderstormDuration() { return 8f + 2f * (float)TalentSystem.Rank(LP, "shr_stormlong") + (TalentSystem.Has(LP, "shr_notable") ? 2f : 0f); } private static int AdjThunderstormTick(int lvl) { return Mathf.RoundToInt(ThunderstormTick(lvl) * TalentSystem.Mult(LP, "shr_stormforce", 1.5f) * TalentSystem.DamageMult(LP, "lightning")); } private static int SkyfallDamage(int lvl) { return Progression.DmgInt(16, lvl); } private static int SkyfallCount() { return 8 + 2 * TalentSystem.Rank(LP, "spm_skycount"); } private static float SkyfallRadius() { return 6f + (float)TalentSystem.Rank(LP, "spm_skywide"); } private static int AdjSkyfallDamage(int lvl) { return Mathf.RoundToInt((float)SkyfallDamage(lvl) * TalentSystem.Mult(LP, "spm_skyforce", 1.4f) * TalentSystem.DamageMult(LP, "pierce")); } private static int BashDamage(int lvl) { return Progression.DmgInt(14, lvl); } private static int LeapDamage(int lvl) { return Progression.DmgInt(15, lvl); } private static int StompDamage(int lvl) { return Progression.DmgInt(18, lvl); } private static int HornDamage(int lvl) { return Progression.DmgInt(20, lvl); } private static int ShoutDamage(int lvl) { return Progression.DmgInt(14, lvl); } private static int StormTickDamage(int lvl) { return Progression.DmgInt(11, lvl); } private static int AdjShoutDamage(int lvl) { return Mathf.RoundToInt((float)ShoutDamage(lvl) * TalentSystem.Mult(LP, "vg_shatteringvoice", 1.3f) * TalentSystem.Mult(LP, "wbr_shoutforce", 1.5f) * TalentSystem.DamageMult(LP, "blunt")); } private static float ShoutRadius() { return 6f + (float)TalentSystem.Rank(LP, "wbr_shoutwide"); } private static int AdjStormTickDamage(int lvl) { return Mathf.RoundToInt((float)StormTickDamage(lvl) * TalentSystem.Mult(LP, "vg_stormblades", 1.3f) * TalentSystem.Mult(LP, "cru_stormforce", 1.4f) * TalentSystem.DamageMult(LP, "blunt")); } private static int FrenzyAttack() { return 15 + (TalentSystem.Has(LP, "vg_frenzyfort") ? 10 : 0) + 5 * TalentSystem.Rank(LP, "wbr_frenzyforce"); } private static int AdjBashDamage(int lvl) { return Mathf.RoundToInt((float)BashDamage(lvl) * (AltSpec ? 1.6f : 1f) * TalentSystem.Mult(LP, "gua_bash", 1.3f) * TalentSystem.Mult(LP, "vg_savagebash", 1.3f) * TalentSystem.Mult(LP, "gb_bashforce", 1.2f) * TalentSystem.Mult(LP, "snt_bashforce", 1.3f) * TalentSystem.Mult(LP, "cru_crushforce", 1.4f) * TalentSystem.DamageMult(LP, "blunt")); } private static float ChallengeRadius() { return 10f + 2f * (float)TalentSystem.Rank(LP, "gua_provoker") + (float)TalentSystem.Rank(LP, "wrd_challwide"); } private static float ShieldWallRadius() { return 8f + 1.5f * (float)TalentSystem.Rank(LP, "gua_wideskjald") + (TalentSystem.Has(LP, "wrd_notable") ? 2f : 0f) + (float)TalentSystem.Rank(LP, "wrd_reach"); } private static float ShieldWallDuration() { return 15f + (TalentSystem.Has(LP, "gua_longskjald") ? 10f : 0f) + 5f * (float)TalentSystem.Rank(LP, "blw_toweringwall") + 3f * (float)TalentSystem.Rank(LP, "wrd_walllong"); } private static int AdjLeapDamage(int lvl) { return Mathf.RoundToInt((float)LeapDamage(lvl) * TalentSystem.Mult(LP, "gua_heavylanding", 1.4f) * TalentSystem.Mult(LP, "vg_executioner", 1.2f) * TalentSystem.Mult(LP, "cru_leapforce", 1.4f) * TalentSystem.Mult(LP, "wbr_leapforce", 1.4f) * TalentSystem.DamageMult(LP, "blunt")); } private static float RampartDuration() { if (!TalentSystem.Has(LP, "gua_rampart")) { return 10f; } return 20f; } private static float BulwarkDuration() { return (TalentSystem.Has(LP, "gua_extbul") ? 30f : 20f) + 5f * (float)TalentSystem.Rank(LP, "snt_bulwarklong"); } private static float StompRadius() { return 8f + (TalentSystem.Has(LP, "gua_tremor") ? 3f : 0f) + (AltSpec ? 2f : 0f) + 1.5f * (float)TalentSystem.Rank(LP, "vg_widerupture") + (float)TalentSystem.Rank(LP, "cru_slamwide") + (TalentSystem.Has(LP, "cru_notable") ? 2f : 0f) + (TalentSystem.HasSynergy(LP, "syn_shockwave") ? 1.5f : 0f); } private static int AdjStompDamage(int lvl) { return Mathf.RoundToInt((float)StompDamage(lvl) * (AltSpec ? 1.5f : 1f) * TalentSystem.Mult(LP, "gua_stonefist", 1.3f) * TalentSystem.Mult(LP, "vg_brutality", 1.15f) * TalentSystem.Mult(LP, "cru_slamforce", 1.5f) * TalentSystem.DamageMult(LP, "blunt")); } private static float FortressDuration() { return ((TalentSystem.Has(LP, "gua_extfort") || TalentSystem.Has(LP, "vg_capstone")) ? 30f : 20f) + 5f * (float)TalentSystem.Rank(LP, "wrd_fortlong") + 5f * (float)TalentSystem.Rank(LP, "wbr_frenzylong") + (TalentSystem.Has(LP, "wbr_capstone") ? 10f : 0f); } private static float HornRadius() { return 12f + (TalentSystem.Has(LP, "gua_greathorn") ? 4f : 0f) + (float)TalentSystem.Rank(LP, "wrd_hornwide") + (float)TalentSystem.Rank(LP, "wbr_hornwide"); } private static int AdjHornDamage(int lvl) { return Mathf.RoundToInt((float)HornDamage(lvl) * (AltSpec ? 1.5f : 1f) * TalentSystem.Mult(LP, "gua_hornbreaker", 1.4f) * TalentSystem.Mult(LP, "vg_warhorn", 1.26f) * TalentSystem.Mult(LP, "wrd_hornforce", 1.4f) * TalentSystem.Mult(LP, "snt_hornforce", 1.4f) * TalentSystem.Mult(LP, "wbr_hornforce", 1.4f) * TalentSystem.DamageMult(LP, "blunt")); } private static float ThornplateDuration() { return 20f + 5f * (float)TalentSystem.Rank(LP, "snt_thornlong"); } private static int ThornplateReflect(int lvl) { return Mathf.RoundToInt(Progression.Dmg(10f, lvl) * (1f + 0.1f * (float)TalentSystem.Rank(LP, "snt_thornforce"))); } private static int EarthbreakerDamage(int lvl) { return Progression.DmgInt(26, lvl); } private static float EarthbreakerRadius() { return 8f + (float)TalentSystem.Rank(LP, "cru_earthwide") + (TalentSystem.Has(LP, "cru_notable") ? 2f : 0f); } private static int AdjEarthbreakerDamage(int lvl) { return Mathf.RoundToInt((float)EarthbreakerDamage(lvl) * TalentSystem.Mult(LP, "cru_earthforce", 1.4f) * TalentSystem.DamageMult(LP, "blunt")); } private static float HolyRadius() { return 8f + (float)TalentSystem.Rank(LP, "pal_reach") + (float)TalentSystem.Rank(LP, "tmp_reach"); } private static float HolyBuffDuration() { return 20f; } private static int BlessLightAttack() { return 15 + 2 * TalentSystem.Rank(LP, "tmp_blessforce") + (TalentSystem.Has(LP, "pal_notable") ? 5 : 0); } private static int BlessLightArmor() { return 20; } private static float HolyGroundRadius() { return 6f + (float)TalentSystem.Rank(LP, "lbr_conswide") + (TalentSystem.Has(LP, "tmp_notable") ? 2f : 0f); } private static float HolyGroundDuration() { return 8f + 2f * (float)(TalentSystem.Rank(LP, "tmp_conslong") + TalentSystem.Rank(LP, "lbr_conslong")); } private static int AdjConsecrationHeal(int lvl) { return Mathf.Max(1, Mathf.RoundToInt(Progression.Heal(5f, lvl) * (1f + 0.1f * (float)TalentSystem.Rank(LP, "tmp_consforce")) * TalentSystem.HealMult(LP))); } private static int AdjConsecrationDamage(int lvl) { return Mathf.RoundToInt(Progression.Dmg(6f, lvl) * TalentSystem.Mult(LP, "lbr_consforce", 1.5f) * TalentSystem.DamageMult(LP, "spirit")); } private static int AdjLayOnHandsHeal(int lvl) { return Mathf.RoundToInt(Progression.Heal(30f, lvl) * (1f + 0.1f * (float)TalentSystem.Rank(LP, "tmp_handforce")) * TalentSystem.HealMult(LP)); } private static int DivineShieldArmor() { return 30 + 6 * TalentSystem.Rank(LP, "tmp_shieldforce"); } private static float DivineShieldDuration() { return 20f + 5f * (float)TalentSystem.Rank(LP, "tmp_shieldlong"); } private static int AdjBeaconHeal(int lvl) { return Mathf.RoundToInt(Progression.Heal(24f, lvl) * (1f + 0.1f * (float)TalentSystem.Rank(LP, "tmp_beaconforce")) * TalentSystem.HealMult(LP)); } private static float BeaconDuration() { return 10f + 3f * (float)TalentSystem.Rank(LP, "tmp_beaconlong"); } private static int SmiteDamage(int lvl) { return Progression.DmgInt(18, lvl); } private static int AdjSmiteDamage(int lvl) { return Mathf.RoundToInt((float)SmiteDamage(lvl) * TalentSystem.Mult(LP, "lbr_smiteforce", 1.4f) * TalentSystem.DamageMult(LP, "spirit")); } private static int HolyNovaDamage(int lvl) { return Progression.DmgInt(16, lvl); } private static float HolyNovaRadius() { return 6f + (float)TalentSystem.Rank(LP, "lbr_novawide"); } private static int AdjHolyNovaDamage(int lvl) { return Mathf.RoundToInt((float)HolyNovaDamage(lvl) * TalentSystem.Mult(LP, "lbr_novaforce", 1.5f) * TalentSystem.DamageMult(LP, "spirit")); } private static int WrathDamage(int lvl) { return Progression.DmgInt(24, lvl); } private static float WrathRadius() { return 10f + 2f * (float)TalentSystem.Rank(LP, "lbr_wrathwide"); } private static int AdjWrathDamage(int lvl) { return Mathf.RoundToInt((float)WrathDamage(lvl) * TalentSystem.Mult(LP, "lbr_wrathforce", 1.4f) * TalentSystem.DamageMult(LP, "spirit")); } private static int ThornDamage(int lvl) { return Progression.DmgInt(13, lvl); } private static int RootsDamage(int lvl) { return Progression.DmgInt(18, lvl); } private static int RegrowthHeal(int lvl) { return Progression.HealInt(22, lvl); } private static int EmbraceHeal(int lvl) { return Progression.HealInt(29, lvl); } private static int YggdrasilHeal(int lvl) { return Progression.HealInt(41, lvl); } private static int YggdrasilDamage(int lvl) { return Progression.DmgInt(16, lvl); } private static float BloomHealPerTick(int lvl) { return Progression.Heal(4.2f, lvl); } private static int ThornSapDamage(int lvl) { return Progression.DmgInt(10, lvl); } private static int AdjThornSapDamage(int lvl) { return Adj(ThornSapDamage(lvl), "pierce"); } private static float BloomPoisonPerTick(int lvl) { return Progression.Dmg(4.75f, lvl); } private static int AdjBloomPoison(int lvl) { return Mathf.Max(1, Mathf.RoundToInt(BloomPoisonPerTick(lvl) * TalentSystem.Mult(LP, "tw_toxicbloom", 1.5f) * TalentSystem.Mult(LP, "tw_corrosion", 1.5f) * TalentSystem.DamageMult(LP, "poison"))); } private static float NatureFuryDuration() { return ((TalentSystem.Has(LP, "tw_fury") ? 20f : 12f) + 4f * (float)TalentSystem.Rank(LP, "tw_longfury") + 3f * (float)TalentSystem.Rank(LP, "sk_furylong")) * BuffDurationMult(); } private static float NatureFuryRadius() { return BlessingRadius() + (TalentSystem.Has(LP, "tw_widefury") ? 3f : 0f) + (TalentSystem.Has(LP, "tw_capstone") ? 4f : 0f); } private static float BlessingRadius() { return 8f + 2f * (float)TalentSystem.Rank(LP, "dru_reach") + 1.5f * (float)TalentSystem.Rank(LP, "lk_grace") + (TalentSystem.Has(LP, "dru_natureswrath") ? 2f : 0f) + (float)TalentSystem.Rank(LP, "wd_reach") + (float)TalentSystem.Rank(LP, "sk_reach") + (float)TalentSystem.Rank(LP, "rs_reach") + (TalentSystem.Has(LP, "sk_capstone") ? 3f : 0f) + (TalentSystem.Has(LP, "lif_capstone") ? 3f : 0f); } private static int AdjRegrowthHeal(int lvl) { return Mathf.RoundToInt((float)RegrowthHeal(lvl) * TalentSystem.Mult(LP, "dru_mender", 1.25f) * (1f + 0.08f * (float)(TalentSystem.Rank(LP, "lif_regrow") + TalentSystem.Rank(LP, "gk_regrow"))) * TalentSystem.HealMult(LP)); } private static int AdjThornDamage(int lvl) { return Mathf.RoundToInt((float)ThornDamage(lvl) * TalentSystem.Mult(LP, "dru_sharpthorns", 1.3f) * TalentSystem.Mult(LP, "tw_venomtip", 1.2f) * TalentSystem.DamageMult(LP, "pierce")); } private static float ForestBlessingDuration() { return (TalentSystem.Has(LP, "dru_longblessing") ? 20f : 12f) * BuffDurationMult(); } private static float BloomRadius() { return 6f + (float)TalentSystem.Rank(LP, "dru_widebloom") + (float)TalentSystem.Rank(LP, "lk_blossom") + (float)TalentSystem.Rank(LP, "tw_spikes") + (float)TalentSystem.Rank(LP, "rs_reach") + (float)TalentSystem.Rank(LP, "lif_bloomwide") + (TalentSystem.Has(LP, "gk_notable") ? 2f : 0f); } private static float BloomDuration() { return 12f + 3f * (float)(TalentSystem.Rank(LP, "dru_longbloom") + TalentSystem.Rank(LP, "lk_springs") + TalentSystem.Rank(LP, "lif_bloomlong") + TalentSystem.Rank(LP, "gk_bloomlong")) + (TalentSystem.HasSynergy(LP, "syn_venomancer") ? 4f : 0f); } private static int AdjBloomHeal(int lvl) { return Mathf.Max(1, Mathf.RoundToInt(BloomHealPerTick(lvl) * TalentSystem.Mult(LP, "dru_bloom", 1.5f) * TalentSystem.Mult(LP, "lk_meadow", 1.5f) * (1f + 0.1f * (float)(TalentSystem.Rank(LP, "lif_bloomforce") + TalentSystem.Rank(LP, "gk_bloomforce"))) * TalentSystem.HealMult(LP))); } private static float WindsGraceDuration() { return ((TalentSystem.Has(LP, "dru_longwind") ? 30f : 20f) + 5f * (float)TalentSystem.Rank(LP, "dru_gale") + 3f * (float)TalentSystem.Rank(LP, "sk_windgrace") + 3f * (float)TalentSystem.Rank(LP, "gk_windforce")) * BuffDurationMult(); } private static float RootsRadius() { return 8f + (float)TalentSystem.Rank(LP, "dru_wideroots") + (float)TalentSystem.Rank(LP, "gk_rootwide"); } private static int AdjRootsDamage(int lvl) { return Mathf.RoundToInt((float)RootsDamage(lvl) * TalentSystem.Mult(LP, "dru_deeproots", 1.3f) * TalentSystem.Mult(LP, "tw_impale", 1.2f) * (1f + 0.1f * (float)TalentSystem.Rank(LP, "gk_rootforce")) * TalentSystem.DamageMult(LP, "pierce")); } private static int AdjEmbraceHeal(int lvl) { return Mathf.RoundToInt((float)EmbraceHeal(lvl) * TalentSystem.Mult(LP, "dru_embrace", 1.3f) * (1f + 0.08f * (float)(TalentSystem.Rank(LP, "sk_embraceforce") + TalentSystem.Rank(LP, "bm_embraceforce") + TalentSystem.Rank(LP, "lif_embraceforce"))) * TalentSystem.HealMult(LP)); } private static float EmbraceDuration() { return ((TalentSystem.Has(LP, "dru_lasting") ? 20f : 10f) + 5f * (float)TalentSystem.Rank(LP, "lk_wardens") + 5f * (float)TalentSystem.Rank(LP, "sk_embracelong") + 5f * (float)TalentSystem.Rank(LP, "lif_embracelong")) * BuffDurationMult(); } private static int AdjYggdrasilHeal(int lvl) { return Mathf.RoundToInt((float)YggdrasilHeal(lvl) * TalentSystem.Mult(LP, "dru_yggdrasil", 1.5f) * TalentSystem.Mult(LP, "lk_lifegiver", 1.5f) * (1f + 0.12f * (float)TalentSystem.Rank(LP, "lif_yggforce")) * TalentSystem.HealMult(LP)); } private static int AdjYggdrasilDamage(int lvl) { return Mathf.RoundToInt((float)YggdrasilDamage(lvl) * TalentSystem.Mult(LP, "tw_worldthorn", 1.4f) * TalentSystem.Mult(LP, "tw_worldrage", 1.4f) * TalentSystem.DamageMult(LP, "pierce")); } private static int DrainDamage(int lvl) { return Progression.DmgInt(12, lvl); } private static int DrainHeal(int lvl) { return Progression.HealInt(10, lvl); } private static int OozeDamage(int lvl) { return Progression.DmgInt(18, lvl); } private static int ToxicTickDamage(int lvl) { return Progression.DmgInt(7, lvl); } private static int SpectralDamage(int lvl) { return Progression.DmgInt(18, lvl); } private static int MaxSkeletons(int lvl) { Player localPlayer = Player.m_localPlayer; int num = 0; if ((Object)(object)localPlayer != (Object)null) { num += (TalentSystem.Has(localPlayer, "bn_notable") ? 1 : 0); num += TalentSystem.Rank(localPlayer, "bl_horde"); num += (TalentSystem.Has(localPlayer, "bl_notable") ? 1 : 0); num += (TalentSystem.Has(localPlayer, "bl_capstone") ? 1 : 0); } return Mathf.Clamp(1 + lvl / 40, 1, 2) + num; } private static int Adj(int baseValue, string element) { return Mathf.Max(1, Mathf.RoundToInt((float)baseValue * TalentSystem.DamageMult(LP, element))); } private static float FrostNovaRadius() { return 8f * TalentSystem.Mult(LP, "mage_widenova", 1.25f) + (TalentSystem.Has(LP, "mage_permafrost") ? 3f : 0f) + (float)TalentSystem.Rank(LP, "dst_frostreach"); } private static int IceShardCount() { if (!TalentSystem.Has(LP, "mage_splitter")) { return 5; } return 7; } private static int RingCount() { return (TalentSystem.Has(LP, "mage_inferno") ? 16 : 12) + TalentSystem.Rank(LP, "dst_combustion"); } private static int StormBolts() { return (TalentSystem.Has(LP, "mage_tempest") ? 12 : 8) + TalentSystem.Rank(LP, "dst_stormsurge"); } private static int MeteorCount() { if (!TalentSystem.Has(LP, "mage_meteormastery")) { return 10; } return 13; } private static int FlameWaveDamage(int lvl) { return Progression.DmgInt(10, lvl); } private static int PillarDamage(int lvl) { return Progression.DmgInt(30, lvl); } private static float BurningTick(int lvl) { return Progression.Dmg(6f, lvl); } private static int AdjFlameWaveDamage(int lvl) { return Mathf.RoundToInt((float)FlameWaveDamage(lvl) * TalentSystem.Mult(LP, "pyr_waverider", 1.5f) * TalentSystem.DamageMult(LP, "fire")); } private static int AdjPillarDamage(int lvl) { return Mathf.RoundToInt((float)PillarDamage(lvl) * TalentSystem.Mult(LP, "pyr_pillarforce", 1.5f) * TalentSystem.DamageMult(LP, "fire")); } private static int AdjBurningTick(int lvl) { return Mathf.RoundToInt(BurningTick(lvl) * TalentSystem.Mult(LP, "smn_searingground", 1.32f) * TalentSystem.DamageMult(LP, "fire")); } private static float BurningGroundRadius() { return 4f + (float)TalentSystem.Rank(LP, "smn_groundcrew"); } private static float BurningGroundDuration() { return 8f + 2f * (float)TalentSystem.Rank(LP, "smn_lastingash"); } private static int FireImpCap() { return 1 + TalentSystem.Rank(LP, "smn_twinimp") + (TalentSystem.Has(LP, "smn_capstone") ? 1 : 0); } private static int LegionCount() { return 3 + TalentSystem.Rank(LP, "smn_greaterlegion"); } private static float LegionLifetime() { return 60f + 10f * (float)TalentSystem.Rank(LP, "smn_legiondrill"); } private static int GlacialSpikeDamage(int lvl) { return Progression.DmgInt(22, lvl); } private static float BlizzardTickDamage(int lvl) { return Progression.Dmg(8f, lvl); } private static int AbsoluteZeroDamage(int lvl) { return Progression.DmgInt(26, lvl); } private static float GraspTickDamage(int lvl) { return Progression.Dmg(5f, lvl); } private static int FimbulBlastDamage(int lvl) { return Progression.DmgInt(20, lvl); } private static int ChainDamage(int lvl) { return Progression.DmgInt(20, lvl); } private static float FieldTickDamage(int lvl) { return Progression.Dmg(7f, lvl); } private static int ThorBoltDamage(int lvl) { return Progression.DmgInt(22, lvl); } private static float BallTickDamage(int lvl) { return Progression.Dmg(7f, lvl); } private static int EyeBoltDamage(int lvl) { return Progression.DmgInt(16, lvl); } private static int AdjGlacialSpikeDamage(int lvl) { return Mathf.RoundToInt((float)GlacialSpikeDamage(lvl) * TalentSystem.Mult(LP, "cry_spikeforce", 1.4f) * TalentSystem.DamageMult(LP, "frost")); } private static float BlizzardRadius() { return 8f + (float)TalentSystem.Rank(LP, "cry_blizzwide"); } private static int AdjBlizzardTick(int lvl) { return Mathf.RoundToInt(BlizzardTickDamage(lvl) * TalentSystem.Mult(LP, "cry_blizzforce", 1.5f) * TalentSystem.DamageMult(LP, "frost")); } private static int AdjAbsoluteZeroDamage(int lvl) { return Mathf.RoundToInt((float)AbsoluteZeroDamage(lvl) * TalentSystem.Mult(LP, "cry_zeroforce", 1.4f) * (TalentSystem.Has(LP, "cry_zero") ? 1.25f : 1f) * TalentSystem.DamageMult(LP, "frost")); } private static float FrostArmorDuration() { return 25f + 5f * (float)TalentSystem.Rank(LP, "fw_armorlong"); } private static float GraspRadius() { return 5f + (float)TalentSystem.Rank(LP, "fw_graspwide"); } private static int AdjGraspTick(int lvl) { return Mathf.RoundToInt(GraspTickDamage(lvl) * TalentSystem.Mult(LP, "fw_graspforce", 1.5f) * TalentSystem.DamageMult(LP, "frost")); } private static float FimbulRadius() { return 12f + (TalentSystem.Has(LP, "fw_capstone") ? 3f : 0f); } private static int AdjFimbulBlastDamage(int lvl) { return Mathf.RoundToInt((float)FimbulBlastDamage(lvl) * TalentSystem.Mult(LP, "fw_fimbulforce", 1.5f) * TalentSystem.DamageMult(LP, "frost")); } private static int ChainJumps() { return 2 + TalentSystem.Rank(LP, "st_chainjump"); } private static int AdjChainDamage(int lvl) { return Mathf.RoundToInt((float)ChainDamage(lvl) * TalentSystem.Mult(LP, "st_chainforce", 1.4f) * TalentSystem.DamageMult(LP, "lightning")); } private static float FieldRadius() { return 4f + (float)TalentSystem.Rank(LP, "st_fieldwide"); } private static float FieldDuration() { return 6f + 2f * (float)TalentSystem.Rank(LP, "st_fieldlong"); } private static int AdjFieldTick(int lvl) { return Mathf.RoundToInt(FieldTickDamage(lvl) * TalentSystem.Mult(LP, "st_fieldforce", 1.5f) * TalentSystem.DamageMult(LP, "lightning")); } private static int AdjThorBoltDamage(int lvl) { return Mathf.RoundToInt((float)ThorBoltDamage(lvl) * TalentSystem.Mult(LP, "st_wrathforce", 1.4f) * TalentSystem.DamageMult(LP, "lightning")); } private static float BlinkDistance() { return 10f + 2f * (float)TalentSystem.Rank(LP, "tm_blinkrange"); } private static float ShroudDuration() { return 15f + 5f * (float)TalentSystem.Rank(LP, "tm_shroudlong"); } private static float BallDuration() { return 6f + (float)TalentSystem.Rank(LP, "tm_balllife"); } private static int AdjBallTick(int lvl) { return Mathf.RoundToInt(BallTickDamage(lvl) * TalentSystem.Mult(LP, "tm_ballforce", 1.4f) * TalentSystem.DamageMult(LP, "lightning")); } private static float EyeRadius() { return 10f + (float)TalentSystem.Rank(LP, "tm_eyewide"); } private static int AdjEyeBoltDamage(int lvl) { return Mathf.RoundToInt((float)EyeBoltDamage(lvl) * TalentSystem.Mult(LP, "tm_eyeforce", 1.4f) * TalentSystem.DamageMult(LP, "lightning")); } private static int AdjFireballDamage(int lvl) { return Mathf.RoundToInt((float)FireballDamage(lvl) * TalentSystem.Mult(LP, "dst_burn", 1.2f) * TalentSystem.DamageMult(LP, "fire")); } private static int AdjFrostNovaDamage(int lvl) { return Mathf.RoundToInt((float)FrostNovaDamage(lvl) * TalentSystem.Mult(LP, "mg_frostbite", 1.4f) * ((ClassSystem.GetClass(LP) == PlayerClass.Mage && SpecSystem.IsAlternative(LP)) ? 0.5f : 1f) * TalentSystem.DamageMult(LP, "frost")); } private static int AdjIceShardDamage(int lvl) { return Mathf.RoundToInt((float)IceShardDamage(lvl) * TalentSystem.Mult(LP, "dst_shards", 1.2f) * TalentSystem.DamageMult(LP, "frost")); } private static int AdjStormBoltDamage(int lvl) { return Mathf.RoundToInt((float)StormBoltDamage(lvl) * TalentSystem.Mult(LP, "dst_overcharge", 1.4f) * TalentSystem.DamageMult(LP, "lightning")); } private static int AdjMeteorDamage(int lvl) { return Mathf.RoundToInt((float)MeteorDamage(lvl) * TalentSystem.Mult(LP, "mage_cataclysm", 1.4f) * TalentSystem.Mult(LP, "dst_pyre", 1.2f) * TalentSystem.DamageMult(LP, "fire")); } private static int AdjLightningBoltDamage(int lvl) { return Mathf.RoundToInt((float)LightningBoltDamage(lvl) * TalentSystem.Mult(LP, "mage_stormlance", 1.3f) * TalentSystem.Mult(LP, "dst_boltmastery", 1.2f) * TalentSystem.DamageMult(LP, "lightning")); } private static int AdjRingFireDamage(int lvl) { return Mathf.RoundToInt((float)RingFireDamage(lvl) * TalentSystem.Mult(LP, "mage_blazing", 1.32f) * TalentSystem.DamageMult(LP, "fire")); } private static float DomeRadius() { return (8f + (TalentSystem.Has(LP, "mage_runicward") ? 3f : 0f) + (TalentSystem.Has(LP, "fw_capstone") ? 3f : 0f)) * ((ClassSystem.GetClass(LP) == PlayerClass.Mage && SpecSystem.IsAlternative(LP)) ? 1.5f : 1f) + (float)TalentSystem.Rank(LP, "rw_greaterward") + (TalentSystem.HasSynergy(LP, "syn_wardkeeper") ? 1f : 0f); } private static float DomeDuration() { return 20f * TalentSystem.Mult(LP, "mage_enduring", 1.5f) + (TalentSystem.Has(LP, "rw_longward") ? 10f : 0f) + (TalentSystem.HasSynergy(LP, "syn_wardkeeper") ? 10f : 0f); } private static int FuryPercent() { return 30 + 5 * (TalentSystem.Rank(LP, "jug_furyforce") + TalentSystem.Rank(LP, "ra_furyforce") + TalentSystem.Rank(LP, "wh_furyforce")); } private static float FuryDuration() { return 15f + 3f * (float)(TalentSystem.Rank(LP, "jug_furylong") + TalentSystem.Rank(LP, "ra_furylong") + TalentSystem.Rank(LP, "wh_furylong")); } private static float IronSkinDuration() { return 20f + 5f * (float)TalentSystem.Rank(LP, "jug_ironlong"); } private static float WarCryRadius() { return 6f + (float)TalentSystem.Rank(LP, "jug_warpush"); } private static int AdjWarCryDamage(int lvl) { return Mathf.RoundToInt((float)WarCryDamage(lvl) * TalentSystem.Mult(LP, "jug_warforce", 1.4f) * TalentSystem.Mult(LP, "ea_warforce", 1.4f) * TalentSystem.DamageMult(LP, "blunt")); } private static bool ChargeIsPierce(Player player) { return BranchSystem.GetBranch(player) == 2; } private static float ChargeDamageMult(Player player) { return TalentSystem.Mult(player, "ra_chargeforce", 1.4f) * TalentSystem.Mult(player, "la_chargeforce", 1.4f); } private static int AdjChargeDamage(int lvl) { return Mathf.RoundToInt((float)ChargeDamage(lvl) * ChargeDamageMult(LP) * TalentSystem.DamageMult(LP, ChargeIsPierce(LP) ? "pierce" : "slash")); } private static int AdjSpearThrowDamage(int lvl) { return Mathf.RoundToInt((float)SpearDamage(lvl) * TalentSystem.Mult(LP, "hu_throw", 1.2f) * TalentSystem.DamageMult(LP, "pierce")); } private static float SeismicRadius() { return 8f + (float)TalentSystem.Rank(LP, "ea_seiswide"); } private static int AdjSeismicDamage(int lvl) { return Mathf.RoundToInt((float)SeismicDamage(lvl) * TalentSystem.Mult(LP, "ea_seisforce", 1.4f) * TalentSystem.DamageMult(LP, "blunt")); } private static int WhirlTicks() { if (TalentSystem.Rank(LP, "rv_whirllong") <= 0) { return 6; } return 6 + TalentSystem.Rank(LP, "rv_whirllong"); } private static float WhirlRadius() { return 4f + 0.5f * (float)TalentSystem.Rank(LP, "rv_whirlwide"); } private static int AdjWhirlDamage(int lvl) { return Mathf.RoundToInt((float)WhirlwindDamage(lvl) * TalentSystem.Mult(LP, "rv_whirlforce", 1.4f) * TalentSystem.DamageMult(LP, "slash")); } private static float SlamRadius() { return 10f + (float)TalentSystem.Rank(LP, "jug_slamwide") + (float)TalentSystem.Rank(LP, "ea_catawide"); } private static int AdjSlamDamage(int lvl) { return Mathf.RoundToInt((float)SlamDamage(lvl) * TalentSystem.Mult(LP, "jug_slamforce", 1.4f) * TalentSystem.DamageMult(LP, "blunt")); } private static int CrushingBlowDamage(int lvl) { return Progression.DmgInt(14, lvl); } private static float CrushingBlowRadius() { return 4f; } private static int AdjCrushingBlowDamage(int lvl) { return Mathf.RoundToInt((float)CrushingBlowDamage(lvl) * TalentSystem.Mult(LP, "cr_force", 1.5f) * TalentSystem.DamageMult(LP, "blunt")); } private static int CleaveDamage(int lvl) { return Progression.DmgInt(12, lvl); } private static float CleaveRadius() { return 4f; } private static int AdjCleaveDamage(int lvl) { return Mathf.RoundToInt((float)CleaveDamage(lvl) * TalentSystem.Mult(LP, "re_force", 1.5f) * TalentSystem.DamageMult(LP, "slash")); } private static int FaultLineDamage(int lvl) { return Progression.DmgInt(18, lvl); } private static float FaultLineLength() { return 12f + 2f * (float)TalentSystem.Rank(LP, "ea_faultlong"); } private static int AdjFaultLineDamage(int lvl) { return Mathf.RoundToInt((float)FaultLineDamage(lvl) * TalentSystem.Mult(LP, "ea_faultforce", 1.5f) * TalentSystem.DamageMult(LP, "blunt")); } private static int CataclysmDamage(int lvl) { return Progression.DmgInt(26, lvl); } private static int AdjCataclysmDamage(int lvl) { return Mathf.RoundToInt((float)CataclysmDamage(lvl) * TalentSystem.Mult(LP, "ea_cataforce", 1.4f) * TalentSystem.DamageMult(LP, "blunt")); } private static int RuptureDamage(int lvl) { return Progression.DmgInt(16, lvl); } private static float RuptureBleedDuration() { return 4f + 2f * (float)TalentSystem.Rank(LP, "rv_ruptbleed"); } private static int AdjRuptureDamage(int lvl) { return Mathf.RoundToInt((float)RuptureDamage(lvl) * TalentSystem.Mult(LP, "rv_ruptforce", 1.5f) * TalentSystem.DamageMult(LP, "slash")); } private static int BloodbathDamage(int lvl) { return Progression.DmgInt(13, lvl); } private static int BloodbathTicks() { return 8 + 2 * (TalentSystem.Has(LP, "rv_bathlong") ? 1 : 0); } private static float BloodbathRadius() { return 5f; } private static int AdjBloodbathDamage(int lvl) { return Mathf.RoundToInt((float)BloodbathDamage(lvl) * TalentSystem.Mult(LP, "rv_bathforce", 1.4f) * TalentSystem.DamageMult(LP, "slash")); } private static int ExecuteDamage(int lvl) { return Progression.DmgInt(24, lvl); } private static int ExecuteBonusPercent() { return 50 + 25 * TalentSystem.Rank(LP, "ra_execthresh"); } private static int AdjExecuteDamage(int lvl) { return Mathf.RoundToInt((float)ExecuteDamage(lvl) * TalentSystem.Mult(LP, "ra_execforce", 1.5f) * TalentSystem.DamageMult(LP, "slash")); } private static int RampageDamage(int lvl) { return Progression.DmgInt(11, lvl); } private static int RampageHits() { return 5 + TalentSystem.Rank(LP, "ra_ramphits"); } private static int AdjRampageDamage(int lvl) { return Mathf.RoundToInt((float)RampageDamage(lvl) * TalentSystem.Mult(LP, "ra_rampforce", 1.4f) * TalentSystem.DamageMult(LP, "slash")); } private static int SpearVolleyDamage(int lvl) { return Progression.DmgInt(12, lvl); } private static int SpearVolleyCount() { return 5 + TalentSystem.Rank(LP, "la_volleycount"); } private static int AdjSpearVolleyDamage(int lvl) { return Mathf.RoundToInt((float)SpearVolleyDamage(lvl) * TalentSystem.Mult(LP, "la_volleyforce", 1.5f) * TalentSystem.DamageMult(LP, "pierce")); } private static int ImpaleDamage(int lvl) { return Progression.DmgInt(22, lvl); } private static int AdjImpaleDamage(int lvl) { return Mathf.RoundToInt((float)ImpaleDamage(lvl) * TalentSystem.Mult(LP, "la_impaleforce", 1.5f) * TalentSystem.DamageMult(LP, "pierce")); } private static int SpearStormDamage(int lvl) { return Progression.DmgInt(16, lvl); } private static int SpearStormCount() { return 10 + (TalentSystem.Has(LP, "la_stormcount") ? 4 : 0); } private static float SpearStormRadius() { return 6f + (float)TalentSystem.Rank(LP, "la_stormwide"); } private static int AdjSpearStormDamage(int lvl) { return Mathf.RoundToInt((float)SpearStormDamage(lvl) * TalentSystem.Mult(LP, "la_stormforce", 1.4f) * TalentSystem.DamageMult(LP, "pierce")); } private static int PounceDamage(int lvl) { return Progression.DmgInt(18, lvl); } private static float PounceRange() { return 8f + 2f * (float)TalentSystem.Rank(LP, "wh_pouncerange"); } private static int AdjPounceDamage(int lvl) { return Mathf.RoundToInt((float)PounceDamage(lvl) * TalentSystem.Mult(LP, "wh_pounceforce", 1.4f) * TalentSystem.DamageMult(LP, "pierce")); } private static int RapidThrowDamage(int lvl) { return Progression.DmgInt(11, lvl); } private static int RapidThrowCount() { return 4 + TalentSystem.Rank(LP, "wh_rapidcount"); } private static int AdjRapidThrowDamage(int lvl) { return Mathf.RoundToInt((float)RapidThrowDamage(lvl) * TalentSystem.Mult(LP, "wh_rapidforce", 1.5f) * TalentSystem.DamageMult(LP, "pierce")); } private static int WildHuntPercent() { return 25 + 5 * TalentSystem.Rank(LP, "wh_huntforce"); } private static float WildHuntDuration() { return 15f + 3f * (float)TalentSystem.Rank(LP, "wh_huntlong"); } private static float DrainRadius() { return 6f + (float)TalentSystem.Rank(LP, "rea_drainwide") + (TalentSystem.Has(LP, "rea_notable") ? 2f : 0f); } private static int AdjDrainDamage(int lvl) { return Mathf.RoundToInt((float)DrainDamage(lvl) * TalentSystem.Mult(LP, "sp_drainforce", 1.3f) * TalentSystem.DamageMult(LP, "spirit")); } private static int AdjDrainHeal(int lvl) { return Mathf.RoundToInt((float)DrainHeal(lvl) * TalentSystem.Mult(LP, "sp_drainheal", 1.45f) * TalentSystem.Mult(LP, "rea_drainheal", 1.45f)); } private static int AdjOozeDamage(int lvl) { return Mathf.RoundToInt((float)OozeDamage(lvl) * TalentSystem.Mult(LP, "pl_bombforce", 1.2f) * TalentSystem.Mult(LP, "bli_bombforce", 1.4f) * TalentSystem.DamageMult(LP, "poison")); } private static int ToxicWaves() { return 6 + TalentSystem.Rank(LP, "pes_cloudwaves") + (TalentSystem.Has(LP, "pes_notable") ? 1 : 0); } private static float ToxicRadius() { return 6f + (float)TalentSystem.Rank(LP, "pes_cloudwide"); } private static int AdjToxicTick(int lvl) { return Mathf.RoundToInt((float)ToxicTickDamage(lvl) * TalentSystem.Mult(LP, "pes_cloudforce", 1.4f) * TalentSystem.Mult(LP, "bli_cloudforce", 1.4f) * TalentSystem.DamageMult(LP, "poison")); } private static int AdjSpectralDamage(int lvl) { return Mathf.RoundToInt((float)SpectralDamage(lvl) * TalentSystem.Mult(LP, "rea_waveforce", 1.4f) * TalentSystem.Mult(LP, "ban_waveforce", 1.4f) * TalentSystem.DamageMult(LP, "spirit")); } private static float SpectralWaveRadius() { return 8f + (float)TalentSystem.Rank(LP, "ban_wavewide"); } private static float BoneArmorDuration() { return 20f + ((TalentSystem.Has(LP, "rea_bonelong") || TalentSystem.Has(LP, "bl_bonelong") || TalentSystem.Has(LP, "dk_bonelong")) ? 10f : 0f); } private static int PutridBombs() { return 8 + TalentSystem.Rank(LP, "bli_rainbombs"); } private static int AdjPutridDamage(int lvl) { return Mathf.RoundToInt((float)OozeDamage(lvl) * TalentSystem.Mult(LP, "pes_rainforce", 1.5f) * TalentSystem.Mult(LP, "bli_rainforce", 1.4f) * TalentSystem.DamageMult(LP, "poison")); } private static int PlagueNovaDamage(int lvl) { return Progression.DmgInt(16, lvl); } private static float PlagueNovaRadius() { return 6f + (float)TalentSystem.Rank(LP, "pes_novawide"); } private static int AdjPlagueNovaDamage(int lvl) { return Mathf.RoundToInt((float)PlagueNovaDamage(lvl) * TalentSystem.Mult(LP, "pes_novaforce", 1.5f) * TalentSystem.DamageMult(LP, "poison")); } private static float PandemicTickDamage(int lvl) { return Progression.Dmg(6f, lvl); } private static float PandemicRadius() { return 8f + (float)TalentSystem.Rank(LP, "pes_panwide"); } private static float PandemicDuration() { return 12f + (TalentSystem.Has(LP, "pes_panlong") ? 5f : 0f); } private static int AdjPandemicTick(int lvl) { return Mathf.RoundToInt(PandemicTickDamage(lvl) * TalentSystem.Mult(LP, "pes_panforce", 1.4f) * TalentSystem.DamageMult(LP, "poison")); } private static int PlagueBoltDamage(int lvl) { return Progression.DmgInt(18, lvl); } private static int PlagueBoltPierce() { return 1 + TalentSystem.Rank(LP, "bli_boltpierce"); } private static int AdjPlagueBoltDamage(int lvl) { return Mathf.RoundToInt((float)PlagueBoltDamage(lvl) * TalentSystem.Mult(LP, "bli_boltforce", 1.4f) * TalentSystem.DamageMult(LP, "poison")); } private static float CorrodeTickDamage(int lvl) { return Progression.Dmg(6f, lvl); } private static float CorrodeDuration() { return 5f + 2f * (float)TalentSystem.Rank(LP, "bli_corrodelong"); } private static int AdjCorrodeDamage(int lvl) { return Mathf.RoundToInt(CorrodeTickDamage(lvl) * CorrodeDuration() * TalentSystem.Mult(LP, "bli_corrodeforce", 1.5f) * (TalentSystem.Has(LP, "bli_venomlord") ? 1.3f : 1f) * TalentSystem.DamageMult(LP, "poison")); } private static int SoulRipDamage(int lvl) { return Progression.DmgInt(18, lvl); } private static int SoulRipHeal(int lvl) { return Mathf.RoundToInt(Progression.Heal(8f, lvl) * (1f + 0.2f * (float)TalentSystem.Rank(LP, "rea_ripheal"))); } private static int AdjSoulRipDamage(int lvl) { return Mathf.RoundToInt((float)SoulRipDamage(lvl) * TalentSystem.Mult(LP, "rea_ripforce", 1.5f) * TalentSystem.DamageMult(LP, "spirit")); } private static int DeathCoilDamage(int lvl) { return Progression.DmgInt(24, lvl); } private static float DeathCoilRadius() { return 8f; } private static int AdjDeathCoilDamage(int lvl) { return Mathf.RoundToInt((float)DeathCoilDamage(lvl) * TalentSystem.Mult(LP, "rea_coilforce", 1.4f) * TalentSystem.DamageMult(LP, "spirit")); } private static int WailDamage(int lvl) { return Progression.DmgInt(14, lvl); } private static float WailRadius() { return 8f; } private static int AdjWailDamage(int lvl) { return Mathf.RoundToInt((float)WailDamage(lvl) * TalentSystem.Mult(LP, "ban_wailforce", 1.5f) * TalentSystem.DamageMult(LP, "spirit")); } private static int SpiritNovaDamage(int lvl) { return Progression.DmgInt(16, lvl); } private static float SpiritNovaRadius() { return 6f + (float)TalentSystem.Rank(LP, "ban_novawide"); } private static int AdjSpiritNovaDamage(int lvl) { return Mathf.RoundToInt((float)SpiritNovaDamage(lvl) * TalentSystem.Mult(LP, "ban_novaforce", 1.5f) * TalentSystem.DamageMult(LP, "spirit")); } private static int SpectralStormDamage(int lvl) { return Progression.DmgInt(15, lvl); } private static int SpectralStormCount() { return 10 + (TalentSystem.Has(LP, "ban_stormcount") ? 4 : 0); } private static float SpectralStormRadius() { return 6f + (float)TalentSystem.Rank(LP, "ban_stormwide"); } private static int AdjSpectralStormDamage(int lvl) { return Mathf.RoundToInt((float)SpectralStormDamage(lvl) * TalentSystem.Mult(LP, "ban_stormforce", 1.4f) * TalentSystem.DamageMult(LP, "spirit")); } private static int ArmyCount() { return 4 + TalentSystem.Rank(LP, "bl_endless"); } private static float PactDuration() { return 15f; } private static int PactBonusPercent() { return 20 + 5 * TalentSystem.Rank(LP, "dk_pactfury"); } private static int RaiseHordeCount() { return 3 + TalentSystem.Rank(LP, "bl_hordeforce"); } private static int BoneStormDamage(int lvl) { return Progression.DmgInt(12, lvl); } private static int BoneStormWaves() { return 5; } private static float BoneStormRadius() { return 6f + (float)TalentSystem.Rank(LP, "bl_stormwide"); } private static int AdjBoneStormDamage(int lvl) { return Mathf.RoundToInt((float)BoneStormDamage(lvl) * TalentSystem.Mult(LP, "bl_stormforce", 1.4f)); } private static int DeathPactDamage(int lvl) { return Progression.DmgInt(22, lvl); } private static float DeathPactRadius() { return 8f + (float)TalentSystem.Rank(LP, "dk_pactwide"); } private static int AdjDeathPactDamage(int lvl) { return Mathf.RoundToInt((float)DeathPactDamage(lvl) * TalentSystem.Mult(LP, "dk_pactforce", 1.4f) * TalentSystem.DamageMult(LP, "spirit")); } private static float NecroBoneMinionMult(Player player) { return (1f + 0.05f * (float)TalentSystem.Rank(player, "bn_mastery") + (TalentSystem.Has(player, "bn_notable") ? 0.1f : 0f)) * (1f + 0.03f * (float)TalentSystem.Rank(player, "bl_command") + 0.03f * (float)TalentSystem.Rank(player, "bl_might") + (TalentSystem.Has(player, "bl_notable") ? 0.1f : 0f)) * (TalentSystem.Has(player, "bl_capstone") ? 1.2f : 1f) * (1f + 0.03f * (float)TalentSystem.Rank(player, "dk_might") + 0.04f * (float)TalentSystem.Rank(player, "dk_elite") + (TalentSystem.Has(player, "dk_notable") ? 0.1f : 0f)) * (TalentSystem.Has(player, "dk_capstone") ? 1.2f : 1f); } private static float WolfMult() { return (1f + 0.04f * (float)TalentSystem.Rank(LP, "ws_wild")) * (TalentSystem.Has(LP, "ws_notable") ? 1.1f : 1f) * (TalentSystem.Has(LP, "ww_notable") ? 1.1f : 1f) * (TalentSystem.Has(LP, "ww_capstone") ? 1.2f : 1f); } private static float BearMult() { return (1f + 0.04f * (float)TalentSystem.Rank(LP, "ws_wild")) * (TalentSystem.Has(LP, "ws_notable") ? 1.1f : 1f) * (TalentSystem.Has(LP, "wb_notable") ? 1.1f : 1f) * (TalentSystem.Has(LP, "wb_capstone") ? 1.2f : 1f); } private static int SavagePounceDamage(int lvl) { return Progression.DmgInt(20, lvl); } private static float SavagePounceRange() { return 6f + 2f * (float)TalentSystem.Rank(LP, "ww_pouncefar"); } private static int AdjSavagePounceDamage(int lvl) { return Mathf.RoundToInt((float)SavagePounceDamage(lvl) * WolfMult() * TalentSystem.Mult(LP, "ww_pounceforce", 1.5f)); } private static int SavageRendHit(int lvl) { return Progression.DmgInt(16, lvl); } private static int AdjSavageRendHit(int lvl) { return Mathf.RoundToInt((float)SavageRendHit(lvl) * WolfMult() * TalentSystem.Mult(LP, "ww_rendforce", 1.5f)); } private static float RendTickDamage(int lvl) { return Progression.Dmg(6f, lvl); } private static int RendTicks() { return 4 + TalentSystem.Rank(LP, "ww_rendlong"); } private static int AdjRendTick(int lvl) { return Mathf.RoundToInt(RendTickDamage(lvl) * WolfMult() * TalentSystem.Mult(LP, "ww_rendforce", 1.5f)); } private static int BloodMoonAttack() { return 15 + 5 * TalentSystem.Rank(LP, "ww_moonforce"); } private static float BloodMoonDuration() { return 15f + 3f * (float)TalentSystem.Rank(LP, "ww_moonlong"); } private static int MaulDamage(int lvl) { return Progression.DmgInt(24, lvl); } private static float MaulRadius() { return 4f + (float)TalentSystem.Rank(LP, "wb_maulwide"); } private static int AdjMaulDamage(int lvl) { return Mathf.RoundToInt((float)MaulDamage(lvl) * BearMult() * TalentSystem.Mult(LP, "wb_maulforce", 1.5f)); } private static int RoarDamage(int lvl) { return Progression.DmgInt(14, lvl); } private static float RoarRadius() { return 6f + (float)TalentSystem.Rank(LP, "wb_roarwide"); } private static int AdjRoarDamage(int lvl) { return Mathf.RoundToInt((float)RoarDamage(lvl) * BearMult() * TalentSystem.Mult(LP, "wb_roarforce", 1.5f)); } private static int FeralChargeDamage(int lvl) { return Progression.DmgInt(26, lvl); } private static float FeralChargeRange() { return 10f + 2f * (float)TalentSystem.Rank(LP, "wb_rampfar"); } private static int AdjFeralChargeDamage(int lvl) { return Mathf.RoundToInt((float)FeralChargeDamage(lvl) * BearMult() * TalentSystem.Mult(LP, "wb_rampforce", 1.4f)); } private static float BuffDurationMult() { return 1f + 0.05f * (float)TalentSystem.Rank(LP, "wd_wisdom") + 0.03f * (float)TalentSystem.Rank(LP, "sk_voice") + (TalentSystem.Has(LP, "wd_notable") ? 0.15f : 0f) + (TalentSystem.Has(LP, "sk_notable") ? 0.1f : 0f); } private static int WardenBuffBonus() { return (TalentSystem.Has(LP, "wd_notable") ? 15 : 0) + (TalentSystem.Has(LP, "sk_notable") ? 10 : 0) + (TalentSystem.Has(LP, "sk_capstone") ? 20 : 0); } private static int NatureFuryAttack() { return 15 + 3 * TalentSystem.Rank(LP, "sk_furyforce") + WardenBuffBonus(); } private static float WarSongRadius() { return BlessingRadius() + (float)TalentSystem.Rank(LP, "sk_warwide"); } private static int WarSongAttack() { return 10 + 2 * TalentSystem.Rank(LP, "sk_warforce") + WardenBuffBonus(); } private static int WarSongArmor() { return 15 + 3 * TalentSystem.Rank(LP, "sk_warforce"); } private static float WarSongDuration() { return (20f + (TalentSystem.Has(LP, "sk_warlong") ? 8f : 0f)) * BuffDurationMult(); } private static int MaxCompanions() { Player lP = LP; if ((Object)(object)lP == (Object)null) { return 2; } return 2 + (TalentSystem.Has(lP, "bm_notable") ? 1 : 0) + TalentSystem.Rank(lP, "bm_wolfcount") + (TalentSystem.Has(lP, "bm_capstone") ? 1 : 0); } private static float CompanionBaseDmgMult(Player p) { return (1f + 0.04f * (float)TalentSystem.Rank(p, "bm_kinship") + 0.04f * (float)TalentSystem.Rank(p, "bm_might") + (TalentSystem.Has(p, "bm_notable") ? 0.1f : 0f)) * (TalentSystem.Has(p, "bm_capstone") ? 1.2f : 1f); } private static float CompanionHpMult(Player p) { return 1f + 0.1f * (float)TalentSystem.Rank(p, "bm_beasthp"); } private static int WildPackCount() { return 3 + TalentSystem.Rank(LP, "bm_callcount"); } private static int TranquilityBurst(int lvl) { return Progression.HealInt(20, lvl); } private static float TranquilityRadius() { return BlessingRadius(); } private static float TranquilityDuration() { return 8f * BuffDurationMult(); } private static int AdjTranquilityBurst(int lvl) { return Mathf.RoundToInt((float)TranquilityBurst(lvl) * (1f + 0.1f * (float)TalentSystem.Rank(LP, "lif_tranforce")) * TalentSystem.HealMult(LP)); } private static int AdjTranquilityTick(int lvl) { return Mathf.Max(1, Mathf.RoundToInt(Progression.Heal(6f, lvl) * (1f + 0.1f * (float)TalentSystem.Rank(LP, "lif_tranforce")) * TalentSystem.HealMult(LP))); } private static float BarkwardRadius() { return BlessingRadius() + (float)TalentSystem.Rank(LP, "gk_barkwide"); } private static int BarkwardArmor() { return 20 + 5 * TalentSystem.Rank(LP, "gk_barkforce"); } private static float BarkwardDuration() { return 20f * BuffDurationMult(); } public static IEnumerable GetUnlockedAt(Player player, int level) { return from s in GetSpells(player) where s.UnlockLevel == level select s.Name; } public static float GetCooldownRemaining(string spellName) { if (!CooldownEnd.TryGetValue(spellName, out var value)) { return 0f; } return Mathf.Max(0f, value - Time.time); } public static void ClearCooldowns() { CooldownEnd.Clear(); } public static Dictionary SnapshotCooldowns() { return new Dictionary(CooldownEnd); } public static void RestoreCooldowns(Dictionary snapshot) { CooldownEnd.Clear(); if (snapshot == null) { return; } foreach (KeyValuePair item in snapshot) { CooldownEnd[item.Key] = item.Value; } } public static bool IsUnlocked(Player player, SpellDef spell) { if (!TrainingHall.IsTraining(player)) { return ClassTrialSystem.IsAbilityUnlocked(player, spell); } return true; } public static void CastSpell(Player player, int index) { SpellDef[] spells = GetSpells(player); if (index < 0 || index >= spells.Length) { return; } SpellDef spellDef = spells[index]; if (ShapeshiftSystem.IsFlying(player) && spellDef.Name != DruidRavenForm.Name) { ShapeshiftSystem.NotifyRavenCombatBlocked(player); return; } bool flag = TrainingHall.IsTraining(player); int level = (flag ? TrainingHall.PreviewCastLevel(player, spellDef) : ClassSystem.GetLevel(player)); if (!IsUnlocked(player, spellDef)) { ((Character)player).Message((MessageType)1, spellDef.Name + ": " + ClassTrialSystem.UnlockRequirement(player, spellDef), 0, (Sprite)null); return; } float cooldownRemaining = GetCooldownRemaining(spellDef.Name); if (cooldownRemaining > 0f) { ((Character)player).Message((MessageType)1, $"{spellDef.Name} on cooldown ({cooldownRemaining:0}s)", 0, (Sprite)null); return; } if (!flag) { if (!MagicProgression.CanCastWithEquipment(player, spellDef, out var requirement)) { ((Character)player).Message((MessageType)1, requirement, 0, (Sprite)null); return; } AbilityResource resource = ResourceFor(player, spellDef); float amount = ResourceCostOf(player, spellDef); if (!MagicProgression.HasResource(player, resource, amount)) { ((Character)player).Message((MessageType)1, "Not enough " + MagicProgression.ResourceName(resource), 0, (Sprite)null); return; } } if (spellDef.CastTime > 0f) { if (IsChanneling) { ((Character)player).Message((MessageType)1, "Already casting " + ChannelSpellName + "...", 0, (Sprite)null); } else { ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(ChannelCast(player, spellDef, level)); } } else { Resolve(player, spellDef, level); } } public static AbilityResource ResourceFor(Player player, SpellDef spell) { if (TrainingHall.IsTraining(player)) { return MagicProgression.ResourceFor(TrainingHall.CurrentClass, TrainingHall.CurrentBranch); } return MagicProgression.ResourceFor(player); } public static float ResourceCostOf(Player player, SpellDef spell) { if (spell.Name == "Challenge" && TalentSystem.Has(player, "blw_capstone")) { return 0f; } return spell.StaminaCost * TalentSystem.StaminaCostMultiplier(player) * AscendantStaminaMultiplier(player, spell); } private static void Resolve(Player player, SpellDef spell, int level) { if (!TrainingHall.IsTraining(player)) { AbilityResource resource = ResourceFor(player, spell); MagicProgression.UseResource(player, resource, ResourceCostOf(player, spell)); } spell.CastAction(player, level); float num = (spell.Cooldown - TalentSystem.FlatCooldownReduction(player, spell.Name)) * TalentSystem.CooldownMultiplier(player); CooldownEnd[spell.Name] = Time.time + Mathf.Max(1f, num); } private static IEnumerator ChannelCast(Player player, SpellDef spell, int level) { IsChanneling = true; ChannelSpellName = spell.Name; ChannelProgress = 0f; bool interrupted = false; Action onDamaged = delegate(float damage, Character attacker) { if (damage > 0f) { interrupted = true; } }; Effects.TryCastAnimation(player, "gpower"); Vector3 startPos = ((Component)player).transform.position; ((Character)player).m_onDamaged = (Action)Delegate.Combine(((Character)player).m_onDamaged, onDamaged); try { float elapsed = 0f; while (elapsed < spell.CastTime) { if ((Object)(object)player == (Object)null || ((Character)player).IsDead() || ((Character)player).IsStaggering() || Vector3.Distance(((Component)player).transform.position, startPos) > 0.4f) { interrupted = true; break; } elapsed += Time.deltaTime; ChannelProgress = elapsed / spell.CastTime; yield return null; } } finally { if ((Object)(object)player != (Object)null) { ((Character)player).m_onDamaged = (Action)Delegate.Remove(((Character)player).m_onDamaged, onDamaged); } IsChanneling = false; } if (interrupted) { if ((Object)(object)player != (Object)null && !((Character)player).IsDead()) { ((Character)player).Message((MessageType)2, spell.Name + " interrupted!", 0, (Sprite)null); } yield break; } if (!TrainingHall.IsTraining(player)) { if (!MagicProgression.CanCastWithEquipment(player, spell, out var requirement)) { ((Character)player).Message((MessageType)1, requirement, 0, (Sprite)null); yield break; } AbilityResource resource = ResourceFor(player, spell); if (!MagicProgression.HasResource(player, resource, ResourceCostOf(player, spell))) { ((Character)player).Message((MessageType)1, "Not enough " + MagicProgression.ResourceName(resource), 0, (Sprite)null); yield break; } } Resolve(player, spell, level); } private static void CastFireball(Player player, int level) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "throw_bomb", "throw", "spear_throw", "staff_fireball0", "gpower"); HitData val = new HitData(); val.m_damage.m_fire = (float)FireballDamage(level) * TalentSystem.Mult(player, "dst_burn", 1.2f); val.m_pushForce = 40f; val.SetAttacker((Character)(object)player); LaunchProjectile(player, "Imp_fireball_projectile", AimDirection(player), 25f, val); Effects.TryPlayAt(EyePosition(player), "sfx_imp_fireball_launch"); } private static void CastFrostNova(Player player, int level) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) float num = FrostNovaRadius(); Effects.TryCastAnimation(player, "gpower"); int num2 = DamageEnemiesAround(player, ((Component)player).transform.position, num, delegate(HitData hit) { hit.m_damage.m_frost = (float)FrostNovaDamage(level) * TalentSystem.Mult(player, "mg_frostbite", 1.4f); }, 80f, new string[1] { "fx_iceshard_hit" }); Effects.TryPlayAtScaled(((Component)player).transform.position, num / 8f, 15f, "fx_fenring_icenova"); ((Character)player).Message((MessageType)1, (num2 > 0) ? $"Frost Nova ({num:0} m): {num2} enemies hit" : $"Frost Nova ({num:0} m): no enemies in range", 0, (Sprite)null); } private static void CastIceShards(Player player, int level) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Expected O, but got Unknown //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "staff_fireball1", "gpower"); Vector3 val = AimDirection(player); float[] array = ((IceShardCount() != 7) ? new float[5] { -20f, -10f, 0f, 10f, 20f } : new float[7] { -30f, -20f, -10f, 0f, 10f, 20f, 30f }); for (int i = 0; i < array.Length; i++) { Vector3 dir = Quaternion.AngleAxis(array[i], Vector3.up) * val; HitData val2 = new HitData(); val2.m_damage.m_frost = (float)IceShardDamage(level) * TalentSystem.Mult(player, "dst_shards", 1.2f); val2.m_pushForce = 20f; val2.SetAttacker((Character)(object)player); LaunchProjectile(player, "staff_iceshard_projectile", dir, 30f, val2); } Effects.TryPlayAt(EyePosition(player), "fx_iceshard_launch"); } private static void CastLightningBolt(Player player, int level) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "staff_lightningshot", "gpower"); HitData val = new HitData(); val.m_damage.m_lightning = (float)LightningBoltDamage(level) * TalentSystem.Mult(player, "mage_stormlance", 1.3f) * TalentSystem.Mult(player, "dst_boltmastery", 1.2f); val.m_pushForce = 60f; val.SetAttacker((Character)(object)player); LaunchProjectile(player, "staff_lightning_projectile", AimDirection(player), 35f, val); Effects.TryPlayAt(EyePosition(player), "vfx_lightningstaff_fire"); } private static void CastRingOfFire(Player player, int level) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "gpower"); int num = TalentSystem.Rank(player, "pyr_cauterize"); if (num > 0) { ((Character)player).Heal(Progression.Heal(4f, level) * (float)num, true); Effects.TryPlayAt(((Component)player).transform.position, "vfx_Potion_health_medium"); } int num2 = RingCount(); Vector3 val = AimForward(player); for (int i = 0; i < num2; i++) { Vector3 dir = Quaternion.AngleAxis((float)i * 360f / (float)num2, Vector3.up) * val; HitData val2 = new HitData(); val2.m_damage.m_fire = (float)RingFireDamage(level) * TalentSystem.Mult(player, "mage_blazing", 1.32f); val2.m_pushForce = 40f; val2.SetAttacker((Character)(object)player); LaunchProjectile(player, "Imp_fireball_projectile", dir, 20f, val2); } Effects.TryPlayAt(((Component)player).transform.position, "sfx_imp_fireball_launch"); } private static void CastRuneShield(Player player, int level) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) float radius = DomeRadius(); float duration = DomeDuration(); Effects.TryCastAnimation(player, "staff_shield", "gpower"); if (TalentSystem.Has(player, "mage_secondwind")) { ((Character)player).Heal(Progression.Heal(7f, level), true); } Vector3 position = ((Component)player).transform.position; Network.BroadcastDome(position, radius, duration, 0); CreateDomeAt(player, position, radius, duration, 0); Effects.TryPlayAt(position, 4f, "fx_StaffShield_Hit"); } public static void CreateDomeAt(Player localPlayer, Vector3 center, float radius, float duration, int style) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) Color color = ((style == 1) ? new Color(1f, 0.85f, 0.45f, 0.16f) : new Color(0.45f, 0.75f, 1f, 0.16f)); GameObject val = new GameObject("cdv_rune_dome"); val.transform.position = center; RuneDome runeDome = val.AddComponent(); runeDome.Owner = localPlayer; runeDome.Radius = radius; runeDome.EndTime = Time.time + duration; runeDome.ShieldEffectName = ((style == 1) ? "SE_CDV_Muro" : "SE_CDV_Scudo"); GameObject val2 = Effects.FindPrefab("vfx_StaffShield"); if ((Object)(object)val2 != (Object)null) { GameObject val3 = Effects.InstantiateLocal(val2, center, Quaternion.identity, val.transform); MonoBehaviour[] componentsInChildren = val3.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); } val3.transform.localScale = Vector3.one * (radius * 0.7f); } CreateDomeShell(val, radius, color, mirrored: false); CreateDomeShell(val, radius, color, mirrored: true); } private static void CreateDomeShell(GameObject parent, float radius, Color color, bool mirrored) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Expected O, but got Unknown //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Expected O, but got Unknown //IL_00fd: Unknown result type (might be due to invalid IL or missing references) GameObject obj = GameObject.CreatePrimitive((PrimitiveType)0); Object.DestroyImmediate((Object)(object)obj.GetComponent()); ((Object)obj).name = (mirrored ? "cdv_dome_inner" : "cdv_dome_outer"); obj.transform.SetParent(parent.transform, false); obj.transform.localPosition = Vector3.zero; float num = radius * 2f; obj.transform.localScale = (mirrored ? new Vector3(0f - num, num, num) : new Vector3(num, num, num)); MeshRenderer component = obj.GetComponent(); ((Renderer)component).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)component).receiveShadows = false; Shader val = Shader.Find("Sprites/Default"); Material val2; if ((Object)(object)val != (Object)null) { val2 = new Material(val); } else { val2 = new Material(Shader.Find("Standard")); val2.SetFloat("_Mode", 3f); val2.SetInt("_SrcBlend", 5); val2.SetInt("_DstBlend", 10); val2.SetInt("_ZWrite", 0); val2.EnableKeyword("_ALPHABLEND_ON"); val2.renderQueue = 3000; } val2.color = color; ((Renderer)component).material = val2; } private static void CastLightningStorm(Player player, int level) { Effects.TryCastAnimation(player, "staff_summon", "gpower"); ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(LightningStorm(player, level)); } private static IEnumerator LightningStorm(Player player, int level) { int bolts = StormBolts(); for (int i = 0; i < bolts; i++) { if ((Object)(object)player == (Object)null) { break; } if (((Character)player).IsDead()) { break; } List list = EnemiesAround(((Component)player).transform.position, 12f); Vector3 point; if (list.Count > 0) { point = ((Component)list[Random.Range(0, list.Count)]).transform.position; } else { Vector2 val = Random.insideUnitCircle * 8f; point = ((Component)player).transform.position + new Vector3(val.x, 0f, val.y); } SpawnLightningBolt(player, point, (float)StormBoltDamage(level) * TalentSystem.Mult(player, "dst_overcharge", 1.4f), 3f * TalentSystem.Mult(player, "mage_widenova", 1.25f)); yield return (object)new WaitForSeconds(0.5f); } } private static void SpawnLightningBolt(Player player, Vector3 point, float damage, float radius) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) GameObject val = Effects.FindPrefab("lightningAOE"); if ((Object)(object)val != (Object)null) { GameObject val2 = Effects.InstantiateLocal(val, point, Quaternion.identity); Aoe[] componentsInChildren = val2.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); } Object.Destroy((Object)(object)val2, 4f); } Effects.TryPlayAt(point, 6f, "sfx_thunder"); DamageEnemiesAround(player, point, radius, delegate(HitData hit) { hit.m_damage.m_lightning = damage; }, 60f, null); } private static void CastWrathOfTheGods(Player player, int level) { Effects.TryCastAnimation(player, "gpower"); ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(MeteorRain(player, level)); } private static IEnumerator MeteorRain(Player player, int level) { Vector3 center = ((Component)player).transform.position + AimForward(player) * 8f; Effects.TryPlayAt(((Component)player).transform.position, "sfx_fader_meteor_start"); int meteors = MeteorCount(); float spread = 6f + 2f * (float)TalentSystem.Rank(player, "pyr_scorchedearth"); for (int i = 0; i < meteors; i++) { if ((Object)(object)player == (Object)null) { break; } if (((Character)player).IsDead()) { break; } Vector2 val = Random.insideUnitCircle * spread; Vector3 val2 = center + new Vector3(val.x, 0f, val.y); Vector2 val3 = Random.insideUnitCircle * 3f; Vector3 val4 = val2 + new Vector3(val3.x, 22f, val3.y); Vector3 val5 = val2 - val4; Vector3 normalized = ((Vector3)(ref val5)).normalized; HitData val6 = new HitData(); val6.m_damage.m_fire = (float)MeteorDamage(level) * TalentSystem.Mult(player, "mage_cataclysm", 1.4f) * TalentSystem.Mult(player, "dst_pyre", 1.2f); val6.m_damage.m_blunt = Progression.Dmg(2.5f, level); val6.m_pushForce = 100f; val6.SetAttacker((Character)(object)player); TalentSystem.ApplyDamageTalents(player, val6); GameObject val7 = Effects.FindPrefab("projectile_meteor", "projectile_meteor_fader"); if ((Object)(object)val7 != (Object)null) { SetupProjectile(Object.Instantiate(val7, val4, Quaternion.LookRotation(normalized)), player, normalized * 28f, val6); } yield return (object)new WaitForSeconds(0.35f); } } private static void CastFlameWave(Player player, int level) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "staff_fireball1", "gpower"); Vector3 val = AimDirection(player); float[] array = new float[5] { -30f, -15f, 0f, 15f, 30f }; for (int i = 0; i < array.Length; i++) { Vector3 dir = Quaternion.AngleAxis(array[i], Vector3.up) * val; HitData val2 = new HitData(); val2.m_damage.m_fire = (float)FlameWaveDamage(level) * TalentSystem.Mult(player, "pyr_waverider", 1.5f); val2.m_pushForce = 30f; val2.SetAttacker((Character)(object)player); LaunchProjectile(player, "Imp_fireball_projectile", dir, 18f, val2); } Effects.TryPlayAt(EyePosition(player), "sfx_imp_fireball_launch"); } private static void CastPillarOfFlame(Player player, int level) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "staff_fireball0", "gpower"); Vector3 val = ((Component)player).transform.position + AimForward(player) * 8f; List list = (from e in EnemiesAround(val, 8f) orderby Vector3.Distance(((Component)e).transform.position, ((Component)player).transform.position) select e).ToList(); Vector3 target = ((list.Count > 0) ? ((Component)list[0]).transform.position : val); DropPillarMeteor(player, target, level); if (TalentSystem.Has(player, "pyr_twinpillar") && list.Count > 1) { DropPillarMeteor(player, ((Component)list[1]).transform.position, level); } Effects.TryPlayAt(((Component)player).transform.position, "sfx_fader_meteor_start"); } private static void DropPillarMeteor(Player player, Vector3 target, int level) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) Vector2 val = Random.insideUnitCircle * 1.5f; Vector3 val2 = target + new Vector3(val.x, 22f, val.y); Vector3 val3 = target - val2; Vector3 normalized = ((Vector3)(ref val3)).normalized; HitData val4 = new HitData(); val4.m_damage.m_fire = (float)PillarDamage(level) * TalentSystem.Mult(player, "pyr_pillarforce", 1.5f); val4.m_damage.m_blunt = Progression.Dmg(2.5f, level); val4.m_pushForce = 100f; val4.SetAttacker((Character)(object)player); TalentSystem.ApplyDamageTalents(player, val4); GameObject val5 = Effects.FindPrefab("projectile_meteor", "projectile_meteor_fader"); if ((Object)(object)val5 != (Object)null) { SetupProjectile(Object.Instantiate(val5, val2, Quaternion.LookRotation(normalized)), player, normalized * 30f, val4); } } private static void CastSummonFireImp(Player player, int level) { Effects.TryCastAnimation(player, "staff_summon", "gpower"); Character val = SpawnFireImp(player); if (!((Object)(object)val == (Object)null)) { FireMinions.RemoveAll((Character m) => (Object)(object)m == (Object)null || m.IsDead()); FireMinions.Add(val); int num = FireImpCap(); while (FireMinions.Count > num) { DespawnMinion(FireMinions[0]); FireMinions.RemoveAt(0); } } } private static Character SpawnFireImp(Player player) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) Vector2 insideUnitCircle = Random.insideUnitCircle; Vector2 val = ((Vector2)(ref insideUnitCircle)).normalized * 2f; Vector3 position = ((Component)player).transform.position + new Vector3(val.x, 0.2f, val.y); Character val2 = SpawnMinion(player, "Surtling", position); if ((Object)(object)val2 != (Object)null) { Effects.TryPlayAt(position, "fx_summon_skeleton_spawn", "fx_summon_skeleton"); Effects.TryPlayAt(position, "sfx_imp_fireball_launch"); } return val2; } private static void CastBurningGround(Player player, int level) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "gpower"); Vector3 position = ((Component)player).transform.position + AimForward(player) * 5f; float radius = BurningGroundRadius(); float duration = BurningGroundDuration(); float amountPerTick = BurningTick(level) * TalentSystem.Mult(player, "smn_searingground", 1.32f) * TalentSystem.DamageMult(player, "fire"); SanctuaryZone.CreateAt(position, radius, duration, amountPerTick, 2); Network.BroadcastGround(position, radius, duration, amountPerTick, 2); Effects.TryPlayAt(position, "sfx_imp_fireball_launch"); if (!TalentSystem.Has(player, "smn_emberpact")) { return; } FireMinions.RemoveAll((Character m) => (Object)(object)m == (Object)null || m.IsDead()); MagmaMinions.RemoveAll((Character m) => (Object)(object)m == (Object)null || m.IsDead()); FireArmy.RemoveAll((Character m) => (Object)(object)m == (Object)null || m.IsDead()); foreach (Character item in FireMinions.Concat(MagmaMinions).Concat(FireArmy).ToList()) { item.Heal(item.GetMaxHealth() * 0.25f, true); Effects.TryPlayAt(((Component)item).transform.position, "vfx_Potion_health_medium"); } } private static void CastSummonMagmaElemental(Player player, int level) { //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "staff_trollsummon", "staff_summon", "gpower"); MagmaMinions.RemoveAll((Character m) => (Object)(object)m == (Object)null || m.IsDead()); foreach (Character item in MagmaMinions.ToList()) { DespawnMinion(item); } MagmaMinions.Clear(); GameObject val = Effects.FindPrefab(MagmaPrefabNames); if ((Object)(object)val == (Object)null) { ((Character)player).Message((MessageType)1, "The summon fails... (prefab not found)", 0, (Sprite)null); return; } Vector2 insideUnitCircle = Random.insideUnitCircle; Vector2 val2 = ((Vector2)(ref insideUnitCircle)).normalized * 2.5f; Vector3 position = ((Component)player).transform.position + new Vector3(val2.x, 0.2f, val2.y); Character val3 = SpawnMinion(player, ((Object)val).name, position); if (!((Object)(object)val3 == (Object)null)) { float dmgMult = 1.6f * (1f + 0.1f * (float)(TalentSystem.Rank(player, "smn_magmaborn") + TalentSystem.Rank(player, "smn_moltencore"))) * (TalentSystem.Has(player, "smn_capstone") ? 1.5f : 1f); float hpMult = 1.8f * (1f + 0.1f * (float)TalentSystem.Rank(player, "smn_magmaborn")); BoostMinion(val3, dmgMult, hpMult); MagmaMinions.Add(val3); Effects.TryPlayAt(position, "fx_summon_start", "fx_summon_skeleton_spawn"); } } private static void CastLegionOfCinders(Player player, int level) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "staff_summon", "gpower"); Effects.TryPlayAt(((Component)player).transform.position, "fx_summon_start"); ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(CinderLegion(player)); } private static IEnumerator CinderLegion(Player player) { FireArmy.RemoveAll((Character m) => (Object)(object)m == (Object)null || m.IsDead()); foreach (Character item in FireArmy.ToList()) { DespawnMinion(item); } FireArmy.Clear(); int count = LegionCount(); for (int i = 0; i < count; i++) { if ((Object)(object)player == (Object)null) { break; } if (((Character)player).IsDead()) { break; } Character val = SpawnFireImp(player); if ((Object)(object)val != (Object)null) { ZNetView component = ((Component)val).GetComponent(); if ((Object)(object)component != (Object)null && component.IsValid()) { ZDO zDO = component.GetZDO(); zDO.Set("cdv_army", 1); if ((Object)(object)ZNet.instance != (Object)null) { zDO.Set("cdv_army_born", (long)ZNet.instance.GetTimeSeconds()); } } FireArmy.Add(val); } yield return (object)new WaitForSeconds(0.4f); } } private static void CastGlacialSpike(Player player, int level) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "staff_fireball1", "gpower"); HitData val = new HitData(); val.m_damage.m_frost = (float)GlacialSpikeDamage(level) * TalentSystem.Mult(player, "cry_spikeforce", 1.4f); val.m_pushForce = 60f; val.SetAttacker((Character)(object)player); GameObject val2 = LaunchProjectile(player, "staff_iceshard_projectile", AimDirection(player), 40f, val); if ((Object)(object)val2 != (Object)null) { Transform transform = val2.transform; transform.localScale *= 2f; AddProjectileGlow(val2, new Color(0.6f, 0.85f, 1f)); } Effects.TryPlayAt(EyePosition(player), "fx_iceshard_launch"); } private static void CastBlizzard(Player player, int level) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "staff_summon", "gpower"); Vector3 center = ((Component)player).transform.position + AimForward(player) * 8f; ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(Blizzard(player, center, level)); } private static IEnumerator Blizzard(Player player, Vector3 center, int level) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) float radius = BlizzardRadius(); for (int i = 0; i < 8; i++) { if ((Object)(object)player == (Object)null) { break; } if (((Character)player).IsDead()) { break; } DamageEnemiesAround(player, center, radius, delegate(HitData hit) { hit.m_damage.m_frost = BlizzardTickDamage(level) * TalentSystem.Mult(player, "cry_blizzforce", 1.5f); }, 10f, new string[1] { "fx_iceshard_hit" }); if (i % 2 == 0) { Effects.TryPlayAtScaled(center, radius / 8f, 12f, "fx_fenring_icenova"); } yield return (object)new WaitForSeconds(1f); } } private static void CastAbsoluteZero(Player player, int level) { //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "gpower"); float mult = TalentSystem.Mult(player, "cry_zeroforce", 1.4f) * (TalentSystem.Has(player, "cry_zero") ? 1.25f : 1f); float pushForce = (TalentSystem.Has(player, "cry_zero") ? 240f : 120f); int num = DamageEnemiesAround(player, ((Component)player).transform.position, 10f, delegate(HitData hit) { hit.m_damage.m_frost = (float)AbsoluteZeroDamage(level) * mult; }, pushForce, new string[1] { "fx_iceshard_hit" }); Effects.TryPlayAtScaled(((Component)player).transform.position, 1.25f, 20f, "fx_fenring_icenova"); ((Character)player).Message((MessageType)1, (num > 0) ? $"Absolute Zero: {num} enemies frozen" : "Absolute Zero: no enemies in range", 0, (Sprite)null); } private static void CastFrostArmor(Player player, int level) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "gpower"); PassiveEffects.ApplyTimedEffect(player, "SE_CDV_Brina", FrostArmorDuration()); Effects.TryPlayAt(((Component)player).transform.position, "fx_StaffShield_Hit"); Effects.TryPlayAt(((Component)player).transform.position, "fx_iceshard_hit"); } private static void CastWintersGrasp(Player player, int level) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "gpower"); Vector3 position = ((Component)player).transform.position + AimForward(player) * 5f; float radius = GraspRadius(); float amountPerTick = GraspTickDamage(level) * TalentSystem.Mult(player, "fw_graspforce", 1.5f) * TalentSystem.DamageMult(player, "frost"); SanctuaryZone.CreateAt(position, radius, 8f, amountPerTick, 3); Network.BroadcastGround(position, radius, 8f, amountPerTick, 3); Effects.TryPlayAt(position, "fx_iceshard_launch"); } private static void CastFimbulwinter(Player player, int level) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "staff_shield", "gpower"); Vector3 position = ((Component)player).transform.position; float num = FimbulRadius(); Network.BroadcastDome(position, num, 20f, 0); CreateDomeAt(player, position, num, 20f, 0); int num2 = DamageEnemiesAround(player, position, num, delegate(HitData hit) { hit.m_damage.m_frost = (float)FimbulBlastDamage(level) * TalentSystem.Mult(player, "fw_fimbulforce", 1.5f); }, 100f, new string[1] { "fx_iceshard_hit" }); Effects.TryPlayAtScaled(position, num / 8f, 20f, "fx_fenring_icenova"); ((Character)player).Message((MessageType)1, (num2 > 0) ? $"Fimbulwinter: {num2} enemies caught in the great winter" : "Fimbulwinter: the great winter rises", 0, (Sprite)null); } private static void CastChainLightning(Player player, int level) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Expected O, but got Unknown //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "staff_lightningshot", "gpower"); Vector3 val = AimDirection(player); Character val2 = (from e in EnemiesAround(((Component)player).transform.position + val * 8f, 10f).Concat(EnemiesAround(((Component)player).transform.position, 6f)) orderby Vector3.Distance(((Component)e).transform.position, ((Component)player).transform.position) select e).FirstOrDefault(); if ((Object)(object)val2 == (Object)null) { ((Character)player).Message((MessageType)1, "Chain Lightning: no enemies in range", 0, (Sprite)null); return; } Effects.TryPlayAt(EyePosition(player), "vfx_lightningstaff_fire"); Effects.TryPlayAt(((Component)val2).transform.position, 6f, "sfx_thunder"); List visited = new List(); Character val3 = val2; float num = (float)ChainDamage(level) * TalentSystem.Mult(player, "st_chainforce", 1.4f); int num2 = ChainJumps(); for (int num3 = 0; num3 <= num2; num3++) { if (!((Object)(object)val3 != (Object)null)) { break; } HitData val4 = new HitData(); val4.m_damage.m_lightning = num; TalentSystem.ApplyDamageTalents(player, val4); val4.m_pushForce = 40f; val4.m_point = ((Component)val3).transform.position; val4.SetAttacker((Character)(object)player); val3.Damage(val4); Effects.TryPlayAt(((Component)val3).transform.position + Vector3.up, "vfx_lightningstaff_fire", "vfx_HitSparks"); visited.Add(val3); num *= 0.85f; Vector3 from = ((Component)val3).transform.position; val3 = (from e in EnemiesAround(@from, 8f) where !visited.Contains(e) orderby Vector3.Distance(((Component)e).transform.position, @from) select e).FirstOrDefault(); } ((Character)player).Message((MessageType)1, $"Chain Lightning: {visited.Count} enemies struck", 0, (Sprite)null); } private static void CastStaticField(Player player, int level) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "gpower"); Vector3 position = ((Component)player).transform.position + AimForward(player) * 5f; float radius = FieldRadius(); float amountPerTick = FieldTickDamage(level) * TalentSystem.Mult(player, "st_fieldforce", 1.5f) * TalentSystem.DamageMult(player, "lightning"); SanctuaryZone.CreateAt(position, radius, FieldDuration(), amountPerTick, 4); Network.BroadcastGround(position, radius, FieldDuration(), amountPerTick, 4); Effects.TryPlayAt(position, "vfx_lightningstaff_fire"); } private static void CastWrathOfThor(Player player, int level) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "gpower"); Effects.TryPlayAt(((Component)player).transform.position, 8f, "sfx_thunder"); ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(WrathOfThor(player, level)); } private static IEnumerator WrathOfThor(Player player, int level) { for (int i = 0; i < 12; i++) { if ((Object)(object)player == (Object)null) { break; } if (((Character)player).IsDead()) { break; } List list = EnemiesAround(((Component)player).transform.position, 15f); Vector3 point; if (list.Count > 0) { point = ((Component)list[Random.Range(0, list.Count)]).transform.position; } else { Vector2 val = Random.insideUnitCircle * 10f; point = ((Component)player).transform.position + new Vector3(val.x, 0f, val.y); } SpawnLightningBolt(player, point, (float)ThorBoltDamage(level) * TalentSystem.Mult(player, "st_wrathforce", 1.4f), 4f); yield return (object)new WaitForSeconds(0.4f); } } private static void CastBlink(Player player, int level) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) Vector3 val = AimForward(player); val.y = 0f; ((Vector3)(ref val)).Normalize(); float num = BlinkDistance(); Vector3 val2 = ((Component)player).transform.position + Vector3.up * 1f; int mask = LayerMask.GetMask(new string[4] { "Default", "static_solid", "piece", "terrain" }); RaycastHit val3 = default(RaycastHit); if (Physics.Raycast(val2, val, ref val3, num, mask)) { num = Mathf.Max(1.5f, ((RaycastHit)(ref val3)).distance - 1f); } Effects.TryPlayAt(((Component)player).transform.position, "vfx_odin_despawn"); Vector3 val4 = ((Component)player).transform.position + val * num; if ((Object)(object)ZoneSystem.instance != (Object)null) { float groundHeight = ZoneSystem.instance.GetGroundHeight(val4); if (Mathf.Abs(groundHeight - val4.y) < 8f) { val4.y = groundHeight + 0.3f; } } ((Component)player).transform.position = val4; if ((Object)(object)((Character)player).m_body != (Object)null) { ((Character)player).m_body.position = val4; } ((Character)player).m_maxAirAltitude = val4.y; Effects.TryPlayAt(val4, "vfx_odin_despawn"); Effects.TryPlayAt(val4, "vfx_lightningstaff_fire"); if (TalentSystem.Has(player, "tm_slipstream")) { PassiveEffects.ApplyTimedEffect(player, "SE_CDV_Inno", 5f); } } private static void CastStormShroud(Player player, int level) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "gpower"); PassiveEffects.ApplyTimedEffect(player, "SE_CDV_Scariche", ShroudDuration()); Effects.TryPlayAt(((Component)player).transform.position, "vfx_lightningstaff_fire"); Effects.TryPlayAt(((Component)player).transform.position, "fx_StaffShield_Hit"); } private static void CastBallLightning(Player player, int level) { Effects.TryCastAnimation(player, "staff_lightningshot", "gpower"); ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(BallLightning(player, level)); } private static IEnumerator BallLightning(Player player, int level) { Vector3 dir = AimDirection(player); dir.y = 0f; ((Vector3)(ref dir)).Normalize(); GameObject orb = new GameObject("cdv_ball_lightning"); orb.transform.position = ((Component)player).transform.position + dir * 1.5f + Vector3.up * 1.5f; GameObject obj = GameObject.CreatePrimitive((PrimitiveType)0); Object.DestroyImmediate((Object)(object)obj.GetComponent()); obj.transform.SetParent(orb.transform, false); obj.transform.localScale = Vector3.one * 0.6f; MeshRenderer component = obj.GetComponent(); ((Renderer)component).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)component).receiveShadows = false; Shader val = Shader.Find("Sprites/Default"); Material val2 = (((Object)(object)val != (Object)null) ? new Material(val) : new Material(Shader.Find("Standard"))); val2.color = new Color(1f, 0.95f, 0.5f, 0.9f); ((Renderer)component).material = val2; Light obj2 = orb.AddComponent(); obj2.type = (LightType)2; obj2.color = new Color(1f, 0.95f, 0.5f); obj2.range = 8f; obj2.intensity = 2.5f; obj2.shadows = (LightShadows)0; float duration = BallDuration(); float elapsed = 0f; float nextZap = 0f; while (elapsed < duration && (Object)(object)player != (Object)null && !((Character)player).IsDead()) { elapsed += Time.deltaTime; Vector3 val3 = orb.transform.position + dir * (4f * Time.deltaTime); if ((Object)(object)ZoneSystem.instance != (Object)null) { val3.y = ZoneSystem.instance.GetGroundHeight(val3) + 1.5f; } orb.transform.position = val3; if (elapsed >= nextZap) { nextZap = elapsed + 0.5f; DamageEnemiesAround(player, val3, 4f, delegate(HitData hit) { hit.m_damage.m_lightning = BallTickDamage(level) * TalentSystem.Mult(player, "tm_ballforce", 1.4f); }, 20f, new string[1] { "vfx_HitSparks" }); } yield return null; } Object.Destroy((Object)(object)orb); } private static void CastEyeOfTheStorm(Player player, int level) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "staff_summon", "gpower"); Effects.TryPlayAt(((Component)player).transform.position, 8f, "sfx_thunder"); ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(EyeOfTheStorm(player, level)); } private static IEnumerator EyeOfTheStorm(Player player, int level) { float elapsed = 0f; while (elapsed < 10f && !((Object)(object)player == (Object)null) && !((Character)player).IsDead()) { List list = EnemiesAround(((Component)player).transform.position, EyeRadius()); if (list.Count > 0) { Vector3 position = ((Component)list[Random.Range(0, list.Count)]).transform.position; SpawnLightningBolt(player, position, (float)EyeBoltDamage(level) * TalentSystem.Mult(player, "tm_eyeforce", 1.4f), 3f); } elapsed += 0.9f; yield return (object)new WaitForSeconds(0.9f); } } private static void CastWarCry(Player player, int level) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) float radius = WarCryRadius(); Effects.TryCastAnimation(player, "emote_challenge", "challenge", "gpower"); int num = DamageEnemiesAround(player, ((Component)player).transform.position, radius, delegate(HitData hit) { hit.m_damage.m_blunt = (float)WarCryDamage(level) * TalentSystem.Mult(player, "jug_warforce", 1.4f) * TalentSystem.Mult(player, "ea_warforce", 1.4f); }, 150f, new string[1] { "vfx_clubhit" }); Effects.TryPlayAt(((Component)player).transform.position, 4f, "fx_eikthyr_stomp"); ((Character)player).Message((MessageType)1, (num > 0) ? $"War Cry: {num} enemies repelled" : "War Cry: no enemies in range", 0, (Sprite)null); } private static void CastCharge(Player player, int level) { Effects.TryCastAnimation(player, "sword_secondary", "unarmed_kick"); ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(ChargeDash(player, level)); } private static IEnumerator ChargeDash(Player player, int level) { Vector3 dir = AimForward(player); dir.y = 0f; dir = ((Vector3)(ref dir)).normalized; HashSet alreadyHit = new HashSet(); float end = Time.time + 0.5f * (TalentSystem.Has(player, "ra_chargelong") ? 1.5f : 1f); float damageMult = ChargeDamageMult(player); bool pierce = ChargeIsPierce(player); bool first = true; while (Time.time < end && (Object)(object)player != (Object)null && !((Character)player).IsDead()) { yield return (object)new WaitForFixedUpdate(); if ((Object)(object)player == (Object)null || ((Character)player).IsDead()) { yield break; } Vector3 linearVelocity = dir * 16f; linearVelocity.y = (first ? 3f : ((Character)player).m_body.linearVelocity.y); ((Character)player).m_body.linearVelocity = linearVelocity; ((Character)player).m_body.MovePosition(((Character)player).m_body.position + dir * 16f * Time.fixedDeltaTime); ((Character)player).m_maxAirAltitude = ((Component)player).transform.position.y; first = false; foreach (Character item in EnemiesAround(((Component)player).transform.position, 2.5f)) { if (alreadyHit.Add(item)) { HitData val = new HitData(); if (pierce) { val.m_damage.m_pierce = (float)ChargeDamage(level) * damageMult; } else { val.m_damage.m_slash = (float)ChargeDamage(level) * damageMult; } val.m_pushForce = 90f; val.m_point = ((Component)item).transform.position; val.m_dir = dir; val.SetAttacker((Character)(object)player); TalentSystem.ApplyDamageTalents(player, val); item.Damage(val); Effects.TryPlayAt(((Component)item).transform.position + Vector3.up, "vfx_HitSparks"); } } } if ((Object)(object)player == (Object)null || ((Character)player).IsDead()) { yield break; } Effects.TryCastAnimation(player, "sword_secondary", "unarmed_kick"); Vector3 center = ((Component)player).transform.position + dir * 1.5f; int num = DamageEnemiesAround(player, center, 2.5f, delegate(HitData hit) { if (pierce) { hit.m_damage.m_pierce = (float)ChargeDamage(level) * 1.5f * damageMult; } else { hit.m_damage.m_slash = (float)ChargeDamage(level) * 1.5f * damageMult; } }, 120f, new string[1] { "vfx_clubhit" }); if (num > 0) { ((Character)player).Message((MessageType)1, $"Charge: finishing blow on {num} enemies", 0, (Sprite)null); } } private static void CastSpearThrow(Player player, int level) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_0066: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "spear_throw", "throw", "swing_longsword0"); HitData val = new HitData(); val.m_damage.m_pierce = (float)SpearDamage(level) * TalentSystem.Mult(player, "hu_throw", 1.2f); val.m_pushForce = 60f; val.SetAttacker((Character)(object)player); LaunchProjectile(player, "ancientbarkspear_projectile", AimDirection(player), 32f, val, "bronzespear_projectile"); } private static void CastSeismicBlow(Player player, int level) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) float radius = SeismicRadius(); Effects.TryCastAnimation(player, "swing_sledge", "battleaxe_attack0", "gpower"); float stagger = 1f + 0.5f * (float)TalentSystem.Rank(player, "ea_stagger"); int num = DamageEnemiesAround(player, ((Component)player).transform.position, radius, delegate(HitData hit) { hit.m_damage.m_blunt = (float)SeismicDamage(level) * TalentSystem.Mult(player, "ea_seisforce", 1.4f); hit.m_staggerMultiplier = stagger; }, 100f, new string[1] { "vfx_clubhit" }); Effects.TryPlayAt(((Component)player).transform.position, "vfx_gdking_stomp"); Effects.TryPlayAt(((Component)player).transform.position, "sfx_gdking_stomp"); ((Character)player).Message((MessageType)1, (num > 0) ? $"Seismic Blow: {num} enemies hit" : "Seismic Blow: no enemies in range", 0, (Sprite)null); } private static void CastFury(Player player, int level) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "emote_roar", "roar", "emote_challenge"); PassiveEffects.ApplyTimedEffect(player, "SE_CDV_Furia", FuryDuration()); Effects.TryPlayAt(((Component)player).transform.position, "sfx_trollfire_roar"); } private static void CastIronSkin(Player player, int level) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "emote_flex", "flex", "gpower"); PassiveEffects.ApplyTimedEffect(player, "SE_CDV_Ferro", IronSkinDuration()); if (TalentSystem.Has(player, "jug_ironwill")) { ((Character)player).Heal(Progression.Heal(10f, level), true); } Effects.TryPlayAt(((Component)player).transform.position, "fx_StaffShield_Hit"); } private static void CastWhirlwind(Player player, int level) { ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(Whirlwind(player, level, WhirlTicks(), WhirlRadius(), "rv_whirlforce", WhirlwindDamage(level), 0f, "Whirlwind")); } private static void CastBloodbath(Player player, int level) { float healPerHit = Progression.Heal(3f, level) * (1f + 0.5f * (float)TalentSystem.Rank(player, "rv_bathheal")); ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(Whirlwind(player, level, BloodbathTicks(), BloodbathRadius(), "rv_bathforce", BloodbathDamage(level), healPerHit, "Bloodbath")); } private static IEnumerator Whirlwind(Player player, int level, int ticks, float radius, string dmgId, int baseDmg, float healPerHit, string name) { for (int i = 0; i < ticks; i++) { if ((Object)(object)player == (Object)null) { break; } if (((Character)player).IsDead()) { break; } Effects.TryCastAnimation(player, "atgeir_secondary", "battleaxe_attack0", "swing_longsword0", "swing_axe0", "atgeir_attack0", "sword_secondary", "unarmed_attack0"); int num = DamageEnemiesAround(player, ((Component)player).transform.position, radius, delegate(HitData hit) { hit.m_damage.m_slash = (float)baseDmg * TalentSystem.Mult(player, dmgId, 1.4f); }, 40f, new string[1] { "vfx_HitSparks" }); float num2 = healPerHit; if (TalentSystem.Has(player, "rv_bloodwhirl")) { num2 += Progression.Heal(1.5f, level); } if (num > 0 && num2 > 0f) { ((Character)player).Heal(num2 * (float)num, true); } yield return (object)new WaitForSeconds(0.5f); } } private static void CastTitanicSlam(Player player, int level) { ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(SlamCore(player, level, TalentSystem.Mult(player, "jug_slamforce", 1.4f), aftershock: false, "Titanic Slam", SlamDamage(level))); } private static void CastCataclysm(Player player, int level) { ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(SlamCore(player, level, TalentSystem.Mult(player, "ea_cataforce", 1.4f), aftershock: true, "Cataclysm", CataclysmDamage(level))); } private static IEnumerator SlamCore(Player player, int level, float damageMult, bool aftershock, string name, int baseDmg) { float launchEnd = Time.time + 0.25f; while (Time.time < launchEnd && (Object)(object)player != (Object)null && !((Character)player).IsDead()) { yield return (object)new WaitForFixedUpdate(); if ((Object)(object)player == (Object)null || ((Character)player).IsDead()) { yield break; } ((Character)player).m_body.linearVelocity = AimForward(player) * 6f + Vector3.up * 14f; ((Character)player).m_maxAirAltitude = ((Component)player).transform.position.y; } yield return (object)new WaitForSeconds(0.15f); float timeout = Time.time + 3f; while (Time.time < timeout && (Object)(object)player != (Object)null && !((Character)player).IsDead() && !((Character)player).IsOnGround()) { ((Character)player).m_maxAirAltitude = ((Component)player).transform.position.y; yield return null; } if (!((Object)(object)player == (Object)null) && !((Character)player).IsDead()) { ((Character)player).m_maxAirAltitude = ((Component)player).transform.position.y; float radius = SlamRadius(); float slamDamage = (float)baseDmg * damageMult; int num = DamageEnemiesAround(player, ((Component)player).transform.position, radius, delegate(HitData hit) { hit.m_damage.m_blunt = slamDamage; }, 150f, new string[1] { "vfx_clubhit" }); Effects.TryPlayAt(((Component)player).transform.position, "fx_fader_meteor_hit"); Effects.TryPlayAt(((Component)player).transform.position, "vfx_gdking_stomp"); Effects.TryPlayAt(((Component)player).transform.position, "sfx_gdking_stomp"); if (aftershock) { float num2 = (TalentSystem.Has(player, "ea_aftershock") ? 0.75f : 0.5f); ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(Aftershock(player, ((Component)player).transform.position, radius, slamDamage * num2)); } ((Character)player).Message((MessageType)1, (num > 0) ? $"{name}: {num} enemies hit" : (name + "!"), 0, (Sprite)null); } } private static void CastCrushingBlow(Player player, int level) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "swing_sledge", "battleaxe_attack0", "swing_longsword0", "gpower"); Vector3 val = ((Component)player).transform.position + AimForward(player) * 2.5f; float stagger = 1.5f + 0.5f * (float)TalentSystem.Rank(player, "cr_stagger"); int num = DamageEnemiesAround(player, val, CrushingBlowRadius(), delegate(HitData hit) { hit.m_damage.m_blunt = (float)CrushingBlowDamage(level) * TalentSystem.Mult(player, "cr_force", 1.5f); hit.m_staggerMultiplier = stagger; }, 60f, new string[1] { "vfx_clubhit" }); Effects.TryPlayAt(val, "vfx_gdking_stomp"); if (num == 0) { ((Character)player).Message((MessageType)1, "Crushing Blow: no enemies in range", 0, (Sprite)null); } } private static void CastCleave(Player player, int level) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "swing_axe0", "battleaxe_attack0", "swing_longsword0", "gpower"); Vector3 val = ((Component)player).transform.position + AimForward(player) * 2.5f; int num = TalentSystem.Rank(player, "re_bleed"); int num2 = DamageEnemiesAround(player, val, CleaveRadius(), delegate(HitData h) { h.m_damage.m_slash = (float)CleaveDamage(level) * TalentSystem.Mult(player, "re_force", 1.5f); }, 30f, new string[1] { "vfx_HitSparks" }); Effects.TryPlayAt(val, "vfx_clubhit"); if (num > 0) { foreach (Character item in EnemiesAround(val, CleaveRadius())) { ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(BleedTarget(player, item, (float)CleaveDamage(level) * 0.3f, num)); } } if (num2 == 0) { ((Character)player).Message((MessageType)1, "Cleave: no enemies in range", 0, (Sprite)null); } } private static void CastFaultLine(Player player, int level) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "swing_sledge", "battleaxe_attack0", "gpower"); Vector3 val = AimForward(player); val.y = 0f; val = ((Vector3)(ref val)).normalized; float num = FaultLineLength(); float stagger = 2f + 0.5f * (float)TalentSystem.Rank(player, "ea_stagger"); int num2 = 0; for (float num3 = 2f; num3 <= num; num3 += 2.5f) { Vector3 val2 = ((Component)player).transform.position + val * num3; num2 += DamageEnemiesAround(player, val2, 3f, delegate(HitData hit) { hit.m_damage.m_blunt = (float)FaultLineDamage(level) * TalentSystem.Mult(player, "ea_faultforce", 1.5f); hit.m_staggerMultiplier = stagger; }, 80f, new string[1] { "vfx_clubhit" }); Effects.TryPlayAt(val2, "vfx_gdking_stomp"); } ((Character)player).Message((MessageType)1, (num2 > 0) ? $"Fault Line: {num2} enemies torn" : "Fault Line: no enemies caught", 0, (Sprite)null); } private static void CastRupture(Player player, int level) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "swing_axe0", "knife_secondary", "swing_longsword0", "gpower"); Vector3 val = ((Component)player).transform.position + AimForward(player) * 2f; int ticks = Mathf.RoundToInt(RuptureBleedDuration()); int num = DamageEnemiesAround(player, val, 3f, delegate(HitData h) { h.m_damage.m_slash = (float)RuptureDamage(level) * TalentSystem.Mult(player, "rv_ruptforce", 1.5f); }, 20f, new string[1] { "vfx_HitSparks" }); foreach (Character item in EnemiesAround(val, 3f)) { ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(BleedTarget(player, item, (float)RuptureDamage(level) * 0.4f, ticks)); } Effects.TryPlayAt(val, "vfx_HitSparks"); ((Character)player).Message((MessageType)1, (num > 0) ? $"Rend: {num} enemies bleeding" : "Rend: no enemies in range", 0, (Sprite)null); } private static IEnumerator BleedTarget(Player player, Character target, float perTick, int ticks) { for (int i = 0; i < ticks; i++) { yield return (object)new WaitForSeconds(1f); if ((Object)(object)player == (Object)null || (Object)(object)target == (Object)null || target.IsDead()) { break; } HitData val = new HitData(); val.m_damage.m_slash = perTick; TalentSystem.ApplyDamageTalents(player, val); val.m_point = ((Component)target).transform.position; val.SetAttacker((Character)(object)player); target.Damage(val); Effects.TryPlayAt(((Component)target).transform.position + Vector3.up, "vfx_blood_hit"); } } private static void CastExecute(Player player, int level) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Expected O, but got Unknown //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "battleaxe_attack0", "swing_axe0", "swing_longsword0", "gpower"); Vector3 val = AimDirection(player); Character val2 = (from e in EnemiesAround(((Component)player).transform.position + val * 3f, 4f).Concat(EnemiesAround(((Component)player).transform.position, 3f)) orderby Vector3.Distance(((Component)e).transform.position, ((Component)player).transform.position) select e).FirstOrDefault(); if ((Object)(object)val2 == (Object)null) { ((Character)player).Message((MessageType)1, "Execute: no enemy ahead", 0, (Sprite)null); return; } float num = 1f - Mathf.Clamp01(val2.GetHealth() / Mathf.Max(1f, val2.GetMaxHealth())); float num2 = 1f + (float)ExecuteBonusPercent() / 100f * num; HitData val3 = new HitData(); val3.m_damage.m_slash = (float)ExecuteDamage(level) * TalentSystem.Mult(player, "ra_execforce", 1.5f) * num2; val3.m_pushForce = 40f; val3.m_point = ((Component)val2).transform.position; val3.SetAttacker((Character)(object)player); TalentSystem.ApplyDamageTalents(player, val3); bool flag = !val2.IsDead(); val2.Damage(val3); Effects.TryPlayAt(((Component)val2).transform.position + Vector3.up, "vfx_clubhit", "vfx_HitSparks"); if (flag && val2.IsDead() && TalentSystem.Has(player, "ra_finisher")) { CooldownEnd["Execute"] = 0f; ((Character)player).Message((MessageType)1, "Execute: killing blow — cooldown refunded!", 0, (Sprite)null); } else { ((Character)player).Message((MessageType)1, $"Execute: {Mathf.RoundToInt(num2 * 100f - 100f)}% bonus", 0, (Sprite)null); } } private static void CastRampage(Player player, int level) { ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(Rampage(player, level)); } private static IEnumerator Rampage(Player player, int level) { int hits = RampageHits(); for (int i = 0; i < hits; i++) { if ((Object)(object)player == (Object)null) { break; } if (((Character)player).IsDead()) { break; } Vector3 val = AimDirection(player); Character val2 = (from e in EnemiesAround(((Component)player).transform.position + val * 2.5f, 4f).Concat(EnemiesAround(((Component)player).transform.position, 3f)) orderby Vector3.Distance(((Component)e).transform.position, ((Component)player).transform.position) select e).FirstOrDefault(); Effects.TryCastAnimation(player, "swing_longsword0", "swing_axe0", "sword_secondary", "unarmed_attack0"); if ((Object)(object)val2 != (Object)null) { HitData val3 = new HitData(); val3.m_damage.m_slash = (float)RampageDamage(level) * TalentSystem.Mult(player, "ra_rampforce", 1.4f); val3.m_pushForce = 20f; val3.m_point = ((Component)val2).transform.position; val3.SetAttacker((Character)(object)player); TalentSystem.ApplyDamageTalents(player, val3); val2.Damage(val3); Effects.TryPlayAt(((Component)val2).transform.position + Vector3.up, "vfx_HitSparks"); } yield return (object)new WaitForSeconds(0.2f); } } private static void CastSpearBarrage(Player player, int level) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown //IL_00b3: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "spear_throw", "throw", "swing_longsword0"); Vector3 val = AimDirection(player); int num = SpearVolleyCount(); float num2 = 40f; for (int i = 0; i < num; i++) { float num3 = ((num > 1) ? ((float)i / (float)(num - 1)) : 0.5f); Vector3 dir = Quaternion.AngleAxis(Mathf.Lerp(0f - num2, num2, num3), Vector3.up) * val; HitData val2 = new HitData(); val2.m_damage.m_pierce = (float)SpearVolleyDamage(level) * TalentSystem.Mult(player, "la_volleyforce", 1.5f); val2.m_pushForce = 30f; val2.SetAttacker((Character)(object)player); LaunchProjectile(player, "ancientbarkspear_projectile", dir, 32f, val2, "bronzespear_projectile"); } Effects.TryPlayAt(EyePosition(player), "vfx_spear_hit"); } private static void CastImpale(Player player, int level) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "spear_throw", "swing_sledge", "gpower"); Vector3 val = AimForward(player); val.y = 0f; val = ((Vector3)(ref val)).normalized; bool flag = TalentSystem.Has(player, "la_impalepull"); int num = 0; for (float num2 = 2f; num2 <= 12f; num2 += 2.5f) { foreach (Character item in EnemiesAround(((Component)player).transform.position + val * num2, 2.5f)) { HitData val2 = new HitData(); val2.m_damage.m_pierce = (float)ImpaleDamage(level) * TalentSystem.Mult(player, "la_impaleforce", 1.5f); val2.m_point = ((Component)item).transform.position; if (flag) { Vector3 val3 = ((Component)player).transform.position - ((Component)item).transform.position; val2.m_dir = ((Vector3)(ref val3)).normalized; val2.m_pushForce = 60f; } else { val2.m_dir = val; val2.m_pushForce = 20f; } val2.SetAttacker((Character)(object)player); TalentSystem.ApplyDamageTalents(player, val2); item.Damage(val2); Effects.TryPlayAt(((Component)item).transform.position + Vector3.up, "vfx_spear_hit", "vfx_HitSparks"); num++; } } ((Character)player).Message((MessageType)1, (num > 0) ? $"Impale: {num} enemies run through" : "Impale: no enemies ahead", 0, (Sprite)null); } private static void CastSpearStorm(Player player, int level) { Effects.TryCastAnimation(player, "spear_throw", "gpower"); ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(SpearStorm(player, level)); } private static IEnumerator SpearStorm(Player player, int level) { Vector3 center = ((Component)player).transform.position + AimForward(player) * 8f; int count = SpearStormCount(); float radius = SpearStormRadius(); for (int i = 0; i < count; i++) { if ((Object)(object)player == (Object)null) { break; } if (((Character)player).IsDead()) { break; } Vector2 val = Random.insideUnitCircle * radius; Vector3 val2 = center + new Vector3(val.x, 0f, val.y); Vector3 val3 = val2 + new Vector3(0f, 20f, 0f); Vector3 val4 = val2 - val3; Vector3 normalized = ((Vector3)(ref val4)).normalized; HitData val5 = new HitData(); val5.m_damage.m_pierce = (float)SpearStormDamage(level) * TalentSystem.Mult(player, "la_stormforce", 1.4f); val5.m_pushForce = 30f; val5.SetAttacker((Character)(object)player); TalentSystem.ApplyDamageTalents(player, val5); GameObject val6 = Effects.FindPrefab("ancientbarkspear_projectile", "bronzespear_projectile"); if ((Object)(object)val6 != (Object)null) { SetupProjectile(Object.Instantiate(val6, val3, Quaternion.LookRotation(normalized)), player, normalized * 30f, val5); } yield return (object)new WaitForSeconds(0.15f); } } private static void CastPounce(Player player, int level) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) Character val = (from e in EnemiesAround(((Component)player).transform.position, PounceRange()) orderby Vector3.Distance(((Component)e).transform.position, ((Component)player).transform.position) select e).FirstOrDefault(); if ((Object)(object)val == (Object)null) { ((Character)player).Message((MessageType)1, "Pounce: no enemy in range", 0, (Sprite)null); return; } Effects.TryCastAnimation(player, "unarmed_kick", "sword_secondary"); ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(Pounce(player, level, val)); } private static IEnumerator Pounce(Player player, int level, Character target) { float end = Time.time + 0.5f; while (Time.time < end && (Object)(object)player != (Object)null && !((Character)player).IsDead() && (Object)(object)target != (Object)null && !target.IsDead()) { yield return (object)new WaitForFixedUpdate(); if ((Object)(object)player == (Object)null || ((Character)player).IsDead() || (Object)(object)target == (Object)null) { break; } Vector3 val = ((Component)target).transform.position - ((Component)player).transform.position; val.y = 0f; Vector3 normalized = ((Vector3)(ref val)).normalized; Vector3 linearVelocity = normalized * 18f + Vector3.up * 4f; ((Character)player).m_body.linearVelocity = linearVelocity; ((Character)player).m_body.MovePosition(((Character)player).m_body.position + normalized * 18f * Time.fixedDeltaTime); ((Character)player).m_maxAirAltitude = ((Component)player).transform.position.y; if (((Vector3)(ref val)).magnitude < 2.5f) { break; } } if (!((Object)(object)player == (Object)null) && !((Character)player).IsDead()) { ((Character)player).m_maxAirAltitude = ((Component)player).transform.position.y; int num = DamageEnemiesAround(player, ((Component)player).transform.position, 3f, delegate(HitData hit) { hit.m_damage.m_pierce = (float)PounceDamage(level) * TalentSystem.Mult(player, "wh_pounceforce", 1.4f); }, 40f, new string[2] { "vfx_spear_hit", "vfx_HitSparks" }); Effects.TryPlayAt(((Component)player).transform.position, "vfx_gdking_stomp"); if (num == 0) { ((Character)player).Message((MessageType)1, "Pounce: missed", 0, (Sprite)null); } } } private static void CastRapidThrow(Player player, int level) { ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(RapidThrow(player, level)); } private static IEnumerator RapidThrow(Player player, int level) { int count = RapidThrowCount(); for (int i = 0; i < count; i++) { if ((Object)(object)player == (Object)null) { break; } if (((Character)player).IsDead()) { break; } Effects.TryCastAnimation(player, "spear_throw", "throw"); HitData val = new HitData(); val.m_damage.m_pierce = (float)RapidThrowDamage(level) * TalentSystem.Mult(player, "wh_rapidforce", 1.5f); val.m_pushForce = 25f; val.SetAttacker((Character)(object)player); LaunchProjectile(player, "ancientbarkspear_projectile", AimDirection(player), 34f, val, "bronzespear_projectile"); yield return (object)new WaitForSeconds(0.15f); } } private static void CastWildHunt(Player player, int level) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "emote_roar", "roar", "emote_challenge"); PassiveEffects.ApplyTimedEffect(player, "SE_CDV_Caccia", WildHuntDuration()); Effects.TryPlayAt(((Component)player).transform.position, "sfx_wolf_howl", "sfx_trollfire_roar"); } private static void CastSpearOfTheGods(Player player, int level) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "spear_throw", "throw_bomb"); HitData val = new HitData(); val.m_damage.m_pierce = (float)GodSpearPierce(level) * TalentSystem.Mult(player, "einh_heavypoint", 1.3f) * TalentSystem.Mult(player, "stc_sharpspears", 1.3f); val.m_damage.m_lightning = GodSpearLightning(level); val.m_pushForce = 60f; val.SetAttacker((Character)(object)player); AddProjectileGlow(LaunchProjectile(player, "GoblinSpear_projectile", AimDirection(player), 34f, val, "ancientbarkspear_projectile", "bronzespear_projectile"), new Color(1f, 0.9f, 0.55f)); Effects.TryPlayAt(EyePosition(player), "vfx_lightningstaff_fire"); } private static void CastSkyDive(Player player, int level) { ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(SkyDive(player, level)); } private static IEnumerator SkyDive(Player player, int level) { Vector3 dir = AimForward(player); dir.y = 0f; dir = ((Vector3)(ref dir)).normalized; float speed = 12f * TalentSystem.Mult(player, "einh_longflight", 1.5f) * (1f + 0.1f * (float)(TalentSystem.Rank(player, "thu_divefar") + TalentSystem.Rank(player, "spm_divefar") + TalentSystem.Rank(player, "vk_divefar"))); float launchEnd = Time.time + 0.25f; while (Time.time < launchEnd && (Object)(object)player != (Object)null && !((Character)player).IsDead()) { yield return (object)new WaitForFixedUpdate(); if ((Object)(object)player == (Object)null || ((Character)player).IsDead()) { yield break; } ((Character)player).m_body.linearVelocity = dir * speed + Vector3.up * 9f; ((Character)player).m_maxAirAltitude = ((Component)player).transform.position.y; } yield return (object)new WaitForSeconds(0.15f); float timeout = Time.time + 3f; while (Time.time < timeout && (Object)(object)player != (Object)null && !((Character)player).IsDead() && !((Character)player).IsOnGround()) { ((Character)player).m_maxAirAltitude = ((Component)player).transform.position.y; yield return null; } if (!((Object)(object)player == (Object)null) && !((Character)player).IsDead()) { ((Character)player).m_maxAirAltitude = ((Component)player).transform.position.y; int num = DamageEnemiesAround(player, ((Component)player).transform.position, SkyDiveRadius(), delegate(HitData hit) { hit.m_damage.m_blunt = (float)SkyDiveDamage(level) * TalentSystem.Mult(player, "einh_crashdive", 1.4f) * TalentSystem.Mult(player, "stc_skyhunter", 1.3f) * TalentSystem.Mult(player, "thu_diveforce", 1.4f) * TalentSystem.Mult(player, "spm_diveforce", 1.4f) * TalentSystem.Mult(player, "vk_diveforce", 1.4f); }, 100f, new string[1] { "vfx_HitSparks" }); Effects.TryPlayAt(((Component)player).transform.position, "vfx_gdking_stomp"); Effects.TryPlayAt(((Component)player).transform.position, "sfx_gdking_stomp"); if (TalentSystem.Has(player, "vk_capstone")) { PassiveEffects.ApplyTimedEffect(player, "SE_CDV_Blessing", BlessingDuration()); } if (num > 0) { ((Character)player).Message((MessageType)1, $"Sky Dive: {num} enemies hit", 0, (Sprite)null); } } } private static void CastBattleBlessing(Player player, int level) { //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "emote_cheer", "gpower"); float num = BlessingDuration(); PassiveEffects.ApplyTimedEffect(player, "SE_CDV_Blessing", num); if (ClassSystem.GetClass(player) == PlayerClass.Einherjar && (SpecSystem.IsAlternative(player) || BranchSystem.GetBranch(player) == 2)) { float num2 = 8f + ValkyrieReachBonus(player); Vector3 position = ((Component)player).transform.position; Network.BroadcastBuff(position, num2, "SE_CDV_Blessing", num); Network.BuffLocalPlayer(position, num2, "SE_CDV_Blessing", num); ((Character)player).Message((MessageType)1, $"Valkyrie's Blessing: allies within {num2:0} m are blessed", 0, (Sprite)null); } Effects.TryPlayAt(((Component)player).transform.position, "vfx_Potion_stamina_medium"); } private static float ValkyrieReachBonus(Player player) { return 2f + (float)TalentSystem.Rank(player, "cv_farreach") + (TalentSystem.Has(player, "cv_capstone") ? 2f : 0f) + (TalentSystem.HasSynergy(player, "syn_lightbringer") ? 1f : 0f) + (float)TalentSystem.Rank(player, "val_reach") + (float)TalentSystem.Rank(player, "vlk_reach") + (TalentSystem.Has(player, "vlk_capstone") ? 3f : 0f); } private static void CastJudgement(Player player, int level) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "staff_lightningshot", "gpower"); Vector3 point = ((Component)player).transform.position + AimForward(player) * 15f; RaycastHit val = default(RaycastHit); if ((Object)(object)GameCamera.instance != (Object)null && Physics.Raycast(new Ray(((Component)GameCamera.instance).transform.position, ((Component)GameCamera.instance).transform.forward), ref val, 40f)) { point = ((RaycastHit)(ref val)).point; } ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(JudgementStrikesRoutine(player, point, level)); } private static IEnumerator JudgementStrikesRoutine(Player player, Vector3 point, int level) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < JudgementStrikes(); i++) { if ((Object)(object)player == (Object)null) { break; } if (((Character)player).IsDead()) { break; } float damage = (float)JudgementDamage(level) * TalentSystem.Mult(player, "stc_maim", 1.3f) * ((i == 0) ? 1f : 0.6f); SpawnLightningBolt(player, point, damage, JudgementRadius()); yield return (object)new WaitForSeconds(0.4f); } } private static void CastSpearVolley(Player player, int level) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "spear_throw", "throw_bomb"); Vector3 val = AimDirection(player); float[] array = ((VolleyCount() != 7) ? new float[5] { -20f, -10f, 0f, 10f, 20f } : new float[7] { -30f, -20f, -10f, 0f, 10f, 20f, 30f }); for (int i = 0; i < array.Length; i++) { Vector3 dir = Quaternion.AngleAxis(array[i], Vector3.up) * val; HitData val2 = new HitData(); val2.m_damage.m_pierce = (float)VolleyDamage(level) * TalentSystem.Mult(player, "einh_piercingvolley", 1.3f) * TalentSystem.Mult(player, "stc_volleymaster", 1.3f); val2.m_pushForce = 40f; val2.SetAttacker((Character)(object)player); AddProjectileGlow(LaunchProjectile(player, "GoblinSpear_projectile", dir, 32f, val2, "ancientbarkspear_projectile", "bronzespear_projectile"), new Color(1f, 0.9f, 0.55f)); } Effects.TryPlayAt(EyePosition(player), "vfx_lightningstaff_fire"); } private static void CastThunderbolt(Player player, int level) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "staff_lightningshot", "gpower"); HitData val = new HitData(); val.m_damage.m_lightning = (float)ThunderboltDamage(level) * TalentSystem.Mult(player, "thu_boltforce", 1.4f); val.m_pushForce = 30f; val.SetAttacker((Character)(object)player); GameObject val2 = LaunchProjectile(player, "staff_lightning_projectile", AimDirection(player), 38f, val); if ((Object)(object)val2 != (Object)null) { AddProjectileGlow(val2, new Color(0.6f, 0.8f, 1f)); } if (TalentSystem.Has(player, "sto_notable") || TalentSystem.Has(player, "thu_capstone")) { Vector3 val3 = AimDirection(player); Character val4 = (from e in EnemiesAround(((Component)player).transform.position + val3 * 6f, 8f) orderby Vector3.Distance(((Component)e).transform.position, ((Component)player).transform.position) select e).FirstOrDefault(); if ((Object)(object)val4 != (Object)null) { SpawnLightningBolt(player, ((Component)val4).transform.position, (float)ThunderboltDamage(level) * 0.6f, 2.5f); } } } private static void CastThunderclap(Player player, int level) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "staff_lightningshot", "gpower"); float num = ThunderclapRadius(); int num2 = DamageEnemiesAround(player, ((Component)player).transform.position, num, delegate(HitData hit) { hit.m_damage.m_lightning = (float)ThunderclapDamage(level) * TalentSystem.Mult(player, "thu_clapforce", 1.5f); }, 40f, new string[2] { "vfx_HitSparks", "fx_StaffShield_Hit" }); Effects.TryPlayAtScaled(((Component)player).transform.position, num / 6f, 12f, "vfx_lightningstaff_fire"); ((Character)player).Message((MessageType)1, (num2 > 0) ? $"Thunderclap: {num2} foes struck" : "Thunderclap!", 0, (Sprite)null); } private static void CastThunderstorm(Player player, int level) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "staff_lightningshot", "gpower"); Vector3 position = ((Component)player).transform.position + AimForward(player) * 5f; float radius = ThunderstormRadius(); float duration = ThunderstormDuration(); int num = Mathf.RoundToInt(ThunderstormTick(level) * TalentSystem.Mult(player, "shr_stormforce", 1.5f) * TalentSystem.DamageMult(player, "lightning")); SanctuaryZone.CreateAt(position, radius, duration, num, 4); Network.BroadcastGround(position, radius, duration, num, 4); Effects.TryPlayAt(position, 10f, "vfx_lightningstaff_fire"); } private static void CastSkyfallSpears(Player player, int level) { Effects.TryCastAnimation(player, "spear_throw", "throw_bomb"); ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(SkyfallSpears(player, level)); } private static IEnumerator SkyfallSpears(Player player, int level) { Vector3 center = ((Component)player).transform.position + AimForward(player) * 8f; int count = SkyfallCount(); float spread = SkyfallRadius(); for (int i = 0; i < count; i++) { if ((Object)(object)player == (Object)null) { break; } if (((Character)player).IsDead()) { break; } Vector2 val = Random.insideUnitCircle * spread; Vector3 val2 = center + new Vector3(val.x, 0f, val.y); Vector2 val3 = Random.insideUnitCircle * 1.5f; Vector3 val4 = val2 + new Vector3(val3.x, 20f, val3.y); Vector3 val5 = val2 - val4; Vector3 normalized = ((Vector3)(ref val5)).normalized; HitData val6 = new HitData(); val6.m_damage.m_pierce = (float)SkyfallDamage(level) * TalentSystem.Mult(player, "spm_skyforce", 1.4f); val6.m_pushForce = 20f; val6.SetAttacker((Character)(object)player); TalentSystem.ApplyDamageTalents(player, val6); GameObject val7 = Effects.FindPrefab("ancientbarkspear_projectile", "bronzespear_projectile", "GoblinSpear_projectile"); if ((Object)(object)val7 != (Object)null) { GameObject obj = Object.Instantiate(val7, val4, Quaternion.LookRotation(normalized)); SetupProjectile(obj, player, normalized * 30f, val6); AddProjectileGlow(obj, new Color(1f, 0.9f, 0.55f)); } yield return (object)new WaitForSeconds(0.12f); } } private static void CastAegis(Player player, int level) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "staff_shield", "gpower"); float num = AegisDuration(); PassiveEffects.ApplyTimedEffect(player, "SE_CDV_Aegis", num); float pushForce = (TalentSystem.Has(player, "einh_repel") ? 240f : 120f); DamageEnemiesAround(player, ((Component)player).transform.position, 5f, delegate(HitData hit) { hit.m_damage.m_spirit = Progression.Dmg(0.6f, level); }, pushForce, new string[1] { "vfx_HitSparks" }); Effects.TryPlayAt(((Component)player).transform.position, "fx_StaffShield_Hit"); if (ClassSystem.GetClass(player) == PlayerClass.Einherjar && (SpecSystem.IsAlternative(player) || (BranchSystem.GetBranch(player) == 2 && BranchSystem.GetSubSpec(player) == 0))) { float num2 = 8f + ValkyrieReachBonus(player); Vector3 position = ((Component)player).transform.position; Network.BroadcastBuff(position, num2, "SE_CDV_Aegis", num); Network.BuffLocalPlayer(position, num2, "SE_CDV_Aegis", num); Network.BroadcastBuff(position, num2, "SE_CDV_Blessing", num); Network.BuffLocalPlayer(position, num2, "SE_CDV_Blessing", num); ((Character)player).Message((MessageType)1, $"Aegis of the Host: {num2:0} m of divine protection", 0, (Sprite)null); } GameObject val = Effects.FindPrefab("vfx_StaffShield"); if ((Object)(object)val != (Object)null) { GameObject val2 = Effects.InstantiateLocal(val, ((Component)player).transform.position + Vector3.up, Quaternion.identity, ((Component)player).transform); MonoBehaviour[] componentsInChildren = val2.GetComponentsInChildren(true); for (int num3 = 0; num3 < componentsInChildren.Length; num3++) { Object.DestroyImmediate((Object)(object)componentsInChildren[num3]); } val2.transform.localPosition = new Vector3(0f, 1f, 0f); val2.transform.localScale = Vector3.one * 1.3f; Object.Destroy((Object)(object)val2, AegisDuration()); } } private static void CastCallTheFallen(Player player, int level) { //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "staff_summon", "gpower"); SpiritMinions.RemoveAll((Character m) => (Object)(object)m == (Object)null || m.IsDead()); int num = Mathf.Min(2, SpiritCap() - SpiritMinions.Count); if (num <= 0) { ((Character)player).Message((MessageType)1, $"The fallen already answer your call (max {SpiritCap()})", 0, (Sprite)null); } for (int num2 = 0; num2 < num; num2++) { SummonSpirit(player); } if (TalentSystem.Has(player, "einh_rally")) { PassiveEffects.ApplyTimedEffect(player, "SE_CDV_Blessing", BlessingDuration()); } if (TalentSystem.Has(player, "einh_spiritbond")) { ((Character)player).Heal(Progression.Heal(10f, level), true); } if (ClassSystem.GetClass(player) == PlayerClass.Einherjar && (SpecSystem.IsAlternative(player) || (BranchSystem.GetBranch(player) == 2 && BranchSystem.GetSubSpec(player) == 0))) { float radius = 6f + ValkyrieReachBonus(player); float ttl = 15f + 5f * (float)TalentSystem.Rank(player, "cv_honorbond"); Vector3 position = ((Component)player).transform.position; Network.BroadcastBuff(position, radius, "SE_CDV_Corsa", ttl); Network.BuffLocalPlayer(position, radius, "SE_CDV_Corsa", ttl); } } private static void SummonSpirit(Player player) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) Vector2 insideUnitCircle = Random.insideUnitCircle; Vector2 val = ((Vector2)(ref insideUnitCircle)).normalized * 2f; Vector3 position = ((Component)player).transform.position + new Vector3(val.x, 0.2f, val.y); Character val2 = SpawnMinion(player, "Charred_Twitcher_Summoned", position); if (!((Object)(object)val2 == (Object)null)) { float num = 1f + 0.1f * (float)(TalentSystem.Rank(player, "her_fallenforce") + TalentSystem.Rank(player, "vlk_honorforce")) + (TalentSystem.Has(player, "her_capstone") ? 0.2f : 0f); if (num > 1f) { BoostMinion(val2, num, num); } SpiritMinions.RemoveAll((Character m) => (Object)(object)m == (Object)null || m.IsDead()); SpiritMinions.Add(val2); while (SpiritMinions.Count > SpiritCap()) { DespawnMinion(SpiritMinions[0]); SpiritMinions.RemoveAt(0); } Effects.TryPlayAt(position, "fx_summon_twitcher_spawn", "fx_summon_start"); } } private static void CastValhallaGrace(Player player, int level) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "emote_cheer", "gpower"); Vector3 position = ((Component)player).transform.position; float radius = GraceRadius(); int num = AdjGraceHeal(level); Network.BroadcastHeal(position, radius, num); Network.HealLocalPlayer(position, radius, num); Network.BroadcastBuff(position, radius, "SE_CDV_Rigenerazione", GraceDuration()); Network.BuffLocalPlayer(position, radius, "SE_CDV_Rigenerazione", GraceDuration()); Effects.TryPlayAt(position, "vfx_Potion_health_medium"); Effects.TryPlayAt(position, "sfx_offering"); } private static void CastSoulSpear(Player player, int level) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "spear_throw", "throw_bomb", "staff_lightningshot"); HitData val = new HitData(); val.m_damage.m_spirit = (float)SoulSpearDamage(level) * TalentSystem.Mult(player, "her_spearforce", 1.5f); val.m_pushForce = 30f; val.SetAttacker((Character)(object)player); GameObject val2 = LaunchProjectile(player, "GoblinSpear_projectile", AimDirection(player), 34f, val, "ancientbarkspear_projectile", "bronzespear_projectile"); if ((Object)(object)val2 != (Object)null) { AddProjectileGlow(val2, new Color(0.6f, 0.9f, 0.8f)); } } private static void CastWailOfTheFallen(Player player, int level) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "gpower", "staff_summon"); float radius = SoulWailRadius(); int num = DamageEnemiesAround(player, ((Component)player).transform.position, radius, delegate(HitData hit) { hit.m_damage.m_spirit = (float)SoulWailDamage(level) * TalentSystem.Mult(player, "her_wailforce", 1.5f); }, 60f, new string[2] { "fx_charred_summoned_death", "vfx_HitSparks" }); Effects.TryPlayAt(((Component)player).transform.position, "vfx_gdking_stomp"); ((Character)player).Message((MessageType)1, (num > 0) ? $"Wail of the Fallen: {num} souls torn" : "Wail of the Fallen!", 0, (Sprite)null); } private static void CastLegionOfValhalla(Player player, int level) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "staff_summon", "gpower"); Effects.TryPlayAt(((Component)player).transform.position, "fx_summon_start"); ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(LegionOfValhalla(player, level)); } private static IEnumerator LegionOfValhalla(Player player, int level) { int count = HeraldLegionCount(); ArmyMinions.RemoveAll((Character m) => (Object)(object)m == (Object)null || m.IsDead()); foreach (Character item in ArmyMinions.ToList()) { DespawnMinion(item); } ArmyMinions.Clear(); float boost = 1f + 0.08f * (float)TalentSystem.Rank(player, "her_legionforce") + (TalentSystem.Has(player, "her_capstone") ? 0.2f : 0f); for (int i = 0; i < count; i++) { if ((Object)(object)player == (Object)null) { break; } if (((Character)player).IsDead()) { break; } Vector2 insideUnitCircle = Random.insideUnitCircle; Vector2 val = ((Vector2)(ref insideUnitCircle)).normalized * 2.5f; Vector3 position = ((Component)player).transform.position + new Vector3(val.x, 0.2f, val.y); Character val2 = SpawnMinion(player, "Charred_Twitcher_Summoned", position); if ((Object)(object)val2 != (Object)null) { BoostMinion(val2, boost, boost); ZNetView component = ((Component)val2).GetComponent(); if ((Object)(object)component != (Object)null && component.IsValid()) { ZDO zDO = component.GetZDO(); zDO.Set("cdv_army", 1); if ((Object)(object)ZNet.instance != (Object)null) { zDO.Set("cdv_army_born", (long)ZNet.instance.GetTimeSeconds()); } } ArmyMinions.Add(val2); Effects.TryPlayAt(position, "fx_summon_twitcher_spawn"); } yield return (object)new WaitForSeconds(0.3f); } } private static void CastRagnarok(Player player, int level) { ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(Ragnarok(player, level)); } private static IEnumerator Ragnarok(Player player, int level) { Effects.TryPlayAt(((Component)player).transform.position, "sfx_thunder"); float launchEnd = Time.time + 0.3f; while (Time.time < launchEnd && (Object)(object)player != (Object)null && !((Character)player).IsDead()) { yield return (object)new WaitForFixedUpdate(); if ((Object)(object)player == (Object)null || ((Character)player).IsDead()) { yield break; } ((Character)player).m_body.linearVelocity = AimForward(player) * 4f + Vector3.up * 16f; ((Character)player).m_maxAirAltitude = ((Component)player).transform.position.y; } yield return (object)new WaitForSeconds(0.15f); float timeout = Time.time + 4f; while (Time.time < timeout && (Object)(object)player != (Object)null && !((Character)player).IsDead() && !((Character)player).IsOnGround()) { ((Character)player).m_maxAirAltitude = ((Component)player).transform.position.y; yield return null; } if ((Object)(object)player == (Object)null || ((Character)player).IsDead()) { yield break; } ((Character)player).m_maxAirAltitude = ((Component)player).transform.position.y; float damage = (float)RagnarokDamage(level) * TalentSystem.Mult(player, "einh_worldbreaker", 1.4f) * TalentSystem.Mult(player, "stc_soulburst", 1.3f) * TalentSystem.Mult(player, "stc_capstone", 1.2f) * TalentSystem.Mult(player, "thu_ragforce", 1.4f) * TalentSystem.Mult(player, "shr_ragforce", 1.4f) * TalentSystem.Mult(player, "vk_ragforce", 1.4f) * TalentSystem.Mult(player, "vlk_ragforce", 1.4f); float pushForce = (TalentSystem.Has(player, "vk_ragstun") ? 400f : 150f); int num = DamageEnemiesAround(player, ((Component)player).transform.position, RagnarokRadius(), delegate(HitData hit) { hit.m_damage.m_blunt = damage; hit.m_damage.m_lightning = damage / 2f; }, pushForce, new string[1] { "vfx_HitSparks" }); Effects.TryPlayAt(((Component)player).transform.position, "fx_fader_meteor_hit"); Effects.TryPlayAt(((Component)player).transform.position, "vfx_gdking_stomp"); Effects.TryPlayAt(((Component)player).transform.position, "sfx_gdking_stomp"); ((Character)player).Message((MessageType)1, (num > 0) ? $"Ragnarök: {num} enemies struck" : "Ragnarök!", 0, (Sprite)null); List targets = EnemiesAround(((Component)player).transform.position, 15f); int bolts = Mathf.Min(RagnarokBolts(), targets.Count); for (int i = 0; i < bolts; i++) { if ((Object)(object)player == (Object)null) { break; } if (((Character)player).IsDead()) { break; } Character val = targets[i % targets.Count]; if (!((Object)(object)val == (Object)null) && !val.IsDead()) { SpawnLightningBolt(player, ((Component)val).transform.position, RagnarokBoltDamage(level), 3f); yield return (object)new WaitForSeconds(0.2f); } } } private static void CastShieldBash(Player player, int level) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "sword_secondary", "unarmed_kick", "gpower"); bool flag = GuardianOffense(player); Vector3 val = ((Component)player).transform.position + AimForward(player) * 2f; float damage = (float)BashDamage(level) * (flag ? 1.6f : 1f) * TalentSystem.Mult(player, "gua_bash", 1.3f) * TalentSystem.Mult(player, "vg_savagebash", 1.3f); int num = DamageEnemiesAround(player, val, 3.5f, delegate(HitData hit) { hit.m_damage.m_blunt = damage; }, flag ? 240f : 120f, new string[1] { "vfx_clubhit" }); if (flag) { int num2 = TalentSystem.Rank(player, "vg_furyheal") + TalentSystem.Rank(player, "cru_crushheal") + TalentSystem.Rank(player, "wbr_crushheal") + (TalentSystem.Has(player, "van_notable") ? 1 : 0); if (num > 0 && num2 > 0) { ((Character)player).Heal((float)num2 * Progression.Heal(3f, level) * (float)num, true); } ((Character)player).Message((MessageType)1, (num > 0) ? $"Skull Crusher: {num} enemies shattered" : "Skull Crusher: no enemies in range", 0, (Sprite)null); } else { Network.BroadcastTaunt((Character)(object)player, val, 3.5f); Network.TauntOwnedEnemies((Character)(object)player, val, 3.5f); ((Character)player).Message((MessageType)1, (num > 0) ? $"Shield Bash: {num} enemies now face you" : "Shield Bash: no enemies in range", 0, (Sprite)null); } } private static void CastChallenge(Player player, int level) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) float radius = ChallengeRadius(); Effects.TryCastAnimation(player, "emote_challenge", "challenge", "gpower"); Vector3 position = ((Component)player).transform.position; Network.BroadcastTaunt((Character)(object)player, position, radius); Network.TauntOwnedEnemies((Character)(object)player, position, radius); PassiveEffects.ApplyTimedEffect(player, "SE_CDV_Sfida", 8f + 4f * (float)TalentSystem.Rank(player, "blw_longchallenge")); Effects.TryPlayAt(position, 4f, "fx_eikthyr_stomp"); int count = EnemiesAround(position, radius).Count; ((Character)player).Message((MessageType)1, (count > 0) ? $"Challenge: {count} enemies answer you" : "Challenge: no enemies in range", 0, (Sprite)null); } private static void CastShieldWall(Player player, int level) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) float radius = ShieldWallRadius(); float duration = ShieldWallDuration(); Effects.TryCastAnimation(player, "staff_shield", "gpower"); Vector3 position = ((Component)player).transform.position; Network.BroadcastDome(position, radius, duration, 1); CreateDomeAt(player, position, radius, duration, 1); int num = TalentSystem.Rank(player, "blw_mendingwall"); if (num > 0) { float amount = (float)num * Progression.Heal(7f, level) * (1f + 0.5f * (float)TalentSystem.Rank(player, "blw_mendfaith")); Network.BroadcastHeal(position, radius, amount); Network.HealLocalPlayer(position, radius, amount); } Effects.TryPlayAt(position, 4f, "fx_StaffShield_Hit"); } private static void CastGuardianLeap(Player player, int level) { ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(GuardianLeap(player, level)); } private static IEnumerator GuardianLeap(Player player, int level) { Vector3 dir = AimForward(player); dir.y = 0f; dir = ((Vector3)(ref dir)).normalized; float speed = 11f * TalentSystem.Mult(player, "gua_longleap", 1.5f) * (1f + 0.1f * (float)(TalentSystem.Rank(player, "cru_leapfar") + TalentSystem.Rank(player, "wbr_leapfar"))); float launchEnd = Time.time + 0.25f; while (Time.time < launchEnd && (Object)(object)player != (Object)null && !((Character)player).IsDead()) { yield return (object)new WaitForFixedUpdate(); if ((Object)(object)player == (Object)null || ((Character)player).IsDead()) { yield break; } ((Character)player).m_body.linearVelocity = dir * speed + Vector3.up * 9f; ((Character)player).m_maxAirAltitude = ((Component)player).transform.position.y; } yield return (object)new WaitForSeconds(0.15f); float timeout = Time.time + 3f; while (Time.time < timeout && (Object)(object)player != (Object)null && !((Character)player).IsDead() && !((Character)player).IsOnGround()) { ((Character)player).m_maxAirAltitude = ((Component)player).transform.position.y; yield return null; } if ((Object)(object)player == (Object)null || ((Character)player).IsDead()) { yield break; } ((Character)player).m_maxAirAltitude = ((Component)player).transform.position.y; DamageEnemiesAround(player, ((Component)player).transform.position, 4f, delegate(HitData hit) { hit.m_damage.m_blunt = (float)LeapDamage(level) * TalentSystem.Mult(player, "gua_heavylanding", 1.4f) * TalentSystem.Mult(player, "vg_executioner", 1.2f); }, 80f, new string[1] { "vfx_clubhit" }); Vector3 position = ((Component)player).transform.position; if (GuardianOffense(player)) { if (TalentSystem.Has(player, "vg_leapfrenzy")) { PassiveEffects.ApplyTimedEffect(player, "SE_CDV_Inno", 10f); } } else { float radius = 6f + 2f * (float)TalentSystem.Rank(player, "blw_rallypoint"); Network.BroadcastBuff(position, radius, "SE_CDV_Rampart", RampartDuration()); Network.BuffLocalPlayer(position, radius, "SE_CDV_Rampart", RampartDuration()); } Effects.TryPlayAt(position, "vfx_gdking_stomp"); Effects.TryPlayAt(position, "sfx_gdking_stomp"); } private static void CastIronBulwark(Player player, int level) { //IL_0089: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "emote_flex", "flex", "gpower"); ((Character)player).GetSEMan().RemoveStatusEffect(StringExtensionMethods.GetStableHashCode("SE_CDV_Fortezza"), true); PassiveEffects.ApplyTimedEffect(player, "SE_CDV_Baluardo", BulwarkDuration()); if (TalentSystem.Has(player, "gua_secondwind")) { ((Character)player).Heal(Progression.Heal(10f, level) * (1f + 0.5f * (float)TalentSystem.Rank(player, "gua_shieldheart")), true); } Effects.TryPlayAt(((Component)player).transform.position, "fx_StaffShield_Hit"); } private static void CastGroundSlam(Player player, int level) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) float num = StompRadius(); bool flag = GuardianOffense(player); Effects.TryCastAnimation(player, "swing_sledge", "battleaxe_attack0", "gpower"); Vector3 position = ((Component)player).transform.position; float damage = (float)StompDamage(level) * (flag ? 1.5f : 1f) * TalentSystem.Mult(player, "gua_stonefist", 1.3f) * TalentSystem.Mult(player, "vg_brutality", 1.15f); float pushForce = 60f * (1f + 0.5f * (float)(TalentSystem.Rank(player, "gua_slamforce") + TalentSystem.Rank(player, "vg_momentum"))); int num2 = DamageEnemiesAround(player, position, num, delegate(HitData hit) { hit.m_damage.m_blunt = damage; }, pushForce, new string[1] { "vfx_clubhit" }); Effects.TryPlayAt(position, "vfx_gdking_stomp"); Effects.TryPlayAt(position, "sfx_gdking_stomp"); if (flag) { if (TalentSystem.Has(player, "vg_aftershock")) { ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(Aftershock(player, position, num, damage / 2f)); } ((Character)player).Message((MessageType)1, (num2 > 0) ? $"Rupture: {num2} enemies hit ({num:0} m)" : $"Rupture: no enemies in range ({num:0} m)", 0, (Sprite)null); } else { float radius = num + 4f * (float)TalentSystem.Rank(player, "blw_tauntslam"); Network.BroadcastTaunt((Character)(object)player, position, radius); Network.TauntOwnedEnemies((Character)(object)player, position, radius); ((Character)player).Message((MessageType)1, (num2 > 0) ? $"Ground Slam: {num2} enemies hit and taunted" : "Ground Slam: no enemies in range", 0, (Sprite)null); } } private static void CastShatteringShout(Player player, int level) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "emote_roar", "roar", "emote_challenge", "gpower"); Vector3 val = ((Component)player).transform.position + AimForward(player) * 3f; int num = DamageEnemiesAround(player, val, 6f + (float)TalentSystem.Rank(player, "vg_echoingshout"), delegate(HitData hit) { hit.m_damage.m_blunt = (float)ShoutDamage(level) * TalentSystem.Mult(player, "vg_shatteringvoice", 1.3f); }, 100f, new string[1] { "vfx_clubhit" }); Effects.TryPlayAt(((Component)player).transform.position, "sfx_trollfire_roar"); Effects.TryPlayAt(val, 4f, "fx_eikthyr_stomp"); ((Character)player).Message((MessageType)1, (num > 0) ? $"Shattering Shout: {num} enemies broken" : "Shattering Shout: no enemies in range", 0, (Sprite)null); } private static void CastShieldStorm(Player player, int level) { ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(ShieldStorm(player, level)); } private static IEnumerator ShieldStorm(Player player, int level) { int ticks = 4 + TalentSystem.Rank(player, "vg_longerstorm"); for (int i = 0; i < ticks; i++) { if ((Object)(object)player == (Object)null) { break; } if (((Character)player).IsDead()) { break; } Effects.TryCastAnimation(player, "atgeir_secondary", "sword_secondary", "swing_longsword0", "unarmed_attack0"); DamageEnemiesAround(player, ((Component)player).transform.position, 4f + 0.5f * (float)TalentSystem.Rank(player, "vg_stormrider"), delegate(HitData hit) { hit.m_damage.m_blunt = (float)StormTickDamage(level) * TalentSystem.Mult(player, "vg_stormblades", 1.3f); }, 50f, new string[1] { "vfx_clubhit" }); yield return (object)new WaitForSeconds(0.5f); } } private static IEnumerator Aftershock(Player player, Vector3 position, float radius, float damage) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) yield return (object)new WaitForSeconds(1f); if (!((Object)(object)player == (Object)null) && !((Character)player).IsDead()) { DamageEnemiesAround(player, position, radius, delegate(HitData hit) { hit.m_damage.m_blunt = damage; }, 40f, new string[1] { "vfx_clubhit" }); Effects.TryPlayAt(position, "vfx_gdking_stomp"); } } private static void CastLivingFortress(Player player, int level) { //IL_007c: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "emote_roar", "roar", "gpower"); ((Character)player).GetSEMan().RemoveStatusEffect(StringExtensionMethods.GetStableHashCode("SE_CDV_Baluardo"), true); PassiveEffects.ApplyTimedEffect(player, "SE_CDV_Fortezza", FortressDuration()); if (GuardianOffense(player)) { PassiveEffects.ApplyTimedEffect(player, "SE_CDV_Inno", FortressDuration()); } else { ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(FortressTauntPulses(player)); } Effects.TryPlayAt(((Component)player).transform.position, "fx_StaffShield_Hit"); } private static IEnumerator FortressTauntPulses(Player player) { int pulses = Mathf.FloorToInt(FortressDuration() / 3f); for (int i = 0; i < pulses; i++) { if ((Object)(object)player == (Object)null) { break; } if (((Character)player).IsDead()) { break; } Vector3 position = ((Component)player).transform.position; Network.BroadcastTaunt((Character)(object)player, position, 10f); Network.TauntOwnedEnemies((Character)(object)player, position, 10f); yield return (object)new WaitForSeconds(3f); } } private static void CastThornplate(Player player, int level) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "staff_shield", "gpower"); PassiveEffects.ApplyTimedEffect(player, "SE_CDV_Spuntoni", ThornplateDuration()); Effects.TryPlayAt(((Component)player).transform.position, "fx_StaffShield_Hit"); } private static void CastEarthbreaker(Player player, int level) { //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "swing_sledge", "battleaxe_attack0", "gpower"); float num = EarthbreakerRadius(); float pushForce = (TalentSystem.Has(player, "cru_earthstun") ? 220f : 80f); int num2 = DamageEnemiesAround(player, ((Component)player).transform.position, num, delegate(HitData hit) { hit.m_damage.m_blunt = (float)EarthbreakerDamage(level) * TalentSystem.Mult(player, "cru_earthforce", 1.4f); }, pushForce, new string[2] { "fx_crystal_break", "vfx_HitSparks" }); Effects.TryPlayAtScaled(((Component)player).transform.position, num / 8f, 6f, "fx_eikthyr_stomp"); Effects.TryPlayAt(((Component)player).transform.position, "sfx_gdking_stomp"); ((Character)player).Message((MessageType)1, (num2 > 0) ? $"Earthbreaker: {num2} foes crushed" : "Earthbreaker!", 0, (Sprite)null); } private static void CastBlessingOfLight(Player player, int level) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "emote_cheer", "gpower"); Vector3 position = ((Component)player).transform.position; float radius = HolyRadius(); float ttl = HolyBuffDuration(); Network.BroadcastBuff(position, radius, "SE_CDV_Blessing", ttl); Network.BuffLocalPlayer(position, radius, "SE_CDV_Blessing", ttl); Network.BroadcastBuff(position, radius, "SE_CDV_Rampart", ttl); Network.BuffLocalPlayer(position, radius, "SE_CDV_Rampart", ttl); if (TalentSystem.Has(player, "tmp_capstone") || TalentSystem.Has(player, "pal_notable")) { float amount = Progression.Heal(15f, level) * TalentSystem.HealMult(player); Network.BroadcastHeal(position, radius, amount); Network.HealLocalPlayer(position, radius, amount); } Effects.TryPlayAt(position, "vfx_Potion_stamina_medium", "sfx_offering"); } private static void CastConsecration(Player player, int level) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "gpower", "staff_summon"); Vector3 position = ((Component)player).transform.position; float num = HolyGroundRadius(); float num2 = HolyGroundDuration(); if (BranchSystem.GetSubSpec(player) == 1) { ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(HolyGroundPulses(player, position, level, num, num2)); Effects.TryPlayAtScaled(position, num / 6f, num2, "fx_eikthyr_stomp"); } else { int num3 = AdjConsecrationHeal(level); SanctuaryZone.CreateAt(position, num, num2, num3); Network.BroadcastGround(position, num, num2, num3); } Effects.TryPlayAt(position, "sfx_offering"); } private static IEnumerator HolyGroundPulses(Player player, Vector3 center, int level, float radius, float duration) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) int pulses = Mathf.FloorToInt(duration); for (int i = 0; i < pulses; i++) { if ((Object)(object)player == (Object)null) { break; } if (((Character)player).IsDead()) { break; } DamageEnemiesAround(player, center, radius, delegate(HitData hit) { hit.m_damage.m_spirit = Progression.Dmg(6f, level) * TalentSystem.Mult(player, "lbr_consforce", 1.5f); }, 0f, new string[1] { "vfx_HitSparks" }); yield return (object)new WaitForSeconds(1f); } } private static void CastLayOnHands(Player player, int level) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "emote_cheer", "gpower"); Vector3 position = ((Component)player).transform.position; float radius = HolyRadius(); int num = AdjLayOnHandsHeal(level); Network.BroadcastHeal(position, radius, num); Network.HealLocalPlayer(position, radius, num); Effects.TryPlayAt(position, "vfx_Potion_health_medium", "sfx_offering"); } private static void CastDivineShield(Player player, int level) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "staff_shield", "gpower"); Vector3 position = ((Component)player).transform.position; float radius = HolyRadius(); float ttl = DivineShieldDuration(); Network.BroadcastBuff(position, radius, "SE_CDV_Rampart", ttl); Network.BuffLocalPlayer(position, radius, "SE_CDV_Rampart", ttl); Effects.TryPlayAt(position, "fx_StaffShield_Hit", "sfx_offering"); } private static void CastBeaconOfLight(Player player, int level) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "emote_cheer", "gpower"); Vector3 position = ((Component)player).transform.position; float radius = HolyRadius(); int num = AdjBeaconHeal(level); Network.BroadcastHeal(position, radius, num); Network.HealLocalPlayer(position, radius, num); Network.BroadcastBuff(position, radius, "SE_CDV_Rigenerazione", BeaconDuration()); Network.BuffLocalPlayer(position, radius, "SE_CDV_Rigenerazione", BeaconDuration()); Effects.TryPlayAt(position, "vfx_Potion_health_medium", "fx_summon_start"); Effects.TryPlayAt(position, "sfx_offering"); } private static void CastSmite(Player player, int level) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "staff_lightningshot", "gpower"); HitData val = new HitData(); val.m_damage.m_spirit = (float)SmiteDamage(level) * TalentSystem.Mult(player, "lbr_smiteforce", 1.4f); val.m_pushForce = 25f; val.SetAttacker((Character)(object)player); GameObject val2 = LaunchProjectile(player, "staff_lightning_projectile", AimDirection(player), 38f, val); if ((Object)(object)val2 != (Object)null) { AddProjectileGlow(val2, new Color(1f, 0.95f, 0.6f)); } } private static void CastHolyNova(Player player, int level) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "gpower", "staff_summon"); float num = HolyNovaRadius(); int num2 = ((!TalentSystem.Has(player, "lbr_capstone")) ? 1 : 2); int num3 = 0; for (int i = 0; i < num2; i++) { num3 += DamageEnemiesAround(player, ((Component)player).transform.position, num, delegate(HitData hit) { hit.m_damage.m_spirit = (float)HolyNovaDamage(level) * TalentSystem.Mult(player, "lbr_novaforce", 1.5f); }, 30f, new string[2] { "vfx_HitSparks", "fx_StaffShield_Hit" }); } Effects.TryPlayAtScaled(((Component)player).transform.position, num / 6f, 8f, "vfx_lightningstaff_fire"); ((Character)player).Message((MessageType)1, (num3 > 0) ? $"Holy Nova: {num3} foes smitten" : "Holy Nova!", 0, (Sprite)null); } private static void CastWrathOfLight(Player player, int level) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "gpower", "staff_summon"); float num = WrathRadius(); int num2 = DamageEnemiesAround(player, ((Component)player).transform.position, num, delegate(HitData hit) { hit.m_damage.m_spirit = (float)WrathDamage(level) * TalentSystem.Mult(player, "lbr_wrathforce", 1.4f); }, 60f, new string[2] { "fx_fader_meteor_hit", "vfx_HitSparks" }); if (TalentSystem.Has(player, "lbr_wrathheal") && num2 > 0) { ((Character)player).Heal(Progression.Heal(6f, level) * (float)num2, true); } Effects.TryPlayAtScaled(((Component)player).transform.position, num / 8f, 8f, "fx_eikthyr_stomp"); Effects.TryPlayAt(((Component)player).transform.position, "sfx_thunder"); ((Character)player).Message((MessageType)1, (num2 > 0) ? $"Wrath of Light: {num2} foes judged" : "Wrath of Light!", 0, (Sprite)null); } private static void CastGjallarhorn(Player player, int level) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "gpower", "emote_challenge"); float num = HornRadius(); Vector3 position = ((Component)player).transform.position; float damage = (float)HornDamage(level) * (GuardianOffense(player) ? 1.5f : 1f) * TalentSystem.Mult(player, "gua_hornbreaker", 1.4f); float pushForce = ((TalentSystem.Has(player, "wrd_hornstun") || TalentSystem.Has(player, "wbr_hornstun")) ? 400f : 200f); int num2 = DamageEnemiesAround(player, position, num, delegate(HitData hit) { hit.m_damage.m_blunt = damage; hit.m_damage.m_spirit = damage / 2f; }, pushForce, new string[1] { "vfx_clubhit" }); if (!GuardianOffense(player)) { float ttl = 15f + 5f * (float)TalentSystem.Rank(player, "blw_hornbrothers"); Network.BroadcastBuff(position, num, "SE_CDV_Rampart", ttl); Network.BuffLocalPlayer(position, num, "SE_CDV_Rampart", ttl); } Effects.TryPlayAtScaled(position, num / 6f, 4f, "fx_eikthyr_stomp"); Effects.TryPlayAt(position, "sfx_thunder"); ((Character)player).Message((MessageType)1, (num2 > 0) ? $"GJALLARHORN! {num2} enemies blasted away" : "GJALLARHORN!", 0, (Sprite)null); } private static void CastRegrowth(Player player, int level) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "gpower", "staff_summon"); float radius = BlessingRadius(); int num = AdjRegrowthHeal(level); Vector3 position = ((Component)player).transform.position; Network.BroadcastHeal(position, radius, num); Network.HealLocalPlayer(position, radius, num); if (GuardianOffense(player)) { int num2 = DamageEnemiesAround(player, position, 5f, delegate(HitData hit) { hit.m_damage.m_pierce = ThornSapDamage(level); }, 30f, new string[2] { "vfx_bush_destroyed", "vfx_HitSparks" }); if (num2 > 0) { ((Character)player).Message((MessageType)1, $"Thorn Sap: {num2} enemies lashed", 0, (Sprite)null); } } Effects.TryPlayAt(position, "vfx_Potion_health_medium"); Effects.TryPlayAt(position, "sfx_offering"); } private static void CastThornBurst(Player player, int level) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "staff_fireball1", "gpower"); Vector3 val = ((Component)player).transform.position + AimForward(player) * 3f; int num = DamageEnemiesAround(player, val, 4f, delegate(HitData hit) { hit.m_damage.m_pierce = (float)ThornDamage(level) * TalentSystem.Mult(player, "dru_sharpthorns", 1.3f) * TalentSystem.Mult(player, "tw_venomtip", 1.2f); }, 60f, new string[1] { "vfx_HitSparks" }); Effects.TryPlayAt(val, 5f, "vfx_bush_destroyed", "vfx_HitSparks"); ((Character)player).Message((MessageType)1, (num > 0) ? $"Thorn Burst: {num} enemies pierced" : "Thorn Burst: no enemies in range", 0, (Sprite)null); } private static void CastForestBlessing(Player player, int level) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "emote_cheer", "gpower"); float radius = BlessingRadius(); Vector3 position = ((Component)player).transform.position; Network.BroadcastBuff(position, radius, "SE_CDV_Inno", ForestBlessingDuration()); Network.BuffLocalPlayer(position, radius, "SE_CDV_Inno", ForestBlessingDuration()); Effects.TryPlayAt(position, "vfx_Potion_stamina_medium"); Effects.TryPlayAt(position, "sfx_offering"); } private static void CastHealingBloom(Player player, int level) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "staff_summon", "gpower"); Vector3 position = ((Component)player).transform.position + AimForward(player) * 3f; float radius = BloomRadius(); float duration = BloomDuration(); if (GuardianOffense(player)) { int num = AdjBloomPoison(level); Network.BroadcastGround(position, radius, duration, num, 1); SanctuaryZone.CreateAt(position, radius, duration, num, 1); } else { int num2 = AdjBloomHeal(level); Network.BroadcastGround(position, radius, duration, num2); SanctuaryZone.CreateAt(position, radius, duration, num2); } Effects.TryPlayAt(position, "vfx_offering"); Effects.TryPlayAt(position, "sfx_offering"); } private static void CastWindsGrace(Player player, int level) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "emote_cheer", "gpower"); float radius = BlessingRadius(); Vector3 position = ((Component)player).transform.position; Network.BroadcastBuff(position, radius, "SE_CDV_Corsa", WindsGraceDuration()); Network.BuffLocalPlayer(position, radius, "SE_CDV_Corsa", WindsGraceDuration()); Effects.TryPlayAt(position, "vfx_Potion_stamina_medium"); } private static void CastGraspingRoots(Player player, int level) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "gpower"); Vector3 position = ((Component)player).transform.position; float num = RootsRadius(); int num2 = DamageEnemiesAround(player, position, num, delegate(HitData hit) { float num3 = (float)RootsDamage(level) * TalentSystem.Mult(player, "dru_deeproots", 1.3f) * TalentSystem.Mult(player, "tw_impale", 1.2f); hit.m_damage.m_pierce = num3; hit.m_damage.m_poison = num3 / 2f; }, 100f, new string[2] { "vfx_bush_destroyed", "vfx_HitSparks" }); if (num2 > 0 && (TalentSystem.Has(player, "dru_lifethorns") || TalentSystem.Has(player, "gk_rootheal"))) { ((Character)player).Heal(Progression.Heal(2f, level) * (float)num2, true); } Effects.TryPlayAt(position, 10f, "vfx_gdking_rootspawn", "fx_gdking_rootspawn", "vfx_gdking_stomp"); Effects.TryPlayAt(position, "sfx_gdking_stomp"); ((Character)player).Message((MessageType)1, (num2 > 0) ? $"Grasping Roots: {num2} enemies torn ({num:0} m)" : $"Grasping Roots: no enemies in range ({num:0} m)", 0, (Sprite)null); } private static void CastForestEmbrace(Player player, int level) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "gpower", "staff_summon"); Vector3 position = ((Component)player).transform.position; if (SpecSystem.IsAlternative(player)) { float radius = NatureFuryRadius(); Network.BroadcastBuff(position, radius, "SE_CDV_FuriaNatura", NatureFuryDuration()); Network.BuffLocalPlayer(position, radius, "SE_CDV_FuriaNatura", NatureFuryDuration()); Effects.TryPlayAt(position, "vfx_bush_destroyed", "vfx_Potion_stamina_medium"); Effects.TryPlayAt(position, "sfx_offering"); } else { float radius2 = BlessingRadius(); int num = AdjEmbraceHeal(level); Network.BroadcastHeal(position, radius2, num); Network.HealLocalPlayer(position, radius2, num); Network.BroadcastBuff(position, radius2, "SE_CDV_Rigenerazione", EmbraceDuration()); Network.BuffLocalPlayer(position, radius2, "SE_CDV_Rigenerazione", EmbraceDuration()); Effects.TryPlayAt(position, "vfx_Potion_health_medium"); Effects.TryPlayAt(position, "sfx_offering"); } } private static void CastNaturesFury(Player player, int level) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "emote_cheer", "gpower"); Vector3 position = ((Component)player).transform.position; float radius = NatureFuryRadius(); Network.BroadcastBuff(position, radius, "SE_CDV_FuriaNatura", NatureFuryDuration()); Network.BuffLocalPlayer(position, radius, "SE_CDV_FuriaNatura", NatureFuryDuration()); Effects.TryPlayAt(position, "vfx_bush_destroyed", "vfx_Potion_stamina_medium"); Effects.TryPlayAt(position, "sfx_offering"); } private static void CastWarSong(Player player, int level) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "emote_cheer", "gpower"); Vector3 position = ((Component)player).transform.position; float radius = WarSongRadius(); Network.BroadcastBuff(position, radius, "SE_CDV_CantoGuerra", WarSongDuration()); Network.BuffLocalPlayer(position, radius, "SE_CDV_CantoGuerra", WarSongDuration()); Effects.TryPlayAt(position, "vfx_Potion_stamina_medium", "fx_summon_start"); Effects.TryPlayAt(position, "sfx_offering"); } private static void CastSummonWolf(Player player, int level) { Effects.TryCastAnimation(player, "staff_summon", "gpower"); float dmgMult = CompanionBaseDmgMult(player) * (1f + 0.05f * (float)TalentSystem.Rank(player, "bm_wolfpower")); SummonCompanion(player, "Wolf", dmgMult, CompanionHpMult(player)); } private static void CastSummonBear(Player player, int level) { Effects.TryCastAnimation(player, "staff_summon", "gpower"); float dmgMult = CompanionBaseDmgMult(player) * (1f + 0.05f * (float)TalentSystem.Rank(player, "bm_bearpower")); SummonCompanion(player, "Bjorn", dmgMult, 1.4f * CompanionHpMult(player)); } private static Character SummonCompanion(Player player, string prefabName, float dmgMult, float hpMult) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) Vector2 insideUnitCircle = Random.insideUnitCircle; Vector2 val = ((Vector2)(ref insideUnitCircle)).normalized * 2f; Vector3 position = ((Component)player).transform.position + new Vector3(val.x, 0.2f, val.y); Character val2 = SpawnMinion(player, prefabName, position); if ((Object)(object)val2 == (Object)null) { return null; } BoostMinion(val2, dmgMult, hpMult); Minions.RemoveAll((Character m) => (Object)(object)m == (Object)null || m.IsDead()); Minions.Add(val2); int num = MaxCompanions(); while (Minions.Count > num) { DespawnMinion(Minions[0]); Minions.RemoveAt(0); } Effects.TryPlayAt(position, "fx_summon_start", "fx_summon_skeleton_spawn"); return val2; } private static void CastCallOfTheWild(Player player, int level) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "staff_summon", "gpower"); Effects.TryPlayAt(((Component)player).transform.position, "fx_summon_start"); ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(WildPack(player, level)); } private static IEnumerator WildPack(Player player, int level) { int count = WildPackCount(); ArmyMinions.RemoveAll((Character m) => (Object)(object)m == (Object)null || m.IsDead()); foreach (Character item in ArmyMinions.ToList()) { DespawnMinion(item); } ArmyMinions.Clear(); float dmg = CompanionBaseDmgMult(player) * (1f + 0.08f * (float)TalentSystem.Rank(player, "bm_callpower")); for (int i = 0; i < count; i++) { if ((Object)(object)player == (Object)null) { break; } if (((Character)player).IsDead()) { break; } Vector2 insideUnitCircle = Random.insideUnitCircle; Vector2 val = ((Vector2)(ref insideUnitCircle)).normalized * 2.5f; Vector3 position = ((Component)player).transform.position + new Vector3(val.x, 0.2f, val.y); Character val2 = SpawnMinion(player, "Wolf", position); if ((Object)(object)val2 != (Object)null) { BoostMinion(val2, dmg, CompanionHpMult(player)); ZNetView component = ((Component)val2).GetComponent(); if ((Object)(object)component != (Object)null && component.IsValid()) { ZDO zDO = component.GetZDO(); zDO.Set("cdv_army", 1); if ((Object)(object)ZNet.instance != (Object)null) { zDO.Set("cdv_army_born", (long)ZNet.instance.GetTimeSeconds()); } } ArmyMinions.Add(val2); Effects.TryPlayAt(position, "fx_summon_skeleton_spawn"); } yield return (object)new WaitForSeconds(0.3f); } } private static void CastTranquility(Player player, int level) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "gpower", "staff_summon"); Vector3 position = ((Component)player).transform.position; float radius = TranquilityRadius(); int num = AdjTranquilityBurst(level); Network.BroadcastHeal(position, radius, num); Network.HealLocalPlayer(position, radius, num); int num2 = AdjTranquilityTick(level); float duration = TranquilityDuration(); SanctuaryZone.CreateAt(position, radius, duration, num2); Network.BroadcastGround(position, radius, duration, num2); Effects.TryPlayAt(position, "vfx_Potion_health_medium", "fx_summon_start"); Effects.TryPlayAt(position, "sfx_offering"); } private static void CastBarkward(Player player, int level) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "staff_shield", "gpower"); Vector3 position = ((Component)player).transform.position; float radius = BarkwardRadius(); float ttl = BarkwardDuration(); Network.BroadcastBuff(position, radius, "SE_CDV_Corteccia", ttl); Network.BuffLocalPlayer(position, radius, "SE_CDV_Corteccia", ttl); if (TalentSystem.Has(player, "gk_capstone")) { Network.BroadcastBuff(position, radius, "SE_CDV_Rigenerazione", ttl); Network.BuffLocalPlayer(position, radius, "SE_CDV_Rigenerazione", ttl); } Effects.TryPlayAt(position, "fx_StaffShield_Hit"); Effects.TryPlayAt(position, "sfx_offering"); } private static void CastWrathOfYggdrasil(Player player, int level) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "gpower", "staff_summon"); float radius = BlessingRadius() + 2f + (float)TalentSystem.Rank(player, "lif_yggwide"); Vector3 position = ((Component)player).transform.position; int num = AdjYggdrasilHeal(level); Network.BroadcastHeal(position, radius, num); Network.HealLocalPlayer(position, radius, num); Network.BroadcastBuff(position, radius, "SE_CDV_Inno", ForestBlessingDuration()); Network.BuffLocalPlayer(position, radius, "SE_CDV_Inno", ForestBlessingDuration()); int num2 = DamageEnemiesAround(player, position, 10f, delegate(HitData hit) { float num3 = (float)YggdrasilDamage(level) * TalentSystem.Mult(player, "tw_worldthorn", 1.4f) * TalentSystem.Mult(player, "tw_worldrage", 1.4f); hit.m_damage.m_pierce = num3; hit.m_damage.m_poison = num3 / 2f; }, 200f, new string[2] { "vfx_bush_destroyed", "vfx_HitSparks" }); Effects.TryPlayAt(position, 10f, "vfx_gdking_rootspawn", "fx_gdking_rootspawn", "vfx_gdking_stomp"); Effects.TryPlayAt(position, "vfx_odin_despawn"); Effects.TryPlayAt(position, "sfx_offering"); Effects.TryPlayAtScaled(position, 1.5f, 4f, "fx_eikthyr_stomp"); ((Character)player).Message((MessageType)1, (num2 > 0) ? $"Wrath of Yggdrasil: the roots strike {num2} enemies" : "The World Tree stirs...", 0, (Sprite)null); } private static void CastLifeDrain(Player player, int level) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) float radius = DrainRadius(); Effects.TryCastAnimation(player, "gpower"); int num = DamageEnemiesAround(player, ((Component)player).transform.position, radius, delegate(HitData hit) { hit.m_damage.m_spirit = (float)DrainDamage(level) * TalentSystem.Mult(player, "sp_drainforce", 1.3f); }, 20f, new string[1] { "vfx_HitSparks" }); if (num > 0) { ((Character)player).Heal((float)(AdjDrainHeal(level) * num), true); Effects.TryPlayAt(((Component)player).transform.position, "vfx_Potion_health_medium"); ((Character)player).Message((MessageType)1, $"Life Drain: {num} souls drained", 0, (Sprite)null); } else { ((Character)player).Message((MessageType)1, "Life Drain: no enemies in range", 0, (Sprite)null); } } private static void CastSummonSkeleton(Player player, int level) { Effects.TryCastAnimation(player, "staff_summon", "gpower"); SummonSkeleton(player, level); } private static void CastSummonRevenant(Player player, int level) { Effects.TryCastAnimation(player, "staff_summon", "gpower"); Character val = SummonSkeleton(player, level); if ((Object)(object)val != (Object)null) { float dmgMult = 1.6f * (1f + 0.1f * (float)TalentSystem.Rank(player, "dk_revenant")); float hpMult = 1.5f * (1f + 0.15f * (float)TalentSystem.Rank(player, "dk_bonehp")); BoostMinion(val, dmgMult, hpMult); } } private static Character SummonSkeleton(Player player, int level) { Character val = SpawnSkeleton(player); if ((Object)(object)val == (Object)null) { return null; } Minions.RemoveAll((Character m) => (Object)(object)m == (Object)null || m.IsDead()); Minions.Add(val); int num = MaxSkeletons(level); while (Minions.Count > num) { DespawnMinion(Minions[0]); Minions.RemoveAt(0); } return val; } private static void BoostMinion(Character minion, float dmgMult, float hpMult) { ZNetView component = ((Component)minion).GetComponent(); if ((Object)(object)component != (Object)null && component.IsValid()) { ZDO zDO = component.GetZDO(); zDO.Set("cdv_minion_dmg", zDO.GetFloat("cdv_minion_dmg", 1f) * dmgMult); } float num = minion.GetMaxHealth() * hpMult; minion.SetMaxHealth(num); minion.SetHealth(num); } private static void CastBonePact(Player player, int level) { //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "gpower"); PassiveEffects.ApplyTimedEffect(player, "SE_CDV_Ossa", BoneArmorDuration()); float num = 0.3f + 0.1f * (float)TalentSystem.Rank(player, "dk_pactheal"); float num2 = 1f + (float)PactBonusPercent() / 100f; long num3 = (((Object)(object)ZNet.instance != (Object)null) ? ((long)(ZNet.instance.GetTimeSeconds() + (double)PactDuration())) : 0); Minions.RemoveAll((Character m) => (Object)(object)m == (Object)null || m.IsDead()); ArmyMinions.RemoveAll((Character m) => (Object)(object)m == (Object)null || m.IsDead()); foreach (Character item in Minions.Concat(ArmyMinions).ToList()) { item.Heal(item.GetMaxHealth() * num, true); ZNetView component = ((Component)item).GetComponent(); if ((Object)(object)component != (Object)null && component.IsValid() && num3 > 0) { component.GetZDO().Set("cdv_pact", num3); component.GetZDO().Set("cdv_pact_mult", num2); } Effects.TryPlayAt(((Component)item).transform.position, "vfx_Potion_health_medium"); } if (TalentSystem.HasSynergy(player, "syn_soulbinder")) { ((Character)player).Heal(Progression.Heal(8f, level), true); } Effects.TryPlayAt(((Component)player).transform.position, "fx_StaffShield_Hit"); } private static void SummonArmySkeleton(Player player) { Character val = SpawnSkeleton(player); if ((Object)(object)val == (Object)null) { return; } ZNetView component = ((Component)val).GetComponent(); if ((Object)(object)component != (Object)null && component.IsValid()) { ZDO zDO = component.GetZDO(); zDO.Set("cdv_army", 1); if ((Object)(object)ZNet.instance != (Object)null) { zDO.Set("cdv_army_born", (long)ZNet.instance.GetTimeSeconds()); } } ArmyMinions.Add(val); } private static bool IsArmyExpired(Character minion, float lifetime) { if ((Object)(object)ZNet.instance == (Object)null) { return false; } ZNetView val = (((Object)(object)minion != (Object)null) ? ((Component)minion).GetComponent() : null); if ((Object)(object)val == (Object)null || !val.IsValid()) { return false; } long num = val.GetZDO().GetLong("cdv_army_born", 0L); if (num <= 0) { val.GetZDO().Set("cdv_army_born", (long)ZNet.instance.GetTimeSeconds()); return false; } return ZNet.instance.GetTimeSeconds() - (double)num > (double)lifetime; } private static Character SpawnSkeleton(Player player) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) Vector2 insideUnitCircle = Random.insideUnitCircle; Vector2 val = ((Vector2)(ref insideUnitCircle)).normalized * 2f; Vector3 position = ((Component)player).transform.position + new Vector3(val.x, 0.2f, val.y); Character val2 = SpawnMinion(player, "Skeleton_Friendly", position); if ((Object)(object)val2 != (Object)null) { Effects.TryPlayAt(position, "fx_summon_skeleton_spawn", "fx_summon_skeleton"); Effects.TryPlayAt(position, "sfx_skull_summon_skeleton"); } return val2; } private static void CastOozeBomb(Player player, int level) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "throw_bomb", "spear_throw"); HitData val = new HitData(); val.m_damage.m_poison = (float)OozeDamage(level) * TalentSystem.Mult(player, "pl_bombforce", 1.2f) * TalentSystem.Mult(player, "bli_bombforce", 1.4f); val.m_pushForce = 30f; val.SetAttacker((Character)(object)player); LaunchProjectile(player, "oozebomb_projectile", AimDirection(player) + Vector3.up * 0.15f, 18f, val); } private static void CastToxicCloud(Player player, int level) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "gpower"); Vector3 val = ((Component)player).transform.position + AimForward(player) * 5f; Effects.TryPlayAt(val, 10f, "fx_Bonemass_aoe_start"); ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(ToxicCloud(player, val, level)); } private static IEnumerator ToxicCloud(Player player, Vector3 center, int level) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) int waves = ToxicWaves(); float radius = ToxicRadius(); for (int i = 0; i < waves; i++) { if ((Object)(object)player == (Object)null) { break; } if (((Character)player).IsDead()) { break; } DamageEnemiesAround(player, center, radius, delegate(HitData hit) { hit.m_damage.m_poison = (float)ToxicTickDamage(level) * TalentSystem.Mult(player, "pes_cloudforce", 1.4f) * TalentSystem.Mult(player, "bli_cloudforce", 1.4f); }, 0f, null); yield return (object)new WaitForSeconds(1f); } } private static void CastSpectralWave(Player player, int level) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) float radius = SpectralWaveRadius(); Effects.TryCastAnimation(player, "staff_summon", "gpower"); float damageMult = TalentSystem.Mult(player, "rea_waveforce", 1.4f) * TalentSystem.Mult(player, "ban_waveforce", 1.4f); int num = DamageEnemiesAround(player, ((Component)player).transform.position, radius, delegate(HitData hit) { hit.m_damage.m_spirit = (float)SpectralDamage(level) * damageMult; hit.m_damage.m_slash = (float)SpectralDamage(level) / 2f * damageMult; }, 120f, new string[2] { "fx_charred_summoned_death", "vfx_HitSparks" }); Effects.TryPlayAt(((Component)player).transform.position, "vfx_gdking_stomp"); ((Character)player).Message((MessageType)1, (num > 0) ? $"Spectral Wave: {num} enemies hit" : "Spectral Wave: no enemies in range", 0, (Sprite)null); } private static void CastBoneArmor(Player player, int level) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "gpower"); PassiveEffects.ApplyTimedEffect(player, "SE_CDV_Ossa", BoneArmorDuration()); Effects.TryPlayAt(((Component)player).transform.position, "fx_StaffShield_Hit"); } private static void CastPutridRain(Player player, int level) { Effects.TryCastAnimation(player, "staff_summon", "gpower"); ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(PutridRain(player, level)); } private static IEnumerator PutridRain(Player player, int level) { Vector3 center = ((Component)player).transform.position + AimForward(player) * 8f; int bombs = PutridBombs(); float spread = 6f; for (int i = 0; i < bombs; i++) { if ((Object)(object)player == (Object)null) { break; } if (((Character)player).IsDead()) { break; } Vector2 val = Random.insideUnitCircle * spread; Vector3 val2 = center + new Vector3(val.x, 0f, val.y); Vector2 val3 = Random.insideUnitCircle * 2f; Vector3 val4 = val2 + new Vector3(val3.x, 18f, val3.y); Vector3 val5 = val2 - val4; Vector3 normalized = ((Vector3)(ref val5)).normalized; HitData val6 = new HitData(); val6.m_damage.m_poison = (float)OozeDamage(level) * TalentSystem.Mult(player, "necro_doubletoxin", 1.3f) * TalentSystem.Mult(player, "plg_pandemic", 1.2f); val6.m_pushForce = 30f; val6.SetAttacker((Character)(object)player); TalentSystem.ApplyDamageTalents(player, val6); GameObject val7 = Effects.FindPrefab("oozebomb_projectile"); if ((Object)(object)val7 != (Object)null) { SetupProjectile(Object.Instantiate(val7, val4, Quaternion.LookRotation(normalized)), player, normalized * 20f, val6); } yield return (object)new WaitForSeconds(0.35f); } } private static void CastArmyOfTheDead(Player player, int level) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "staff_summon", "gpower"); Effects.TryPlayAt(((Component)player).transform.position, "fx_summon_start"); ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(DeadArmy(player, level)); DamageEnemiesAround(player, ((Component)player).transform.position, 10f, delegate(HitData hit) { hit.m_damage.m_spirit = SpectralDamage(level); hit.m_damage.m_slash = (float)SpectralDamage(level) / 2f; }, 120f, new string[2] { "fx_charred_summoned_death", "vfx_HitSparks" }); } private static IEnumerator DeadArmy(Player player, int level) { int count = ArmyCount(); ArmyMinions.RemoveAll((Character m) => (Object)(object)m == (Object)null || m.IsDead()); foreach (Character item in ArmyMinions.ToList()) { DespawnMinion(item); } ArmyMinions.Clear(); for (int i = 0; i < count; i++) { if ((Object)(object)player == (Object)null) { break; } if (((Character)player).IsDead()) { break; } SummonArmySkeleton(player); yield return (object)new WaitForSeconds(0.4f); } } private static void CastRaiseHorde(Player player, int level) { Effects.TryCastAnimation(player, "staff_summon", "gpower"); ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(RaiseHorde(player, level)); } private static IEnumerator RaiseHorde(Player player, int level) { int count = RaiseHordeCount(); for (int i = 0; i < count; i++) { if ((Object)(object)player == (Object)null) { break; } if (((Character)player).IsDead()) { break; } SummonSkeleton(player, level); yield return (object)new WaitForSeconds(0.2f); } } private static void CastBoneStorm(Player player, int level) { Effects.TryCastAnimation(player, "gpower"); ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(BoneStorm(player, level)); } private static IEnumerator BoneStorm(Player player, int level) { int waves = BoneStormWaves(); float radius = BoneStormRadius(); float dmgMult = TalentSystem.Mult(player, "bl_stormforce", 1.4f); for (int i = 0; i < waves; i++) { if ((Object)(object)player == (Object)null) { break; } if (((Character)player).IsDead()) { break; } DamageEnemiesAround(player, ((Component)player).transform.position, radius, delegate(HitData hit) { hit.m_damage.m_slash = (float)BoneStormDamage(level) * dmgMult; hit.m_damage.m_pierce = (float)BoneStormDamage(level) / 2f * dmgMult; }, 15f, new string[1] { "vfx_HitSparks" }); Effects.TryPlayAtScaled(((Component)player).transform.position, radius / 6f, 12f, "fx_summon_skeleton"); yield return (object)new WaitForSeconds(0.5f); } } private static void CastDeathPact(Player player, int level) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "gpower"); float radius = DeathPactRadius(); float dmgMult = TalentSystem.Mult(player, "dk_pactforce", 1.4f); int num = DamageEnemiesAround(player, ((Component)player).transform.position, radius, delegate(HitData hit) { hit.m_damage.m_spirit = (float)DeathPactDamage(level) * dmgMult; hit.m_damage.m_slash = (float)DeathPactDamage(level) / 2f * dmgMult; }, 40f, new string[2] { "fx_charred_summoned_death", "vfx_HitSparks" }); Minions.RemoveAll((Character m) => (Object)(object)m == (Object)null || m.IsDead()); ArmyMinions.RemoveAll((Character m) => (Object)(object)m == (Object)null || m.IsDead()); foreach (Character item in Minions.Concat(ArmyMinions).ToList()) { item.Heal(item.GetMaxHealth() * 0.4f, true); Effects.TryPlayAt(((Component)item).transform.position, "vfx_Potion_health_medium"); } if (TalentSystem.Has(player, "dk_capstone")) { ((Character)player).Heal(Progression.Heal(10f, level) * (float)Mathf.Max(1, num), true); } Effects.TryPlayAt(((Component)player).transform.position, "vfx_gdking_stomp"); ((Character)player).Message((MessageType)1, (num > 0) ? $"Death Pact: {num} enemies struck" : "Death Pact: no enemies in range", 0, (Sprite)null); } private static void CastRavenForm(Player player, int level) { ShapeshiftSystem.Toggle(player, WildForm.Raven); } private static void CastWolfForm(Player player, int level) { ShapeshiftSystem.Toggle(player, WildForm.Wolf); } private static void CastBearForm(Player player, int level) { ShapeshiftSystem.Toggle(player, WildForm.Bear); } private static void CastSavagePounce(Player player, int level) { Effects.TryCastAnimation(player, "unarmed_kick", "sword_secondary", "gpower"); ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(SavagePounce(player, level)); } private static IEnumerator SavagePounce(Player player, int level) { Vector3 dir = AimForward(player); dir.y = 0f; dir = ((Vector3)(ref dir)).normalized; float end = Time.time + 0.4f + 0.06f * (float)TalentSystem.Rank(player, "ww_pouncefar"); while (Time.time < end && (Object)(object)player != (Object)null && !((Character)player).IsDead()) { yield return (object)new WaitForFixedUpdate(); if ((Object)(object)player == (Object)null || (Object)(object)((Character)player).m_body == (Object)null) { break; } ((Character)player).m_body.linearVelocity = dir * 18f + Vector3.up * 3f; ((Character)player).m_body.MovePosition(((Character)player).m_body.position + dir * 18f * Time.fixedDeltaTime); ((Character)player).m_maxAirAltitude = ((Component)player).transform.position.y; } if (!((Object)(object)player == (Object)null) && !((Character)player).IsDead()) { ((Character)player).m_maxAirAltitude = ((Component)player).transform.position.y; int num = DamageEnemiesAround(player, ((Component)player).transform.position, 3f, delegate(HitData hit) { hit.m_damage.m_slash = (float)SavagePounceDamage(level) * WolfMult() * TalentSystem.Mult(player, "ww_pounceforce", 1.5f); }, 40f, new string[2] { "vfx_blood_hit", "vfx_HitSparks" }); Effects.TryPlayAt(((Component)player).transform.position, "vfx_gdking_stomp"); if (num == 0) { ((Character)player).Message((MessageType)1, "Savage Pounce: missed", 0, (Sprite)null); } } } private static void CastSavageRend(Player player, int level) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected O, but got Unknown //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "swing_axe0", "sword_secondary", "unarmed_attack0", "gpower"); Character val = (from e in EnemiesAround(((Component)player).transform.position, 4f) orderby Vector3.Distance(((Component)e).transform.position, ((Component)player).transform.position) select e).FirstOrDefault(); if ((Object)(object)val == (Object)null) { ((Character)player).Message((MessageType)1, "Savage Rend: no foe ahead", 0, (Sprite)null); return; } HitData val2 = new HitData(); val2.m_damage.m_slash = (float)SavageRendHit(level) * WolfMult() * TalentSystem.Mult(player, "ww_rendforce", 1.5f); val2.m_pushForce = 20f; val2.m_point = ((Component)val).transform.position; val2.SetAttacker((Character)(object)player); TalentSystem.ApplyDamageTalents(player, val2); val.Damage(val2); Effects.TryPlayAt(((Component)val).transform.position + Vector3.up, "vfx_blood_hit"); float perTick = RendTickDamage(level) * WolfMult() * TalentSystem.Mult(player, "ww_rendforce", 1.5f); ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(BleedTarget(player, val, perTick, RendTicks())); if (TalentSystem.Has(player, "ww_bloodheal")) { ((Character)player).Heal(Progression.Heal(4f, level) * (float)TalentSystem.Rank(player, "ww_bloodheal"), true); } } private static void CastBloodMoon(Player player, int level) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "emote_challenge", "roar", "gpower"); Vector3 position = ((Component)player).transform.position; PassiveEffects.ApplyTimedEffect(player, "SE_CDV_LunaSangue", BloodMoonDuration()); if (TalentSystem.Has(player, "ww_packlead")) { Network.BroadcastBuff(position, BlessingRadius(), "SE_CDV_Blessing", BloodMoonDuration()); Network.BuffLocalPlayer(position, BlessingRadius(), "SE_CDV_Blessing", BloodMoonDuration()); } Effects.TryPlayAt(position, "vfx_gdking_stomp"); Effects.TryPlayAt(position, "sfx_offering"); } private static void CastMaul(Player player, int level) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "swing_sledge", "battleaxe_attack0", "unarmed_attack0", "gpower"); Vector3 val = ((Component)player).transform.position + AimForward(player) * 2f; float radius = MaulRadius(); int num = DamageEnemiesAround(player, val, radius, delegate(HitData hit) { hit.m_damage.m_blunt = (float)MaulDamage(level) * BearMult() * TalentSystem.Mult(player, "wb_maulforce", 1.5f); }, 60f, new string[2] { "fx_crystal_break", "vfx_HitSparks" }); Effects.TryPlayAt(val, "vfx_gdking_stomp"); if (num == 0) { ((Character)player).Message((MessageType)1, "Maul: missed", 0, (Sprite)null); } } private static void CastThunderousRoar(Player player, int level) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "emote_roar", "roar", "emote_challenge", "gpower"); float num = RoarRadius(); float pushForce = 90f; int num2 = DamageEnemiesAround(player, ((Component)player).transform.position, num, delegate(HitData hit) { hit.m_damage.m_blunt = (float)RoarDamage(level) * BearMult() * TalentSystem.Mult(player, "wb_roarforce", 1.5f); }, pushForce, new string[2] { "vfx_gdking_stomp", "vfx_HitSparks" }); Effects.TryPlayAtScaled(((Component)player).transform.position, num / 6f, 12f, "fx_Bonemass_aoe_start"); ((Character)player).Message((MessageType)1, (num2 > 0) ? $"Thunderous Roar: {num2} foes staggered" : "Thunderous Roar: no enemies in range", 0, (Sprite)null); } private static void CastFeralCharge(Player player, int level) { Effects.TryCastAnimation(player, "swing_sledge", "battleaxe_attack0", "gpower"); ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(FeralCharge(player, level)); } private static IEnumerator FeralCharge(Player player, int level) { Vector3 dir = AimForward(player); dir.y = 0f; dir = ((Vector3)(ref dir)).normalized; HashSet hitOnce = new HashSet(); float end = Time.time + 0.5f + 0.05f * (float)TalentSystem.Rank(player, "wb_rampfar"); float push = (TalentSystem.Has(player, "wb_rampstun") ? 90f : 50f); while (Time.time < end && (Object)(object)player != (Object)null && !((Character)player).IsDead()) { yield return (object)new WaitForFixedUpdate(); if ((Object)(object)player == (Object)null || (Object)(object)((Character)player).m_body == (Object)null) { break; } ((Character)player).m_body.linearVelocity = dir * 16f + Vector3.up * 1.5f; ((Character)player).m_body.MovePosition(((Character)player).m_body.position + dir * 16f * Time.fixedDeltaTime); ((Character)player).m_maxAirAltitude = ((Component)player).transform.position.y; foreach (Character item in EnemiesAround(((Component)player).transform.position, 2.5f)) { if (hitOnce.Add(item)) { HitData val = new HitData(); val.m_damage.m_blunt = (float)FeralChargeDamage(level) * BearMult() * TalentSystem.Mult(player, "wb_rampforce", 1.4f); val.m_pushForce = push; val.m_point = ((Component)item).transform.position; val.m_dir = dir; val.SetAttacker((Character)(object)player); TalentSystem.ApplyDamageTalents(player, val); item.Damage(val); Effects.TryPlayAt(((Component)item).transform.position + Vector3.up, "vfx_gdking_stomp", "vfx_HitSparks"); } } } if ((Object)(object)player != (Object)null && !((Character)player).IsDead()) { ((Character)player).m_maxAirAltitude = ((Component)player).transform.position.y; } } private static void CastPlagueNova(Player player, int level) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "gpower"); float num = PlagueNovaRadius(); int num2 = DamageEnemiesAround(player, ((Component)player).transform.position, num, delegate(HitData hit) { hit.m_damage.m_poison = (float)PlagueNovaDamage(level) * TalentSystem.Mult(player, "pes_novaforce", 1.5f); }, 30f, new string[2] { "vfx_blob_death", "vfx_HitSparks" }); Effects.TryPlayAtScaled(((Component)player).transform.position, num / 6f, 12f, "fx_Bonemass_aoe_start"); ((Character)player).Message((MessageType)1, (num2 > 0) ? $"Plague Nova: {num2} enemies infected" : "Plague Nova: no enemies in range", 0, (Sprite)null); } private static void CastPandemic(Player player, int level) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "staff_summon", "gpower"); Vector3 position = ((Component)player).transform.position + AimForward(player) * 5f; float radius = PandemicRadius(); float duration = PandemicDuration(); float amountPerTick = PandemicTickDamage(level) * TalentSystem.Mult(player, "pes_panforce", 1.4f) * TalentSystem.DamageMult(player, "poison"); SanctuaryZone.CreateAt(position, radius, duration, amountPerTick, 1); Network.BroadcastGround(position, radius, duration, amountPerTick, 1); Effects.TryPlayAt(position, 10f, "fx_Bonemass_aoe_start"); } private static void CastPlagueBolt(Player player, int level) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "throw_bomb", "spear_throw", "staff_fireball0"); HitData val = new HitData(); val.m_damage.m_poison = (float)PlagueBoltDamage(level) * TalentSystem.Mult(player, "bli_boltforce", 1.4f); val.m_pushForce = 20f; val.SetAttacker((Character)(object)player); GameObject val2 = LaunchProjectile(player, "oozebomb_projectile", AimDirection(player), 30f, val); if ((Object)(object)val2 != (Object)null) { AddProjectileGlow(val2, new Color(0.55f, 0.85f, 0.3f)); } } private static void CastCorrode(Player player, int level) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "staff_summon", "gpower"); Vector3 val = AimDirection(player); Character target = (from e in EnemiesAround(((Component)player).transform.position + val * 4f, 5f).Concat(EnemiesAround(((Component)player).transform.position, 3f)) orderby Vector3.Distance(((Component)e).transform.position, ((Component)player).transform.position) select e).FirstOrDefault(); if ((Object)(object)target == (Object)null) { ((Character)player).Message((MessageType)1, "Corrode: no enemy ahead", 0, (Sprite)null); return; } int ticks = Mathf.RoundToInt(CorrodeDuration()); float perTick = CorrodeTickDamage(level) * TalentSystem.Mult(player, "bli_corrodeforce", 1.5f) * (TalentSystem.Has(player, "bli_venomlord") ? 1.3f : 1f); ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(PoisonTarget(player, target, perTick, ticks)); if (TalentSystem.Has(player, "bli_notable")) { Character val2 = (from e in EnemiesAround(((Component)target).transform.position, 6f) where (Object)(object)e != (Object)(object)target orderby Vector3.Distance(((Component)e).transform.position, ((Component)target).transform.position) select e).FirstOrDefault(); if ((Object)(object)val2 != (Object)null) { ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(PoisonTarget(player, val2, perTick, ticks)); } } ((Character)player).Message((MessageType)1, "Corrode: the flesh rots", 0, (Sprite)null); } private static IEnumerator PoisonTarget(Player player, Character target, float perTick, int ticks) { for (int i = 0; i < ticks; i++) { yield return (object)new WaitForSeconds(1f); if ((Object)(object)player == (Object)null || (Object)(object)target == (Object)null || target.IsDead()) { break; } HitData val = new HitData(); val.m_damage.m_poison = perTick; TalentSystem.ApplyDamageTalents(player, val); val.m_point = ((Component)target).transform.position; val.SetAttacker((Character)(object)player); target.Damage(val); Effects.TryPlayAt(((Component)target).transform.position + Vector3.up, "vfx_blob_death"); } } private static void CastSoulRip(Player player, int level) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "staff_lightningshot", "staff_summon", "gpower"); HitData val = new HitData(); val.m_damage.m_spirit = (float)SoulRipDamage(level) * TalentSystem.Mult(player, "rea_ripforce", 1.5f); val.m_pushForce = 30f; val.SetAttacker((Character)(object)player); GameObject val2 = LaunchProjectile(player, "staff_lightning_projectile", AimDirection(player), 34f, val, "oozebomb_projectile"); if ((Object)(object)val2 != (Object)null) { AddProjectileGlow(val2, new Color(0.6f, 0.9f, 0.8f)); } ((Character)player).Heal((float)SoulRipHeal(level), true); Effects.TryPlayAt(((Component)player).transform.position, "vfx_Potion_health_medium"); } private static void CastDeathCoil(Player player, int level) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "staff_summon", "gpower"); float radius = DeathCoilRadius(); int num = DamageEnemiesAround(player, ((Component)player).transform.position, radius, delegate(HitData hit) { hit.m_damage.m_spirit = (float)DeathCoilDamage(level) * TalentSystem.Mult(player, "rea_coilforce", 1.4f); }, 60f, new string[2] { "fx_charred_summoned_death", "vfx_HitSparks" }); float num2 = Progression.Heal(6f, level) * (1f + 0.2f * (float)TalentSystem.Rank(player, "rea_coilheal")); if (TalentSystem.Has(player, "rea_coillife")) { num2 += Progression.Heal(3f, level) * (float)num; } ((Character)player).Heal(num2, true); Effects.TryPlayAt(((Component)player).transform.position, "vfx_gdking_stomp"); Effects.TryPlayAt(((Component)player).transform.position, "vfx_Potion_health_medium"); ((Character)player).Message((MessageType)1, (num > 0) ? $"Death Coil: {num} souls torn" : "Death Coil!", 0, (Sprite)null); } private static void CastWail(Player player, int level) { //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "staff_summon", "emote_challenge", "gpower"); float radius = WailRadius(); float pushForce = 150f + 50f * (float)TalentSystem.Rank(player, "ban_wailfear"); int num = DamageEnemiesAround(player, ((Component)player).transform.position, radius, delegate(HitData hit) { hit.m_damage.m_spirit = (float)WailDamage(level) * TalentSystem.Mult(player, "ban_wailforce", 1.5f); }, pushForce, new string[2] { "fx_charred_summoned_death", "vfx_HitSparks" }); Effects.TryPlayAt(((Component)player).transform.position, 6f, "sfx_wraith_alerted"); ((Character)player).Message((MessageType)1, (num > 0) ? $"Wail: {num} enemies hurled back" : "Wail: no enemies in range", 0, (Sprite)null); } private static void CastSpiritNova(Player player, int level) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, "gpower"); float radius = SpiritNovaRadius(); int num = DamageEnemiesAround(player, ((Component)player).transform.position, radius, delegate(HitData hit) { hit.m_damage.m_spirit = (float)SpiritNovaDamage(level) * TalentSystem.Mult(player, "ban_novaforce", 1.5f); }, 40f, new string[2] { "fx_charred_summoned_death", "vfx_HitSparks" }); Effects.TryPlayAt(((Component)player).transform.position, "vfx_gdking_stomp"); ((Character)player).Message((MessageType)1, (num > 0) ? $"Spirit Nova: {num} enemies struck" : "Spirit Nova: no enemies in range", 0, (Sprite)null); } private static void CastSpectralStorm(Player player, int level) { Effects.TryCastAnimation(player, "staff_summon", "gpower"); ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(SpectralStorm(player, level)); } private static IEnumerator SpectralStorm(Player player, int level) { Vector3 center = ((Component)player).transform.position + AimForward(player) * 8f; int count = SpectralStormCount(); float radius = SpectralStormRadius(); for (int i = 0; i < count; i++) { if ((Object)(object)player == (Object)null) { break; } if (((Character)player).IsDead()) { break; } Vector2 val = Random.insideUnitCircle * radius; Vector3 val2 = center + new Vector3(val.x, 0f, val.y); DamageEnemiesAround(player, val2, 3f, delegate(HitData hit) { hit.m_damage.m_spirit = (float)SpectralStormDamage(level) * TalentSystem.Mult(player, "ban_stormforce", 1.4f); }, 30f, new string[2] { "fx_charred_summoned_death", "vfx_HitSparks" }); Effects.TryPlayAt(val2, "fx_charred_summoned_death"); yield return (object)new WaitForSeconds(0.15f); } } public static void DespawnAllMinions() { //IL_008b: Unknown result type (might be due to invalid IL or missing references) long num = (((Object)(object)Player.m_localPlayer != (Object)null) ? Player.m_localPlayer.GetPlayerID() : 0); foreach (Character item in Character.GetAllCharacters().ToList()) { bool flag = (Object)(object)item != (Object)null && (((Object)item).name.StartsWith("Wolf") || ((Object)item).name.StartsWith("Bjorn")); if (!((Object)(object)item == (Object)null) && !item.IsDead() && (item.IsTamed() || (int)item.GetFaction() == 0) && (((Object)item).name.StartsWith("Skeleton_Friendly") || ((Object)item).name.StartsWith("Charred_Twitcher_Summoned") || ((Object)item).name.StartsWith("Surtling") || ((Object)item).name.StartsWith("BlobLava") || ((Object)item).name.StartsWith("Hatchling") || ((Object)item).name.StartsWith("Charred_Melee") || flag)) { ZNetView component = ((Component)item).GetComponent(); ZDO val = (((Object)(object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null); long num2 = ((val != null) ? val.GetLong("cdv_owner", 0L) : 0); if ((num2 == 0L || num2 == num) && (!flag || (val != null && val.GetInt("cdv_minion", 0) == 1))) { DespawnMinion(item); } } } Minions.Clear(); ArmyMinions.Clear(); SpiritMinions.Clear(); FireMinions.Clear(); MagmaMinions.Clear(); FireArmy.Clear(); } public static int DismissPermanentMinions(Player player) { if ((Object)(object)player == (Object)null) { return 0; } long playerID = player.GetPlayerID(); int num = 0; foreach (Character item in Character.GetAllCharacters().ToList()) { if (!IsModMinion(item) || item.IsDead()) { continue; } ZNetView component = ((Component)item).GetComponent(); ZDO val = (((Object)(object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null); if (val != null && val.GetInt("cdv_army", 0) != 1) { long num2 = val.GetLong("cdv_owner", 0L); if (num2 == 0L || num2 == playerID) { DespawnMinion(item); num++; } } } Minions.Clear(); SpiritMinions.Clear(); FireMinions.Clear(); MagmaMinions.Clear(); ((Character)player).Message((MessageType)1, (num > 0) ? string.Format("Dismissed {0} permanent summon{1}.", num, (num == 1) ? "" : "s") : "You have no permanent summons to dismiss.", 0, (Sprite)null); return num; } public static bool IsModMinion(Character character) { if ((Object)(object)character == (Object)null) { return false; } ZNetView component = ((Component)character).GetComponent(); if ((Object)(object)component != (Object)null && component.IsValid()) { return component.GetZDO().GetInt("cdv_minion", 0) == 1; } return false; } private static bool IsArmyMinion(Character minion) { if ((Object)(object)minion == (Object)null) { return false; } ZNetView component = ((Component)minion).GetComponent(); if ((Object)(object)component != (Object)null && component.IsValid()) { return component.GetZDO().GetInt("cdv_army", 0) == 1; } return false; } private static Character SpawnMinion(Player player, string prefabName, Vector3 position) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) GameObject val = Effects.FindPrefab(prefabName); if ((Object)(object)val == (Object)null) { ((Character)player).Message((MessageType)1, "The summon fails... (prefab not found)", 0, (Sprite)null); return null; } GameObject obj = Object.Instantiate(val, position, Quaternion.LookRotation(AimForward(player))); CharacterDrop component = obj.GetComponent(); if ((Object)(object)component != (Object)null) { component.SetDropsEnabled(false); component.m_drops.Clear(); } float num = Progression.MinionPower(ClassSystem.GetLevel(player)); float num2 = num; if (ClassSystem.GetClass(player) == PlayerClass.Necromancer && BranchSystem.GetBranch(player) == 2) { num *= NecroBoneMinionMult(player); num2 *= 1f + 0.04f * (float)TalentSystem.Rank(player, "bl_vitality") + 0.04f * (float)TalentSystem.Rank(player, "dk_vitality"); } if (ClassSystem.GetClass(player) == PlayerClass.Mage && BranchSystem.GetSubSpec(player) == 1) { num *= (1f + 0.06f * (float)TalentSystem.Rank(player, "smn_stokeforge") + 0.08f * (float)TalentSystem.Rank(player, "smn_impfury")) * (TalentSystem.Has(player, "smn_capstone") ? 1.2f : 1f); num2 *= 1f + 0.1f * (float)TalentSystem.Rank(player, "smn_sturdyimps") + 0.08f * (float)TalentSystem.Rank(player, "smn_overseer"); } Character component2 = obj.GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.m_faction = (Faction)0; component2.SetTamed(true); float num3 = component2.GetMaxHealth() * num2; component2.SetMaxHealth(num3); component2.SetHealth(num3); } ZNetView component3 = obj.GetComponent(); if ((Object)(object)component3 != (Object)null && component3.IsValid()) { ZDO zDO = component3.GetZDO(); zDO.Set("cdv_minion", 1); zDO.Set("cdv_owner", player.GetPlayerID()); zDO.Set("cdv_minion_dmg", num); } MonsterAI component4 = obj.GetComponent(); if ((Object)(object)component4 != (Object)null) { component4.m_alertRange = 30f; component4.SetFollowTarget(((Component)player).gameObject); } return component2; } public static void UpdateMinions(Player player) { //IL_053d: Unknown result type (might be due to invalid IL or missing references) //IL_02b1: Unknown result type (might be due to invalid IL or missing references) //IL_02c0: Unknown result type (might be due to invalid IL or missing references) //IL_02ba: Unknown result type (might be due to invalid IL or missing references) Minions.RemoveAll((Character m) => (Object)(object)m == (Object)null || m.IsDead()); ArmyMinions.RemoveAll((Character m) => (Object)(object)m == (Object)null || m.IsDead()); SpiritMinions.RemoveAll((Character m) => (Object)(object)m == (Object)null || m.IsDead()); FireMinions.RemoveAll((Character m) => (Object)(object)m == (Object)null || m.IsDead()); MagmaMinions.RemoveAll((Character m) => (Object)(object)m == (Object)null || m.IsDead()); FireArmy.RemoveAll((Character m) => (Object)(object)m == (Object)null || m.IsDead()); foreach (Character item in ArmyMinions.ToList()) { if (IsArmyExpired(item, ArmyLifetime)) { DespawnMinion(item); ArmyMinions.Remove(item); } } foreach (Character item2 in FireArmy.ToList()) { if (IsArmyExpired(item2, LegionLifetime())) { DespawnMinion(item2); FireArmy.Remove(item2); } } foreach (Character allCharacter in Character.GetAllCharacters()) { if ((Object)(object)allCharacter == (Object)null || allCharacter.IsDead()) { continue; } bool flag = ((Object)allCharacter).name.StartsWith("Wolf") || ((Object)allCharacter).name.StartsWith("Bjorn"); if (!(((Object)allCharacter).name.StartsWith("Skeleton_Friendly") || ((Object)allCharacter).name.StartsWith("Charred_Twitcher_Summoned") || ((Object)allCharacter).name.StartsWith("Surtling") || ((Object)allCharacter).name.StartsWith("BlobLava") || ((Object)allCharacter).name.StartsWith("Charred_Melee") || flag)) { continue; } ZNetView component = ((Component)allCharacter).GetComponent(); ZDO val = (((Object)(object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null); bool flag2 = val != null && val.GetInt("cdv_minion", 0) == 1; if (flag && !flag2) { continue; } if ((flag2 || allCharacter.IsTamed()) && (int)allCharacter.m_faction != 0) { allCharacter.m_faction = (Faction)0; } if ((int)allCharacter.GetFaction() != 0) { continue; } long num = ((val != null) ? val.GetLong("cdv_owner", 0L) : 0); if (num != 0L && num != player.GetPlayerID()) { continue; } if (((Object)allCharacter).name.StartsWith("Skeleton_Friendly")) { if (Minions.Contains(allCharacter) || ArmyMinions.Contains(allCharacter)) { continue; } (IsArmyMinion(allCharacter) ? ArmyMinions : Minions).Add(allCharacter); } else if (((Object)allCharacter).name.StartsWith("Surtling")) { if (FireMinions.Contains(allCharacter) || FireArmy.Contains(allCharacter)) { continue; } (IsArmyMinion(allCharacter) ? FireArmy : FireMinions).Add(allCharacter); } else if (((Object)allCharacter).name.StartsWith("BlobLava") || ((Object)allCharacter).name.StartsWith("Charred_Melee")) { if (MagmaMinions.Contains(allCharacter)) { continue; } MagmaMinions.Add(allCharacter); } else if (flag) { List list = (IsArmyMinion(allCharacter) ? ArmyMinions : Minions); if (list.Contains(allCharacter)) { continue; } list.Add(allCharacter); } else { if (SpiritMinions.Contains(allCharacter) || ArmyMinions.Contains(allCharacter)) { continue; } (IsArmyMinion(allCharacter) ? ArmyMinions : SpiritMinions).Add(allCharacter); } MonsterAI component2 = ((Component)allCharacter).GetComponent(); if ((Object)(object)component2 != (Object)null && (Object)(object)component2.GetFollowTarget() == (Object)null) { component2.SetFollowTarget(((Component)player).gameObject); } } foreach (Character minion in Minions.Concat(ArmyMinions).Concat(SpiritMinions).Concat(FireMinions) .Concat(MagmaMinions) .Concat(FireArmy)) { if ((Object)(object)minion == (Object)null || minion.IsDead()) { continue; } MonsterAI component3 = ((Component)minion).GetComponent(); if ((Object)(object)component3 == (Object)null) { continue; } Character targetCreature = component3.m_targetCreature; if ((Object)(object)targetCreature != (Object)null && !targetCreature.IsDead()) { continue; } List list2 = EnemiesAround(((Component)minion).transform.position, 25f); if (list2.Count != 0) { Character targetCreature2 = list2.OrderBy((Character e) => Vector3.Distance(((Component)e).transform.position, ((Component)minion).transform.position)).First(); component3.m_targetCreature = targetCreature2; ((BaseAI)component3).SetAlerted(true); } } } private static void DespawnMinion(Character minion) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)minion == (Object)null) { return; } Effects.TryPlayAt(((Component)minion).transform.position, 5f, "fx_charred_summoned_death", "vfx_odin_despawn"); if ((Object)(object)ZNetScene.instance != (Object)null) { ZNetView component = ((Component)minion).GetComponent(); if ((Object)(object)component != (Object)null && component.IsValid() && !component.IsOwner()) { component.ClaimOwnership(); } ZNetScene.instance.Destroy(((Component)minion).gameObject); } else { Object.Destroy((Object)(object)((Component)minion).gameObject); } } private static Vector3 AimDirection(Player player) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)GameCamera.instance != (Object)null)) { return ((Component)player).transform.forward; } return ((Component)GameCamera.instance).transform.forward; } private static Vector3 AimForward(Player player) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) Vector3 val = Vector3.ProjectOnPlane(AimDirection(player), Vector3.up); if (!(((Vector3)(ref val)).sqrMagnitude > 0.001f)) { return AimForward(player); } return ((Vector3)(ref val)).normalized; } private static Vector3 EyePosition(Player player) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) return ((Component)player).transform.position + Vector3.up * 1.6f; } private static GameObject LaunchProjectile(Player player, string prefabName, Vector3 dir, float speed, HitData hit, params string[] fallbackNames) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) List list = new List(); list.Add(prefabName); list.AddRange(fallbackNames); GameObject val = Effects.FindPrefab(list.ToArray()); if ((Object)(object)val == (Object)null) { ((Character)player).Message((MessageType)1, "The ability fails... (prefab not found)", 0, (Sprite)null); return null; } TalentSystem.ApplyDamageTalents(player, hit); speed *= TalentSystem.Mult(player, "mage_velocity", 1.3f); Vector3 val2 = EyePosition(player) + dir * 0.7f; GameObject obj = Object.Instantiate(val, val2, Quaternion.LookRotation(dir)); SetupProjectile(obj, player, dir * speed, hit); return obj; } private static void AddProjectileGlow(GameObject projectile, Color color) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Expected O, but got Unknown if (!((Object)(object)projectile == (Object)null)) { Renderer[] componentsInChildren = projectile.GetComponentsInChildren(true); foreach (Renderer obj in componentsInChildren) { obj.enabled = true; ((Component)obj).gameObject.SetActive(true); } GameObject val = new GameObject("cdv_glow"); val.transform.SetParent(projectile.transform, false); Light obj2 = val.AddComponent(); obj2.type = (LightType)2; obj2.color = color; obj2.range = 6f; obj2.intensity = 3f; obj2.shadows = (LightShadows)0; TrailRenderer val2 = val.AddComponent(); val2.time = 0.35f; val2.startWidth = 0.28f; val2.endWidth = 0f; val2.numCapVertices = 4; ((Renderer)val2).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)val2).receiveShadows = false; Shader val3 = Shader.Find("Sprites/Default"); if ((Object)(object)val3 != (Object)null) { ((Renderer)val2).material = new Material(val3); } val2.startColor = color; val2.endColor = new Color(color.r, color.g, color.b, 0f); } } private static List EnemiesAround(Vector3 center, float radius) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) return (from c in Character.GetAllCharacters() where (Object)(object)c != (Object)null && !c.IsPlayer() && !c.IsTamed() && !c.IsDead() && (int)c.GetFaction() != 0 && Vector3.Distance(center, ((Component)c).transform.position) <= radius select c).ToList(); } private static int DamageEnemiesAround(Player player, Vector3 center, float radius, Action setDamage, float pushForce, string[] perTargetVfx) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) int num = 0; foreach (Character item in EnemiesAround(center, radius)) { HitData val = new HitData(); setDamage(val); TalentSystem.ApplyDamageTalents(player, val); val.m_pushForce = pushForce; val.m_point = ((Component)item).transform.position; Vector3 val2 = ((Component)item).transform.position - center; val.m_dir = ((Vector3)(ref val2)).normalized; val.SetAttacker((Character)(object)player); item.Damage(val); if (perTargetVfx != null) { Effects.TryPlayAt(((Component)item).transform.position + Vector3.up, perTargetVfx); } num++; } return num; } private static void SetupProjectile(GameObject go, Player owner, Vector3 velocity, HitData hit) { //IL_00b4: Unknown result type (might be due to invalid IL or missing references) Projectile component = go.GetComponent(); if ((Object)(object)component == (Object)null) { return; } MethodInfo methodInfo = typeof(Projectile).GetMethods(AccessTools.all).FirstOrDefault((MethodInfo m) => m.Name == "Setup"); if (methodInfo == null) { Logger.LogWarning((object)"Projectile.Setup not found"); return; } ParameterInfo[] parameters = methodInfo.GetParameters(); object[] array = new object[parameters.Length]; for (int num = 0; num < parameters.Length; num++) { Type parameterType = parameters[num].ParameterType; if (typeof(Character).IsAssignableFrom(parameterType)) { array[num] = owner; } else if (parameterType == typeof(Vector3)) { array[num] = velocity; } else if (parameterType == typeof(HitData)) { array[num] = hit; } else if (parameterType == typeof(float)) { array[num] = (parameters[num].Name.ToLowerInvariant().Contains("noise") ? 10f : 1f); } else { array[num] = (parameterType.IsValueType ? Activator.CreateInstance(parameterType) : null); } } methodInfo.Invoke(component, array); } private static SpellDef[] ExpandSingleTreeRoster(Player player, PlayerClass cls, int branch, int sub, SpellDef[] original) { if (original == null || original.Length != 5) { return original ?? new SpellDef[0]; } string key = AscendantKey(cls, branch, sub); if (!AscendantPaths.TryGetValue(key, out var value)) { return original; } if (ExpandedRosterCache.TryGetValue(key, out var value2)) { return value2; } value2 = new SpellDef[8] { CloneAtLevel(original[0], 1), CloneAtLevel(original[1], 10), CloneAtLevel(original[2], 20), CreateAscendantSpell(value, mythic: false), CloneAtLevel(original[3], 40), CreateAscendantSpell(value, mythic: true), CloneAtLevel(original[4], 60), CreateAscensionUltimate(cls) }; ExpandedRosterCache[key] = value2; return value2; } private static SpellDef CloneAtLevel(SpellDef source, int level) { return new SpellDef { Name = source.Name, UnlockLevel = level, Cooldown = source.Cooldown, StaminaCost = source.StaminaCost, IconItem = source.IconItem, CastAction = source.CastAction, Describe = source.Describe, CastTime = source.CastTime }; } private static SpellDef CreateAscendantSpell(AscendantPath path, bool mythic) { return new SpellDef { Name = (mythic ? path.MythicName : path.OmenName), UnlockLevel = (mythic ? 50 : 30), Cooldown = (mythic ? 55f : 24f), StaminaCost = (mythic ? 65f : 40f), IconItem = (mythic ? path.MythicIcon : path.OmenIcon), CastTime = (mythic ? 1.5f : 0f), CastAction = delegate(Player player, int level) { CastAscendant(player, level, path, mythic); }, Describe = (int level) => DescribeAscendant(level, path, mythic) }; } private static string DescribeAscendant(int level, AscendantPath path, bool mythic) { Player localPlayer = Player.m_localPlayer; AscendantMode ascendantMode = (mythic ? path.MythicMode : path.OmenMode); string text = (mythic ? path.MythicFlavor : path.OmenFlavor); float num = (((Object)(object)localPlayer != (Object)null) ? AscendantPowerMultiplier(localPlayer, mythic) : 1f); int num2 = (mythic ? (5 + (((Object)(object)localPlayer != (Object)null) ? TalentSystem.Rank(localPlayer, CurrentAscendantPrefix(localPlayer) + "_mythicfocus") : 0)) : ((ascendantMode != AscendantMode.Field) ? 1 : 3)); float num3 = (mythic ? (6.5f + 0.35f * (float)Mathf.Max(0, num2 - 5)) : (5.5f + (((Object)(object)localPlayer != (Object)null) ? AscendantRadiusBonus(localPlayer) : 0f))); string arg = ((ascendantMode == AscendantMode.Ward || ascendantMode == AscendantMode.Companion) ? "around you" : $"{(mythic ? 5 : 4)} m ahead"); string text2 = ElementName(path.Element); string text3 = $"{arg}, {num3:0.#} m"; string text4 = ((num2 > 1) ? $", {num2} pulses" : string.Empty); string text5; switch (ascendantMode) { case AscendantMode.Ward: { int num8 = Progression.HealInt(Mathf.RoundToInt((mythic ? 6f : 18f) * num), level); int num9 = Progression.DmgInt(Mathf.RoundToInt((mythic ? 6f : 18f) * 0.35f * num), level); text5 = $"heals allies for {num8} and blasts foes for {num9} {text2}"; break; } case AscendantMode.Drain: { int num5 = Progression.DmgInt(Mathf.RoundToInt((mythic ? 11f : 22f) * num), level); int num6 = Progression.HealInt(mythic ? 2 : 4, level); text5 = $"{num5} {text2} damage and {num6} life stolen per enemy hit"; break; } case AscendantMode.Companion: { int num7 = Progression.DmgInt(Mathf.RoundToInt((mythic ? 9f : 14f) * num), level); text5 = $"{num7} {text2} damage and mends your summons"; break; } case AscendantMode.Field: text5 = $"{Progression.DmgInt(Mathf.RoundToInt((mythic ? 11f : 12f) * num), level)} " + text2 + " damage per pulse"; break; default: { int num4 = Progression.DmgInt(Mathf.RoundToInt((mythic ? 11f : 22f) * num), level); text5 = $"{num4} {text2} damage" + ((num2 > 1) ? " per pulse" : string.Empty); break; } } return text + ". Erupts " + text3 + text4 + ": " + text5; } private static string ElementName(AscendantElement element) { return element switch { AscendantElement.Fire => "fire", AscendantElement.Frost => "frost", AscendantElement.Lightning => "lightning", AscendantElement.Earth => "blunt", AscendantElement.Blood => "slash", AscendantElement.Pierce => "pierce", AscendantElement.Poison => "poison", AscendantElement.Spirit => "spirit", AscendantElement.Bone => "bone (blunt and spirit)", AscendantElement.Wild => "wild (slash and blunt)", AscendantElement.Nature => "nature", _ => "holy", }; } private static void CastAscendant(Player player, int level, AscendantPath path, bool mythic) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)player == (Object)null)) { Effects.TryCastAnimation(player, (!mythic) ? new string[3] { "gpower", "staff_fireball0", "battleaxe_attack" } : new string[2] { "gpower", "staff_summon" }); AscendantMode ascendantMode = (mythic ? path.MythicMode : path.OmenMode); Vector3 val = AimForward(player); Vector3 center = ((ascendantMode == AscendantMode.Ward || ascendantMode == AscendantMode.Companion) ? ((Component)player).transform.position : (((Component)player).transform.position + val * (mythic ? 5f : 4f))); if (mythic) { ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(AscendantMythic(player, level, path, center)); } else { CastAscendantOmen(player, level, path, center); } } } private static void CastAscendantOmen(Player player, int level, AscendantPath path, Vector3 center) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) float num = 5.5f + AscendantRadiusBonus(player); float num2 = AscendantPowerMultiplier(player, mythic: false); PlayAscendantFx(path.Element, center, num / 6f); switch (path.OmenMode) { case AscendantMode.Field: ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(AscendantField(player, level, path.Element, center, num, num2)); break; case AscendantMode.Ward: ApplyAscendantWard(player, level, path.Element, center, num, 18f * num2, 12f); break; case AscendantMode.Drain: { int num3 = AscendantDamage(player, level, path.Element, center, num, 22f * num2); if (num3 > 0) { ((Character)player).Heal(Progression.Heal(4f, level) * (float)num3 * num2, true); Effects.TryPlayAt(((Component)player).transform.position, "vfx_Potion_health_medium"); } break; } case AscendantMode.Companion: AscendantDamage(player, level, path.Element, center, num, 14f * num2); MendOwnedMinions(player, 0.3f); break; default: AscendantDamage(player, level, path.Element, center, num, 22f * num2); break; } } private static IEnumerator AscendantField(Player player, int level, AscendantElement element, Vector3 center, float radius, float multiplier) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) for (int pulse = 0; pulse < 3; pulse++) { if ((Object)(object)player == (Object)null) { break; } if (((Character)player).IsDead()) { break; } AscendantDamage(player, level, element, center, radius, 12f * multiplier); PlayAscendantFx(element, center, radius / 7f); yield return (object)new WaitForSeconds(0.65f); } } private static IEnumerator AscendantMythic(Player player, int level, AscendantPath path, Vector3 center) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) string text = CurrentAscendantPrefix(player); int num = ((!string.IsNullOrEmpty(text)) ? TalentSystem.Rank(player, text + "_mythicfocus") : 0); int pulses = 5 + num; float radius = 6.5f + 0.35f * (float)num; float multiplier = AscendantPowerMultiplier(player, mythic: true); for (int pulse = 0; pulse < pulses; pulse++) { if ((Object)(object)player == (Object)null) { break; } if (((Character)player).IsDead()) { break; } float num2 = radius + (float)pulse * 0.35f; switch (path.MythicMode) { case AscendantMode.Ward: ApplyAscendantWard(player, level, path.Element, center, num2, 6f * multiplier, 2f + (float)pulses * 0.5f); break; case AscendantMode.Drain: { int num3 = AscendantDamage(player, level, path.Element, center, num2, 11f * multiplier); if (num3 > 0) { ((Character)player).Heal(Progression.Heal(2f, level) * (float)num3 * multiplier, true); } break; } case AscendantMode.Companion: AscendantDamage(player, level, path.Element, center, num2, 9f * multiplier); MendOwnedMinions(player, 0.08f); break; default: AscendantDamage(player, level, path.Element, center, num2, 11f * multiplier); break; } PlayAscendantFx(path.Element, center, num2 / 7f); yield return (object)new WaitForSeconds(0.5f); } } private static int AscendantDamage(Player player, int level, AscendantElement element, Vector3 center, float radius, float basePower) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) float damage = Progression.Dmg(basePower, level); return DamageEnemiesAround(player, center, radius, delegate(HitData hit) { SetAscendantDamage(hit, element, damage); }, (element == AscendantElement.Earth) ? 180f : 45f, AscendantHitFx(element)); } private static void SetAscendantDamage(HitData hit, AscendantElement element, float damage) { switch (element) { case AscendantElement.Fire: hit.m_damage.m_fire = damage; break; case AscendantElement.Frost: hit.m_damage.m_frost = damage; break; case AscendantElement.Lightning: hit.m_damage.m_lightning = damage; break; case AscendantElement.Earth: hit.m_damage.m_blunt = damage; break; case AscendantElement.Blood: hit.m_damage.m_slash = damage; break; case AscendantElement.Pierce: hit.m_damage.m_pierce = damage; break; case AscendantElement.Poison: hit.m_damage.m_poison = damage; break; case AscendantElement.Spirit: hit.m_damage.m_spirit = damage; break; case AscendantElement.Bone: hit.m_damage.m_blunt = damage * 0.7f; hit.m_damage.m_spirit = damage * 0.3f; break; case AscendantElement.Wild: hit.m_damage.m_slash = damage * 0.75f; hit.m_damage.m_blunt = damage * 0.25f; break; case AscendantElement.Nature: hit.m_damage.m_pierce = damage * 0.65f; hit.m_damage.m_poison = damage * 0.35f; break; default: hit.m_damage.m_spirit = damage * 0.75f; hit.m_damage.m_lightning = damage * 0.25f; break; } } private static void ApplyAscendantWard(Player player, int level, AscendantElement element, Vector3 center, float radius, float baseHeal, float duration) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) float amount = Progression.Heal(baseHeal, level); Network.BroadcastHeal(center, radius, amount); Network.HealLocalPlayer(center, radius, amount); string effectName = AscendantWardEffect(element); Network.BroadcastBuff(center, radius, effectName, duration); Network.BuffLocalPlayer(center, radius, effectName, duration); AscendantDamage(player, level, element, center, radius, baseHeal * 0.35f); } private static void MendOwnedMinions(Player player, float fraction) { //IL_009e: Unknown result type (might be due to invalid IL or missing references) long playerID = player.GetPlayerID(); foreach (Character item in Character.GetAllCharacters().Where(IsModMinion).ToList()) { ZNetView component = ((Component)item).GetComponent(); ZDO val = (((Object)(object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null); if (val != null && (val.GetLong("cdv_owner", 0L) == 0L || val.GetLong("cdv_owner", 0L) == playerID)) { item.Heal(item.GetMaxHealth() * fraction, true); Effects.TryPlayAt(((Component)item).transform.position, "vfx_Potion_health_medium"); } } } private static float AscendantPowerMultiplier(Player player, bool mythic) { string text = CurrentAscendantPrefix(player); if (string.IsNullOrEmpty(text)) { return 1f; } int num = TalentSystem.Rank(player, text + (mythic ? "_mythicforce" : "_omenforce")); int num2 = TalentSystem.Rank(player, text + "_asc_vigor"); return 1f + (float)num * 0.06f + (float)num2 * 0.03f; } private static float AscendantRadiusBonus(Player player) { string text = CurrentAscendantPrefix(player); if (!string.IsNullOrEmpty(text)) { return (float)TalentSystem.Rank(player, text + "_omenreach") * 0.5f; } return 0f; } private static float AscendantStaminaMultiplier(Player player, SpellDef spell) { if (spell == null || (spell.UnlockLevel != 30 && spell.UnlockLevel != 50)) { return 1f; } string text = CurrentAscendantPrefix(player); int num = ((!string.IsNullOrEmpty(text)) ? TalentSystem.Rank(player, text + "_asc_efficiency") : 0); return Mathf.Max(0.5f, 1f - (float)num * 0.03f); } private static string CurrentAscendantPrefix(Player player) { SubSpecDef subSpecDef = BranchSystem.CurrentSub(player); if (subSpecDef != null && !string.IsNullOrEmpty(subSpecDef.CapstoneId)) { return subSpecDef.CapstoneId.Replace("_capstone", ""); } return string.Empty; } private static void PlayAscendantFx(AscendantElement element, Vector3 center, float scale) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Unknown result type (might be due to invalid IL or missing references) switch (element) { case AscendantElement.Fire: Effects.TryPlayAtScaled(center, scale, 8f, "fx_fader_meteor_hit", "vfx_goblin_meteor_hit"); Effects.TryPlayAt(center, "sfx_fader_meteor_start", "sfx_imp_fireball_launch"); break; case AscendantElement.Frost: Effects.TryPlayAtScaled(center, scale, 8f, "fx_fenring_icenova", "fx_iceshard_hit"); break; case AscendantElement.Lightning: Effects.TryPlayAtScaled(center, scale, 8f, "vfx_lightningstaff_fire", "fx_eikthyr_stomp"); Effects.TryPlayAt(center, "sfx_thunder"); break; case AscendantElement.Earth: Effects.TryPlayAtScaled(center, scale, 8f, "vfx_gdking_stomp", "fx_fader_meteor_hit"); Effects.TryPlayAt(center, "sfx_gdking_stomp"); break; case AscendantElement.Blood: Effects.TryPlayAtScaled(center, scale, 8f, "vfx_blood_hit", "vfx_HitSparks"); break; case AscendantElement.Pierce: Effects.TryPlayAtScaled(center, scale, 8f, "vfx_spear_hit", "vfx_HitSparks"); break; case AscendantElement.Poison: Effects.TryPlayAtScaled(center, scale, 8f, "vfx_blob_attack", "vfx_blobdeath"); break; case AscendantElement.Spirit: Effects.TryPlayAtScaled(center, scale, 8f, "fx_charred_summoned_death", "vfx_odin_despawn"); break; case AscendantElement.Bone: Effects.TryPlayAtScaled(center, scale, 8f, "fx_summon_skeleton_spawn", "vfx_skeleton_hit"); break; case AscendantElement.Wild: Effects.TryPlayAtScaled(center, scale, 8f, "vfx_blood_hit", "vfx_clubhit"); Effects.TryPlayAt(center, "sfx_wolf_howl"); break; case AscendantElement.Nature: Effects.TryPlayAtScaled(center, scale, 8f, "vfx_gdking_rootspawn", "vfx_bush_destroyed"); Effects.TryPlayAt(center, "sfx_offering"); break; default: Effects.TryPlayAtScaled(center, scale, 8f, "fx_eikthyr_stomp", "vfx_Potion_health_medium"); Effects.TryPlayAt(center, "sfx_offering"); break; } } private static string[] AscendantHitFx(AscendantElement element) { switch (element) { case AscendantElement.Fire: return new string[1] { "vfx_HitSparks" }; case AscendantElement.Frost: return new string[1] { "fx_iceshard_hit" }; case AscendantElement.Lightning: return new string[1] { "vfx_lightningstaff_fire" }; case AscendantElement.Earth: return new string[1] { "vfx_gdking_stomp" }; case AscendantElement.Blood: case AscendantElement.Wild: return new string[1] { "vfx_blood_hit" }; case AscendantElement.Pierce: return new string[1] { "vfx_spear_hit" }; case AscendantElement.Poison: return new string[1] { "vfx_blob_attack" }; case AscendantElement.Nature: return new string[1] { "vfx_bush_destroyed" }; case AscendantElement.Bone: return new string[1] { "vfx_skeleton_hit" }; default: return new string[1] { "fx_charred_summoned_death" }; } } private static string AscendantWardEffect(AscendantElement element) { switch (element) { case AscendantElement.Frost: return "SE_CDV_Scudo"; case AscendantElement.Lightning: case AscendantElement.Pierce: case AscendantElement.Spirit: return "SE_CDV_Aegis"; case AscendantElement.Earth: case AscendantElement.Bone: return "SE_CDV_Baluardo"; case AscendantElement.Blood: return "SE_CDV_Furia"; case AscendantElement.Wild: return "SE_CDV_Caccia"; case AscendantElement.Poison: case AscendantElement.Nature: return "SE_CDV_Corteccia"; default: return "SE_CDV_Inno"; } } private static Dictionary BuildAscendantPaths() { Dictionary dictionary = new Dictionary(); AddAscendant(dictionary, PlayerClass.Mage, 0, 0, AscendantElement.Fire, "Solar Brand", "Brand the battlefield with a newborn sun", "SurtlingCore", AscendantMode.Burst, "Phoenix Descent", "A phoenix circles down in expanding waves of flame", "TrophySurtling", AscendantMode.Field); AddAscendant(dictionary, PlayerClass.Mage, 0, 1, AscendantElement.Fire, "Cinder Gate", "Open a burning gate that feeds your fiery servants", "Coal", AscendantMode.Companion, "Forgeheart Colossus", "The divine forge awakens beneath your legion", "TrophyGoblinBrute", AscendantMode.Companion); AddAscendant(dictionary, PlayerClass.Mage, 1, 0, AscendantElement.Frost, "Icebound Comet", "Call down a comet wrapped in ancient winter", "Crystal", AscendantMode.Burst, "Crown of Boreas", "Boreas answers with an ever-growing crown of frost", "TrophyDragonQueen", AscendantMode.Field); AddAscendant(dictionary, PlayerClass.Mage, 1, 1, AscendantElement.Frost, "Mirror of Rime", "Raise a mirrored ward that heals and freezes", "StaffShield", AscendantMode.Ward, "Citadel of Ice", "Conjure a pulsing citadel of living ice", "TrophySGolem", AscendantMode.Ward); AddAscendant(dictionary, PlayerClass.Mage, 2, 0, AscendantElement.Lightning, "Thunder God's Mark", "Mark the earth for a divine lightning strike", "Thunderstone", AscendantMode.Burst, "Ninefold Tempest", "Nine echoes of the heavens roll across the battlefield", "TrophyEikthyr", AscendantMode.Field); AddAscendant(dictionary, PlayerClass.Mage, 2, 1, AscendantElement.Lightning, "Stormstep Echo", "Your passage leaves a violent echo of lightning", "Wisp", AscendantMode.Burst, "Living Constellation", "A constellation of roaming thunder awakens around you", "Thunderstone", AscendantMode.Field); AddAscendant(dictionary, PlayerClass.Berserker, 0, 0, AscendantElement.Earth, "Avalanche Charge", "Release the weight of an avalanche in one impact", "Stone", AscendantMode.Burst, "Worldbreaker", "Each heartbeat cracks a wider ring through the world", "SledgeDemolisher", AscendantMode.Field); AddAscendant(dictionary, PlayerClass.Berserker, 0, 1, AscendantElement.Earth, "Tectonic Rift", "Tear open a fault that erupts beneath your prey", "SledgeIron", AscendantMode.Field, "Heart of the Mountain", "The mountain beats through you in crushing waves", "TrophySGolem", AscendantMode.Ward); AddAscendant(dictionary, PlayerClass.Berserker, 1, 0, AscendantElement.Blood, "Crimson Cyclone", "A crimson arc harvests every foe around you", "AxeBlackMetal", AscendantMode.Drain, "Red Harvest", "Repeated circles of steel return stolen life", "Bloodbag", AscendantMode.Drain); AddAscendant(dictionary, PlayerClass.Berserker, 1, 1, AscendantElement.Blood, "Predator's Brand", "Brand wounded prey for immediate execution", "KnifeBlackMetal", AscendantMode.Burst, "Feast of Blades", "The hunt becomes an expanding feast of steel", "TrophyFenring", AscendantMode.Drain); AddAscendant(dictionary, PlayerClass.Berserker, 2, 0, AscendantElement.Pierce, "Gungnir's Wake", "A spectral spear tears a wake through the enemy line", "SpearChitin", AscendantMode.Burst, "Spear of Midnight", "Midnight spears answer in widening volleys", "TrophyUlv", AscendantMode.Field); AddAscendant(dictionary, PlayerClass.Berserker, 2, 1, AscendantElement.Wild, "Packrunner's Trail", "The spectral pack tears through your chosen ground", "TrophyWolf", AscendantMode.Burst, "Fenrir Unbound", "Fenrir's shadow hunts in relentless circles", "TrophyFenring", AscendantMode.Field); AddAscendant(dictionary, PlayerClass.Necromancer, 0, 0, AscendantElement.Poison, "Virulent Garden", "A garden of corruption flowers beneath your enemies", "Guck", AscendantMode.Field, "Black Plague", "The oldest sickness returns in pulsing waves", "TrophyBonemass", AscendantMode.Field); AddAscendant(dictionary, PlayerClass.Necromancer, 0, 1, AscendantElement.Poison, "Rotting Star", "Condense every blight into one rotting star", "Ooze", AscendantMode.Burst, "Worldblight", "The land itself exhales a world-ending disease", "TrophyAbomination", AscendantMode.Field); AddAscendant(dictionary, PlayerClass.Necromancer, 1, 0, AscendantElement.Spirit, "Soul Lantern", "A lantern of stolen souls burns and restores you", "TrophyWraith", AscendantMode.Drain, "Reaper's Eclipse", "An eclipse strips life from everything it touches", "TrophyDraugrElite", AscendantMode.Drain); AddAscendant(dictionary, PlayerClass.Necromancer, 1, 1, AscendantElement.Spirit, "Dirge of Glass", "A crystalline scream shatters body and spirit", "Crystal", AscendantMode.Burst, "Choir of the Damned", "The dead sing in an expanding spectral choir", "TrophyWraith", AscendantMode.Field); AddAscendant(dictionary, PlayerClass.Necromancer, 2, 0, AscendantElement.Bone, "Ossuary Gate", "Open an ossuary that mends servants and crushes foes", "BoneFragments", AscendantMode.Companion, "Throne of Bones", "A throne of the dead empowers your whole army", "TrophySkeletonPoison", AscendantMode.Companion); AddAscendant(dictionary, PlayerClass.Necromancer, 2, 1, AscendantElement.Bone, "Gravebound Oath", "Bind your servants and yourself in a graveward", "TrophySkeleton", AscendantMode.Ward, "Death March", "Every pulse drives the gravebound host forward", "TrophyDraugr", AscendantMode.Companion); AddAscendant(dictionary, PlayerClass.Druid, 0, 0, AscendantElement.Wild, "Moonclaw", "A crescent claw of moonlight rends the hunting ground", "TrophyWolf", AscendantMode.Drain, "Hunt Under Red Moon", "The red moon answers every beat of the hunt", "TrophyFenring", AscendantMode.Drain); AddAscendant(dictionary, PlayerClass.Druid, 0, 1, AscendantElement.Earth, "Earthen Rampart", "Rise like a bear and break the earth around you", "TrophyBear", AscendantMode.Ward, "Ursa Major", "The great bear constellation descends in crushing rings", "TrophySGolem", AscendantMode.Field); AddAscendant(dictionary, PlayerClass.Druid, 1, 0, AscendantElement.Nature, "Verse of Valor", "A living verse heals allies and lashes enemies", "TankardOdin", AscendantMode.Ward, "Song of the World Tree", "Yggdrasil's song rolls outward through every living soul", "YggdrasilWood", AscendantMode.Ward); AddAscendant(dictionary, PlayerClass.Druid, 1, 1, AscendantElement.Wild, "Primal Convergence", "Call every companion into one primal heartbeat", "TrophyWolf", AscendantMode.Companion, "Wildheart Stampede", "The unseen wild stampedes through widening circles", "TrophyLox", AscendantMode.Companion); AddAscendant(dictionary, PlayerClass.Druid, 2, 0, AscendantElement.Holy, "Seed of Renewal", "Plant a radiant seed that restores the wounded", "Dandelion", AscendantMode.Ward, "Dawn Bloom", "A flower of dawn opens again with every pulse", "MeadHealthMedium", AscendantMode.Ward); AddAscendant(dictionary, PlayerClass.Druid, 2, 1, AscendantElement.Nature, "Thorn Labyrinth", "A labyrinth of roots closes around your enemies", "Root", AscendantMode.Field, "Yggdrasil's Dream", "The World Tree dreams through healing and thorns", "YggdrasilWood", AscendantMode.Ward); AddAscendant(dictionary, PlayerClass.Einherjar, 0, 0, AscendantElement.Lightning, "Mjolnir's Echo", "The echo of Mjolnir lands where you decree", "SledgeStagbreaker", AscendantMode.Burst, "Heaven's Anvil", "The heavens hammer the battlefield in repeated rings", "TrophyEikthyr", AscendantMode.Field); AddAscendant(dictionary, PlayerClass.Einherjar, 0, 1, AscendantElement.Lightning, "Storm Banner", "Plant an unseen banner of thunder and protection", "Thunderstone", AscendantMode.Ward, "Bifrost Tempest", "The Bifrost fractures into a many-colored storm", "TrophyDragonQueen", AscendantMode.Ward); AddAscendant(dictionary, PlayerClass.Einherjar, 1, 0, AscendantElement.Pierce, "Runic Javelin", "A giant rune-spear erupts from the chosen ground", "SpearChitin", AscendantMode.Burst, "Rain of Gungnir", "Gungnir's reflections fall in measured waves", "TrophyUlv", AscendantMode.Field); AddAscendant(dictionary, PlayerClass.Einherjar, 1, 1, AscendantElement.Holy, "Winged Lunge", "Radiant wings carry a spear through the enemy line", "Feathers", AscendantMode.Burst, "Chooser of the Slain", "Each pulse judges who may rise to Valhalla", "TrophyValkyrie", AscendantMode.Drain); AddAscendant(dictionary, PlayerClass.Einherjar, 2, 0, AscendantElement.Holy, "Shieldmaiden's Call", "Call a shield-circle from beyond the veil", "ShieldSilver", AscendantMode.Ward, "Hall of Heroes", "The hall opens and renews every worthy ally", "TankardOdin", AscendantMode.Ward); AddAscendant(dictionary, PlayerClass.Einherjar, 2, 1, AscendantElement.Spirit, "Soul Standard", "Raise a spectral standard among the fallen", "TrophyWraith", AscendantMode.Companion, "Einherjar Ascendant", "The honored dead march through the battlefield again", "TrophyDraugrElite", AscendantMode.Companion); AddAscendant(dictionary, PlayerClass.Guardian, 0, 0, AscendantElement.Earth, "Bastion's Roar", "Your shield speaks with the voice of a fortress", "ShieldIronTower", AscendantMode.Ward, "Unfallen Wall", "An unfallen wall pulses outward from your stance", "ShieldSerpentscale", AscendantMode.Ward); AddAscendant(dictionary, PlayerClass.Guardian, 0, 1, AscendantElement.Nature, "Mirror Shield", "Reflect the battlefield through a shield of thorns", "ShieldSerpentscale", AscendantMode.Ward, "Thousand Thorns", "Every blow awakens another widening crown of thorns", "TrophyAbomination", AscendantMode.Field); AddAscendant(dictionary, PlayerClass.Guardian, 1, 0, AscendantElement.Earth, "Faultbreaker", "Drive a crushing fault beneath the enemy line", "SledgeIron", AscendantMode.Burst, "Continental Divide", "The world parts in a sequence of colossal impacts", "SledgeDemolisher", AscendantMode.Field); AddAscendant(dictionary, PlayerClass.Guardian, 1, 1, AscendantElement.Blood, "Banner of Ruin", "Raise a war-banner that drinks the enemy's courage", "TankardOdin", AscendantMode.Drain, "March of Conquest", "Each pulse advances the line of conquest", "TrophyGoblinBrute", AscendantMode.Ward); AddAscendant(dictionary, PlayerClass.Guardian, 2, 0, AscendantElement.Holy, "Sacred Chain", "Bind allies together beneath a sacred ward", "Chain", AscendantMode.Ward, "Aegis of Dawn", "Dawn rises repeatedly behind your shield", "ShieldSilver", AscendantMode.Ward); AddAscendant(dictionary, PlayerClass.Guardian, 2, 1, AscendantElement.Holy, "Sunlance", "A spear of condensed daylight judges the wicked", "StaffLightning", AscendantMode.Burst, "Day of Judgement", "Judgement arrives in seven expanding dawns", "TrophyValkyrie", AscendantMode.Field); AddAscendant(dictionary, PlayerClass.Ranger, 0, 0, AscendantElement.Pierce, "Northwind Arrow", "A silent arrow rides the north wind beyond mortal range", "ArrowSilver", AscendantMode.Burst, "The Last Horizon", "Every horizon narrows into a single perfect shot", "BowSpineSnap", AscendantMode.Burst); AddAscendant(dictionary, PlayerClass.Ranger, 0, 1, AscendantElement.Pierce, "Runebreaker Bolt", "A runed quarrel sunders armor and the ground beneath it", "BoltCarapace", AscendantMode.Burst, "Siege of the Gods", "An unseen battery answers with waves of impossible bolts", "CrossbowRipper", AscendantMode.Field); AddAscendant(dictionary, PlayerClass.Ranger, 1, 0, AscendantElement.Wild, "Gale Passage", "The wild wind opens a path through every hunting line", "Feathers", AscendantMode.Burst, "Path Beyond Sight", "You become the trail and strike from every step", "TrophyHare", AscendantMode.Field); AddAscendant(dictionary, PlayerClass.Ranger, 1, 1, AscendantElement.Pierce, "Constellation Volley", "A hunter's constellation looses its first rain of stars", "ArrowCarapace", AscendantMode.Field, "Night Without Stars", "The sky disappears behind an endless black rain", "TrophyGjall", AscendantMode.Field); AddAscendant(dictionary, PlayerClass.Ranger, 2, 0, AscendantElement.Poison, "Worldroot Snare", "Ancient roots close around everything that enters the ground", "Root", AscendantMode.Field, "Huntmaster's Labyrinth", "Every escape awakens another trap beneath the prey", "TrophyAbomination", AscendantMode.Field); AddAscendant(dictionary, PlayerClass.Ranger, 2, 1, AscendantElement.Wild, "Skybond", "Hunter and raptor strike within the same heartbeat", "TrophyHatchling", AscendantMode.Companion, "Crown of Talons", "The sovereign raptor circles in widening storms", "TrophySeeker", AscendantMode.Companion); return dictionary; } private static void AddAscendant(Dictionary paths, PlayerClass cls, int branch, int sub, AscendantElement element, string omenName, string omenFlavor, string omenIcon, AscendantMode omenMode, string mythicName, string mythicFlavor, string mythicIcon, AscendantMode mythicMode) { paths[AscendantKey(cls, branch, sub)] = new AscendantPath { OmenName = omenName, OmenFlavor = omenFlavor, OmenIcon = omenIcon, OmenMode = omenMode, MythicName = mythicName, MythicFlavor = mythicFlavor, MythicIcon = mythicIcon, MythicMode = mythicMode, Element = element }; } private static string AscendantKey(PlayerClass cls, int branch, int sub) { string[] array = new string[5]; int num = (int)cls; array[0] = num.ToString(); array[1] = ":"; array[2] = branch.ToString(); array[3] = ":"; array[4] = sub.ToString(); return string.Concat(array); } private static SpellDef CreateAscensionUltimate(PlayerClass cls) { if (AscensionUltimates.TryGetValue(cls, out var value)) { return value; } SpellDef spellDef = new SpellDef { UnlockLevel = 70, Cooldown = 180f, CastTime = 2.5f }; switch (cls) { case PlayerClass.Mage: spellDef.Name = "Convergence of the Nine Realms"; spellDef.StaminaCost = 100f; spellDef.IconItem = "StaffLightning"; break; case PlayerClass.Berserker: spellDef.Name = "Ragnarök Incarnate"; spellDef.StaminaCost = 100f; spellDef.IconItem = "SledgeDemolisher"; spellDef.CastTime = 1.5f; break; case PlayerClass.Necromancer: spellDef.Name = "Sovereign of the Veil"; spellDef.StaminaCost = 100f; spellDef.IconItem = "TrophyWraith"; break; case PlayerClass.Einherjar: spellDef.Name = "Valhalla Descends"; spellDef.StaminaCost = 100f; spellDef.IconItem = "TrophyValkyrie"; spellDef.CastTime = 2f; break; case PlayerClass.Ranger: spellDef.Name = "The Eternal Hunt"; spellDef.StaminaCost = 90f; spellDef.IconItem = "TrophyGjall"; spellDef.CastTime = 1.5f; break; case PlayerClass.Guardian: spellDef.Name = "Aegis of Creation"; spellDef.StaminaCost = 90f; spellDef.IconItem = "ShieldCarapaceBuckler"; spellDef.CastTime = 1.5f; break; default: spellDef.Name = "Yggdrasil Awakens"; spellDef.StaminaCost = 100f; spellDef.IconItem = "YggdrasilWood"; break; } spellDef.Describe = (int level) => AscensionUltimateDescription(cls, level); spellDef.CastAction = delegate(Player player, int level) { ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(AscensionUltimateRoutine(player, level, cls)); }; AscensionUltimates[cls] = spellDef; return spellDef; } private static string AscensionUltimateDescription(PlayerClass cls, int level) { int num = Mathf.Max(1, Mathf.RoundToInt(Progression.Dmg(AscensionBasePower(cls), level))); return cls switch { PlayerClass.Mage => $"Merge fire, frost and lightning into seven expanding cataclysms ({num} power per pulse)", PlayerClass.Berserker => $"Become Ragnarök and shatter the battlefield seven times ({num} power per pulse)", PlayerClass.Necromancer => $"Open the Veil in seven soul-draining eclipses ({num} power per pulse, restores life and minions)", PlayerClass.Einherjar => $"Bring Valhalla to earth in seven waves of thunder and divine steel ({num} power per pulse)", PlayerClass.Ranger => $"Unleash a sevenfold spectral hunt across an expanding kill zone ({num} power per pulse)", PlayerClass.Guardian => $"Raise the first shield in seven radiant waves ({num} power per pulse, heals and wards allies)", _ => $"Awaken Yggdrasil in seven rings of roots and renewal ({num} power per pulse, heals allies)", }; } private static IEnumerator AscensionUltimateRoutine(Player player, int level, PlayerClass cls) { if ((Object)(object)player == (Object)null) { yield break; } Effects.TryCastAnimation(player, "gpower", "staff_summon", "battleaxe_attack"); ApplyAscensionOpeningBuff(player, cls); for (int pulse = 0; pulse < 7; pulse++) { if ((Object)(object)player == (Object)null || ((Character)player).IsDead()) { yield break; } Vector3 position = ((Component)player).transform.position; float num = 7f + (float)pulse * 1.05f; AscendantElement element = AscensionElement(cls, pulse); int hits = AscendantDamage(player, level, element, position, num, AscensionBasePower(cls)); PlayAscendantFx(element, position, Mathf.Max(1f, num / 7f)); SpawnAscensionRing(position + Vector3.up * 0.16f, AscensionColor(cls), num); ApplyAscensionPulseBenefit(player, level, cls, pulse, hits, position, num); yield return (object)new WaitForSeconds(0.58f); } if ((Object)(object)player != (Object)null && !((Character)player).IsDead()) { Vector3 position2 = ((Component)player).transform.position; Effects.TryPlayAtScaled(position2, 2.1f, 8f, "vfx_odin_despawn", "fx_eikthyr_stomp", "vfx_gdking_rootspawn"); SpawnAscensionRing(position2 + Vector3.up * 0.2f, Color.white, 15f); } } private static void ApplyAscensionOpeningBuff(Player player, PlayerClass cls) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) string text = null; switch (cls) { case PlayerClass.Berserker: text = "SE_CDV_Furia"; break; case PlayerClass.Einherjar: text = "SE_CDV_Aegis"; break; case PlayerClass.Guardian: text = "SE_CDV_Baluardo"; break; case PlayerClass.Druid: text = "SE_CDV_Corteccia"; break; } if (!string.IsNullOrEmpty(text)) { Vector3 position = ((Component)player).transform.position; Network.BroadcastBuff(position, 10f, text, 18f); Network.BuffLocalPlayer(position, 10f, text, 18f); } } private static void ApplyAscensionPulseBenefit(Player player, int level, PlayerClass cls, int pulse, int hits, Vector3 center, float radius) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) switch (cls) { case PlayerClass.Necromancer: if (hits > 0) { ((Character)player).Heal(Progression.Heal(3.5f, level) * (float)hits, true); } if (pulse % 2 == 0) { MendOwnedMinions(player, 0.15f); } break; case PlayerClass.Guardian: if (pulse % 2 == 0) { ApplyAscendantWard(player, level, AscendantElement.Holy, center, radius, 8f, 8f); } break; case PlayerClass.Druid: if (pulse % 2 == 0) { ApplyAscendantWard(player, level, AscendantElement.Nature, center, radius, 9f, 8f); } break; case PlayerClass.Einherjar: break; } } private static float AscensionBasePower(PlayerClass cls) { switch (cls) { case PlayerClass.Berserker: return 24f; case PlayerClass.Ranger: return 22f; case PlayerClass.Mage: case PlayerClass.Einherjar: return 21f; case PlayerClass.Necromancer: return 18f; case PlayerClass.Druid: return 17f; case PlayerClass.Guardian: return 16f; default: return 18f; } } private static AscendantElement AscensionElement(PlayerClass cls, int pulse) { return cls switch { PlayerClass.Mage => (new AscendantElement[3] { AscendantElement.Fire, AscendantElement.Frost, AscendantElement.Lightning })[pulse % 3], PlayerClass.Berserker => (new AscendantElement[3] { AscendantElement.Earth, AscendantElement.Blood, AscendantElement.Wild })[pulse % 3], PlayerClass.Necromancer => (new AscendantElement[3] { AscendantElement.Spirit, AscendantElement.Bone, AscendantElement.Poison })[pulse % 3], PlayerClass.Einherjar => (new AscendantElement[3] { AscendantElement.Lightning, AscendantElement.Pierce, AscendantElement.Holy })[pulse % 3], PlayerClass.Ranger => (new AscendantElement[3] { AscendantElement.Pierce, AscendantElement.Wild, AscendantElement.Nature })[pulse % 3], PlayerClass.Guardian => (new AscendantElement[3] { AscendantElement.Holy, AscendantElement.Earth, AscendantElement.Lightning })[pulse % 3], _ => (new AscendantElement[3] { AscendantElement.Nature, AscendantElement.Wild, AscendantElement.Holy })[pulse % 3], }; } private static Color AscensionColor(PlayerClass cls) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) return (Color)(cls switch { PlayerClass.Mage => new Color(0.45f, 0.72f, 1f, 0.95f), PlayerClass.Berserker => new Color(1f, 0.2f, 0.08f, 0.95f), PlayerClass.Necromancer => new Color(0.48f, 0.95f, 0.55f, 0.95f), PlayerClass.Einherjar => new Color(1f, 0.78f, 0.25f, 0.95f), PlayerClass.Ranger => new Color(0.55f, 0.95f, 0.28f, 0.95f), PlayerClass.Guardian => new Color(0.68f, 0.85f, 1f, 0.95f), _ => new Color(0.28f, 1f, 0.62f, 0.95f), }); } private static void SpawnAscensionRing(Vector3 center, Color color, float radius) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("cdv_ascension_wave"); val.transform.position = center; val.AddComponent().Initialize(color, Mathf.Max(1f, radius * 0.18f), radius, 1.25f); } private static SpellDef[] RangerRoster(int branch, int sub) { return branch switch { 0 => sub switch { 1 => ArbalistSpells, 0 => DeadeyeSpells, _ => RangerMarksmanshipBaseOnly, }, 1 => sub switch { 1 => VolleyMasterSpells, 0 => PathfinderSpells, _ => RangerSkirmishingBaseOnly, }, _ => sub switch { 1 => FalconerSpells, 0 => TrapperSpells, _ => RangerWildernessBaseOnly, }, }; } private static SpellDef RangerSpell(string name, int level, float cooldown, float stamina, string icon, float castTime, Func describe, Action cast) { return new SpellDef { Name = name, UnlockLevel = level, Cooldown = cooldown, StaminaCost = stamina, IconItem = icon, CastTime = castTime, Describe = describe, CastAction = cast }; } private static int RangerDamage(int baseline, int level) { return Progression.DmgInt(baseline, level); } public static float RangerCooldownReduction(Player player, string spellName) { return spellName switch { "Aimed Shot" => TalentSystem.Rank(player, "de_a_focus"), "Armor Breaker" => TalentSystem.Rank(player, "arb_a_focus"), "Quickstep" => TalentSystem.Rank(player, "pf_a_focus"), "Split Shot" => TalentSystem.Rank(player, "vm_a_focus"), "Caltrops" => TalentSystem.Rank(player, "tr_a_focus"), "Falcon Strike" => TalentSystem.Rank(player, "fal_a_focus"), "One Shot" => 5f * (float)TalentSystem.Rank(player, "de_d_focus"), "Ballista Salvo" => 5f * (float)TalentSystem.Rank(player, "arb_d_focus"), "Ghost Trail" => 5f * (float)TalentSystem.Rank(player, "pf_d_focus"), "Skyfall Barrage" => 5f * (float)TalentSystem.Rank(player, "vm_d_focus"), "Grand Hunt" => 5f * (float)TalentSystem.Rank(player, "tr_d_focus"), "Apex Companion" => 5f * (float)TalentSystem.Rank(player, "fal_d_focus"), _ => 0f, }; } private static float RangerSpecificMult(Player player, string prefix, string slot) { float num = 1f + 0.08f * (float)TalentSystem.Rank(player, prefix + "_" + slot + "_force"); if (TalentSystem.Has(player, prefix + "_execution")) { num *= 1.05f; } return num; } private static void CastMarkedShot(Player player, int level) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) FireRangerProjectile(player, RangerDamage(13, level), crossbow: false, 42f, Color.white); } private static void CastAimedShot(Player player, int level) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) FireRangerProjectile(player, (float)RangerDamage(25, level) * RangerSpecificMult(player, "de", "a"), crossbow: false, 48f, new Color(1f, 0.82f, 0.35f)); } private static void CastHuntersMark(Player player, int level) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) RangerDirectStrike(player, RangerTargetPoint(player, 32f), 7f, (float)RangerDamage(30, level) * RangerSpecificMult(player, "de", "b"), 25f, "vfx_HitSparks", "vfx_blood_hit"); } private static void CastHeartseeker(Player player, int level) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) float damage = (float)RangerDamage(45, level) * RangerSpecificMult(player, "de", "c"); RangerDirectStrike(player, RangerTargetPoint(player, 38f), 8f, damage, 45f, "vfx_HitSparks", "vfx_blood_hit"); } private static void CastOneShot(Player player, int level) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) float damage = (float)RangerDamage(72, level) * RangerSpecificMult(player, "de", "d"); RangerDirectStrike(player, RangerTargetPoint(player, 45f), 9f, damage, 80f, "vfx_HitSparks", "fx_eikthyr_forwardshockwave"); } private static void CastArmorBreaker(Player player, int level) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) FireRangerProjectile(player, (float)RangerDamage(28, level) * RangerSpecificMult(player, "arb", "a"), crossbow: true, 50f, new Color(0.85f, 0.75f, 0.48f), 90f); } private static void CastPavise(Player player, int level) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) float ttlOverride = 12f + (float)TalentSystem.Rank(player, "arb_b_reach"); PassiveEffects.ApplyTimedEffect(player, "SE_CDV_RangerPavise", ttlOverride); Effects.TryPlayAt(((Component)player).transform.position, "vfx_StaffShield", "sfx_blocked"); } private static void CastSiegeBolt(Player player, int level) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) float num = (float)RangerDamage(48, level) * RangerSpecificMult(player, "arb", "c"); Vector3 center = RangerTargetPoint(player, 38f); RangerDirectStrike(player, center, 9f, num, 120f, "vfx_HitSparks", "vfx_rock_destroyed"); FireRangerProjectile(player, num * 0.55f, crossbow: true, 55f, new Color(1f, 0.65f, 0.25f), 100f); } private static void CastBallistaSalvo(Player player, int level) { ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(RangerSalvo(player, level, 7, "arb", "d", crossbow: true, 0.16f)); } private static void CastEvasiveShot(Player player, int level) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) FireRangerProjectile(player, RangerDamage(11, level), crossbow: false, 40f, new Color(0.65f, 0.9f, 1f)); ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(RangerDash(player, -AimForward(player), 11f, 0.3f, 2.5f)); } private static void CastQuickstep(Player player, int level) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(RangerDash(player, AimForward(player), 15f, 0.35f, 2f)); Effects.TryPlayAt(((Component)player).transform.position, "vfx_Dodge", "vfx_Potion_stamina_medium"); } private static IEnumerator RangerDash(Player player, Vector3 direction, float speed, float duration, float hop) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) direction.y = 0f; if ((Object)(object)player == (Object)null || ((Vector3)(ref direction)).sqrMagnitude < 0.0001f) { yield break; } Vector3 dir = ((Vector3)(ref direction)).normalized; float end = Time.time + duration; bool first = true; while (Time.time < end && (Object)(object)player != (Object)null && !((Character)player).IsDead()) { yield return (object)new WaitForFixedUpdate(); if ((Object)(object)player == (Object)null || (Object)(object)((Character)player).m_body == (Object)null || ((Character)player).IsDead()) { break; } Vector3 linearVelocity = dir * speed; linearVelocity.y = (first ? hop : ((Character)player).m_body.linearVelocity.y); ((Character)player).m_body.linearVelocity = linearVelocity; ((Character)player).m_body.MovePosition(((Character)player).m_body.position + dir * speed * Time.fixedDeltaTime); ((Character)player).m_maxAirAltitude = ((Component)player).transform.position.y; first = false; } } private static void CastRapidFire(Player player, int level) { ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(RangerSalvo(player, level, 5, "pf", "b", crossbow: false, 0.12f)); } private static void CastWindrunner(Player player, int level) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) float ttlOverride = 12f + (float)TalentSystem.Rank(player, "pf_c_reach"); PassiveEffects.ApplyTimedEffect(player, "SE_CDV_RangerWindrunner", ttlOverride); ((Character)player).AddStamina((20f + (float)level * 0.5f) * RangerSpecificMult(player, "pf", "c")); Effects.TryPlayAt(((Component)player).transform.position, "vfx_Potion_stamina_medium", "vfx_Dodge"); } private static void CastGhostTrail(Player player, int level) { ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(GhostTrail(player, level)); } private static IEnumerator GhostTrail(Player player, int level) { PassiveEffects.ApplyTimedEffect(player, "SE_CDV_RangerWindrunner", 5f); for (int i = 0; i < 7; i++) { if ((Object)(object)player == (Object)null) { break; } if (((Character)player).IsDead()) { break; } if ((Object)(object)((Character)player).m_body != (Object)null) { ((Character)player).m_body.linearVelocity = AimForward(player) * 12f + Vector3.up * 0.8f; } FireRangerProjectile(player, (float)RangerDamage(18, level) * RangerSpecificMult(player, "pf", "d"), crossbow: false, 46f, new Color(0.55f, 0.95f, 0.9f)); Effects.TryPlayAt(((Component)player).transform.position, "vfx_Dodge"); yield return (object)new WaitForSeconds(0.14f); } } private static void CastSplitShot(Player player, int level) { FireRangerFan(player, level, 5, 10, "vm", "a", 9f); } private static void CastArrowRain(Player player, int level) { ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(RangerRain(player, level, 12, 12, "vm", "b", 6f, 0.12f)); } private static void CastSuppressingVolley(Player player, int level) { ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(RangerVolleyWaves(player, level)); } private static void CastSkyfallBarrage(Player player, int level) { ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(RangerRain(player, level, 24, 19, "vm", "d", 9f, 0.09f)); } private static void CastSnareTrap(Player player, int level) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) StartRangerTrap(player, RangerTargetPoint(player, 12f), level, 10, "tr", "a", 1f, 25f, 3.5f, RangerTrapKind.Snare); } private static void CastCaltrops(Player player, int level) { ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(CaltropPulses(player, level)); } private static void CastExplosiveTrap(Player player, int level) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) StartRangerTrap(player, RangerTargetPoint(player, 14f), level, 30, "tr", "b", 1.5f, 30f, 5f, RangerTrapKind.Explosive); } private static void CastVenomMine(Player player, int level) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) StartRangerTrap(player, RangerTargetPoint(player, 16f), level, 38, "tr", "c", 1f, 35f, 5.5f, RangerTrapKind.Venom); } private static void CastGrandHunt(Player player, int level) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) Vector3 val = RangerTargetPoint(player, 18f); for (int i = 0; i < 5; i++) { float num = (float)i * (float)Math.PI * 2f / 5f; Vector3 position = val + new Vector3(Mathf.Cos(num), 0f, Mathf.Sin(num)) * 4f; StartRangerTrap(player, position, level, 26, "tr", "d", 0.5f, 35f, 4f, (i % 2 == 0) ? RangerTrapKind.Explosive : RangerTrapKind.Venom); } } private static void CastFalconStrike(Player player, int level) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) Vector3 center = RangerTargetPoint(player, 30f); RangerDirectStrike(player, center, 7f, (float)RangerDamage(22, level) * RangerSpecificMult(player, "fal", "a"), 45f, "vfx_Hatchling_death", "vfx_HitSparks"); } private static void CastScoutsMark(Player player, int level) { ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(FalconMarkStrikes(player, level)); } private static void CastWingstorm(Player player, int level) { ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(Wingstorm(player, level)); } private static void CastApexCompanion(Player player, int level) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)player).transform.position + AimForward(player) * 3f + Vector3.up * 2f; Character val = SpawnMinion(player, "Hatchling", position); if (!((Object)(object)val == (Object)null)) { float num = RangerSpecificMult(player, "fal", "d") * (TalentSystem.Has(player, "fal_capstone") ? 1.2f : 1f); BoostMinion(val, (1.2f + (float)level * 0.01f) * num, 0.75f + (float)level * 0.005f); ZNetView component = ((Component)val).GetComponent(); if ((Object)(object)component != (Object)null && component.IsValid()) { component.GetZDO().Set("cdv_army", 1); } ArmyMinions.Add(val); Effects.TryPlayAt(position, "vfx_Hatchling_death", "fx_summon_start"); ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(ExpireRangerCompanion(val, 35f)); } } private static IEnumerator ExpireRangerCompanion(Character companion, float lifetime) { yield return (object)new WaitForSeconds(lifetime); if ((Object)(object)companion != (Object)null && !companion.IsDead()) { Effects.TryPlayAt(((Component)companion).transform.position, "vfx_Hatchling_death"); DespawnMinion(companion); } ArmyMinions.Remove(companion); } private static IEnumerator RangerSalvo(Player player, int level, int count, string prefix, string slot, bool crossbow, float delay) { int baseline = (crossbow ? 22 : 13); for (int i = 0; i < count; i++) { if ((Object)(object)player == (Object)null) { break; } if (((Character)player).IsDead()) { break; } Vector3 value = Quaternion.AngleAxis(Random.Range(-2.5f, 2.5f), Vector3.up) * AimDirection(player); FireRangerProjectile(player, (float)RangerDamage(baseline, level) * RangerSpecificMult(player, prefix, slot), crossbow, crossbow ? 52f : 45f, (Color)(crossbow ? new Color(1f, 0.7f, 0.3f) : Color.white), 30f, value); yield return (object)new WaitForSeconds(delay); } } private static void FireRangerFan(Player player, int level, int count, int baseline, string prefix, string slot, float spread) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < count; i++) { Vector3 value = Quaternion.AngleAxis(((count == 1) ? 0f : ((float)i / (float)(count - 1) - 0.5f)) * spread * 2f, Vector3.up) * AimDirection(player); FireRangerProjectile(player, (float)RangerDamage(baseline, level) * RangerSpecificMult(player, prefix, slot), crossbow: false, 43f, new Color(0.75f, 0.95f, 0.75f), 15f, value); } } private static IEnumerator RangerRain(Player player, int level, int count, int baseline, string prefix, string slot, float radius, float delay) { Vector3 center = RangerTargetPoint(player, 32f); for (int i = 0; i < count; i++) { if ((Object)(object)player == (Object)null) { break; } if (((Character)player).IsDead()) { break; } Vector2 val = Random.insideUnitCircle * radius; Vector3 val2 = center + new Vector3(val.x, 0f, val.y); DamageEnemiesAround(player, val2, 2.2f, delegate(HitData hit) { hit.m_damage.m_pierce = (float)RangerDamage(baseline, level) * RangerSpecificMult(player, prefix, slot); }, 15f, new string[1] { "vfx_HitSparks" }); Effects.TryPlayAt(val2 + Vector3.up * 0.2f, "vfx_arrowhit"); yield return (object)new WaitForSeconds(delay); } } private static IEnumerator RangerVolleyWaves(Player player, int level) { Vector3 center = RangerTargetPoint(player, 28f); float radius = 7f + (float)TalentSystem.Rank(player, "vm_c_reach"); for (int wave = 0; wave < 3; wave++) { DamageEnemiesAround(player, center, radius, delegate(HitData hit) { hit.m_damage.m_pierce = (float)RangerDamage(18, level) * RangerSpecificMult(player, "vm", "c"); }, 35f, new string[1] { "vfx_HitSparks" }); Effects.TryPlayAt(center, "vfx_arrowhit", "sfx_bow_fire"); yield return (object)new WaitForSeconds(0.55f); } } private static IEnumerator CaltropPulses(Player player, int level) { Vector3 center = RangerTargetPoint(player, 12f); for (int pulse = 0; pulse < 3; pulse++) { DamageEnemiesAround(player, center, 5f, delegate(HitData hit) { hit.m_damage.m_pierce = (float)RangerDamage(9, level) * RangerSpecificMult(player, "tr", "a"); }, 10f, new string[1] { "vfx_HitSparks" }); Effects.TryPlayAt(center, "vfx_rock_destroyed"); yield return (object)new WaitForSeconds(1f); } } private static IEnumerator FalconMarkStrikes(Player player, int level) { Vector3 center = RangerTargetPoint(player, 32f); for (int strike = 0; strike < 3; strike++) { RangerDirectStrike(player, center, 8f, (float)RangerDamage(14, level) * RangerSpecificMult(player, "fal", "b"), 20f, "vfx_Hatchling_death", "vfx_HitSparks"); yield return (object)new WaitForSeconds(0.65f); } } private static IEnumerator Wingstorm(Player player, int level) { float radius = 7f + (float)TalentSystem.Rank(player, "fal_c_reach"); for (int wave = 0; wave < 4; wave++) { DamageEnemiesAround(player, ((Component)player).transform.position, radius, delegate(HitData hit) { hit.m_damage.m_pierce = (float)RangerDamage(20, level) * RangerSpecificMult(player, "fal", "c"); }, 45f, new string[1] { "vfx_HitSparks" }); Effects.TryPlayAt(((Component)player).transform.position, "vfx_Hatchling_death", "vfx_Dodge"); yield return (object)new WaitForSeconds(0.45f); } } private static void StartRangerTrap(Player player, Vector3 position, int level, int baseline, string prefix, string slot, float armDelay, float lifetime, float radius, RangerTrapKind kind) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(RangerTrap(player, position, level, baseline, prefix, slot, armDelay, lifetime, radius, kind)); } private static IEnumerator RangerTrap(Player player, Vector3 position, int level, int baseline, string prefix, string slot, float armDelay, float lifetime, float radius, RangerTrapKind kind) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) Effects.TryPlayAt(position, "vfx_Place_bed", "sfx_build_hammer_wood"); yield return (object)new WaitForSeconds(armDelay); float elapsed = 0f; while (elapsed < lifetime && (Object)(object)player != (Object)null && !((Character)player).IsDead()) { if (EnemiesAround(position, radius).Any()) { float damage = (float)RangerDamage(baseline, level) * RangerSpecificMult(player, prefix, slot); float rangerGeneral = TalentSystem.DamageMult(player, "pierce"); DamageEnemiesAround(player, position, radius, delegate(HitData hit) { if (kind == RangerTrapKind.Explosive) { hit.m_damage.m_fire = damage * 0.55f * rangerGeneral; hit.m_damage.m_blunt = damage * 0.45f * rangerGeneral; } else if (kind == RangerTrapKind.Venom) { hit.m_damage.m_poison = damage * 0.65f * rangerGeneral; hit.m_damage.m_pierce = damage * 0.35f; } else { hit.m_damage.m_pierce = damage; } }, (kind == RangerTrapKind.Snare) ? 5f : 75f, new string[1] { (kind == RangerTrapKind.Venom) ? "vfx_poison" : "vfx_HitSparks" }); Effects.TryPlayAt(position, (kind != RangerTrapKind.Explosive) ? ((kind != RangerTrapKind.Venom) ? new string[2] { "vfx_rock_destroyed", "sfx_trap_arm" } : new string[2] { "vfx_poison", "sfx_blob_attack" }) : new string[2] { "vfx_blob_attack", "sfx_goblin_bomb" }); break; } elapsed += 0.25f; yield return (object)new WaitForSeconds(0.25f); } } private static GameObject FireRangerProjectile(Player player, float damage, bool crossbow, float speed, Color glow, float push = 15f, Vector3? direction = null) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) Effects.TryCastAnimation(player, crossbow ? "crossbow_fire" : "bow_fire", "gpower"); HitData val = new HitData(); val.m_damage.m_pierce = damage; val.m_pushForce = push; val.SetAttacker((Character)(object)player); Vector3 dir = (Vector3)(((??)direction) ?? AimDirection(player)); GameObject obj = (crossbow ? LaunchProjectile(player, "bolt_carapace_projectile", dir, speed, val, "arrow_wood_projectile", "ancientbarkspear_projectile") : LaunchProjectile(player, "arrow_wood_projectile", dir, speed, val, "ancientbarkspear_projectile")); AddProjectileGlow(obj, glow); return obj; } private static bool RangerDirectStrike(Player player, Vector3 center, float searchRadius, float damage, float push, params string[] effects) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Expected O, but got Unknown //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) Character val = (from enemy in EnemiesAround(center, searchRadius) orderby Vector3.Distance(((Component)enemy).transform.position, center) select enemy).FirstOrDefault(); if ((Object)(object)val == (Object)null) { FireRangerProjectile(player, damage, BranchSystem.GetBranch(player) == 0 && BranchSystem.GetSubSpec(player) == 1, 50f, Color.white, push); return false; } if (val.GetHealth() / Mathf.Max(1f, val.GetMaxHealth()) <= 0.35f) { string text = RangerCallingPrefix(player); if (TalentSystem.Has(player, text + "_execution")) { damage *= 1.15f; } } HitData val2 = new HitData(); val2.m_damage.m_pierce = damage; TalentSystem.ApplyDamageTalents(player, val2); val2.m_pushForce = push; val2.m_point = ((Component)val).transform.position; Vector3 val3 = ((Component)val).transform.position - ((Component)player).transform.position; val2.m_dir = ((Vector3)(ref val3)).normalized; val2.SetAttacker((Character)(object)player); val.Damage(val2); Effects.TryPlayAt(((Component)val).transform.position + Vector3.up, effects); return true; } private static string RangerCallingPrefix(Player player) { int branch = BranchSystem.GetBranch(player); int subSpec = BranchSystem.GetSubSpec(player); switch (branch) { case 0: if (subSpec != 0) { return "arb"; } return "de"; case 1: if (subSpec != 0) { return "vm"; } return "pf"; default: if (subSpec != 0) { return "fal"; } return "tr"; } } private static Vector3 RangerTargetPoint(Player player, float range) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) Vector3 val = EyePosition(player); Vector3 val2 = AimDirection(player); RaycastHit val3 = default(RaycastHit); if (Physics.Raycast(val, val2, ref val3, range, -5)) { return ((RaycastHit)(ref val3)).point; } Vector3 val4 = ((Component)player).transform.position + val2 * range; if ((Object)(object)ZoneSystem.instance != (Object)null) { val4.y = ZoneSystem.instance.GetGroundHeight(val4); } return val4; } } internal sealed class AscensionWaveVisual : MonoBehaviour { private const int Segments = 96; private LineRenderer _line; private Light _light; private Color _color; private float _startRadius; private float _endRadius; private float _lifetime; private float _born; public void Initialize(Color color, float startRadius, float endRadius, float lifetime) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown _color = color; _startRadius = startRadius; _endRadius = endRadius; _lifetime = lifetime; _born = Time.time; _line = ((Component)this).gameObject.AddComponent(); _line.useWorldSpace = false; _line.loop = true; _line.positionCount = 96; _line.numCornerVertices = 2; _line.numCapVertices = 2; ((Renderer)_line).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)_line).receiveShadows = false; Shader val = Shader.Find("Sprites/Default"); if ((Object)(object)val != (Object)null) { ((Renderer)_line).material = new Material(val); } _light = ((Component)this).gameObject.AddComponent(); _light.type = (LightType)2; _light.color = color; _light.range = Mathf.Max(8f, endRadius); _light.shadows = (LightShadows)0; Draw(0f); } private void Update() { float num = Mathf.Clamp01((Time.time - _born) / Mathf.Max(0.01f, _lifetime)); Draw(num); if (num >= 1f) { Object.Destroy((Object)(object)((Component)this).gameObject); } } private void Draw(float t) { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_line == (Object)null)) { float num = Mathf.Lerp(_startRadius, _endRadius, Mathf.SmoothStep(0f, 1f, t)); float num2 = (1f - t) * _color.a; Color val = default(Color); ((Color)(ref val))..ctor(_color.r, _color.g, _color.b, num2); _line.startColor = val; _line.endColor = val; _line.startWidth = Mathf.Lerp(0.34f, 0.05f, t); _line.endWidth = _line.startWidth; for (int i = 0; i < 96; i++) { float num3 = (float)i * (float)Math.PI * 2f / 96f; _line.SetPosition(i, new Vector3(Mathf.Cos(num3) * num, 0f, Mathf.Sin(num3) * num)); } if ((Object)(object)_light != (Object)null) { _light.intensity = (1f - t) * 1.8f; } } } } public class SubSpecDef { public string Name; public string Role; public string Description; public string CapstoneId; public TalentNode[] Tree; } public class BranchDef { public string Name; public string Color; public string Description; public string BaseSpellHint; public TalentNode[] Tree; public SubSpecDef[] Subs; public bool ComingSoon; public string[] PlannedSubNames; } public static class BranchSystem { public const string KeyBranch = "cdv_branch"; public const string KeySubSpec = "cdv_subspec"; private const string NotableColor = "#ffd27a"; private const string CapstoneColor = "#ffdd55"; public static readonly Dictionary Defs; private static readonly Dictionary> IdCache; static BranchSystem() { Defs = new Dictionary { { PlayerClass.Mage, new BranchDef[3] { new BranchDef { Name = "Fire", Color = "#ff8c4a", Description = "The devouring flame: raw damage that burns everything.", BaseSpellHint = "Fireball", Tree = new TalentNode[6] { new TalentNode("mage_pyro", "Kindling", "+4% fire damage per rank", 4, 0, 1, null, null, "SurtlingCore"), new TalentNode("mg_kindling", "Searing Focus", "Fireball cooldown -1 s per rank", 2, 1, 0, "mage_pyro", null, "Resin"), new TalentNode("dst_burn", "Twin Flame", "Fireball deals +10% more per rank", 2, 1, 2, "mage_pyro", null, "StaffFireball"), new TalentNode("fb_emberward", "Ember Ward", "+4 armor per rank", 2, 2, 0, null, null, "ArmorLeatherChest"), new TalentNode("fb_warmblood", "Warm Blood", "+4% stamina regeneration per rank", 2, 2, 2, null, null, "Honey"), new TalentNode("fb_burningsoul", "Burning Soul", "+10% fire damage and -5% ability stamina cost", 1, 3, 1, "dst_burn", "#ffd27a", "TrophySurtling") }, Subs = new SubSpecDef[2] { new SubSpecDef { Name = "Pyromancer", Role = "Burst Damage", Description = "The flame unleashed: Ring of Fire, Flame Wave, Pillar of Flame and the Meteor Shower.", CapstoneId = "pyr_capstone", Tree = new TalentNode[17] { new TalentNode("dst_firepower", "Pyromania", "+3% fire damage per rank", 5, 0, 0, null, null, "SurtlingCore"), new TalentNode("pyr_manawell", "Mana Well", "+7% eitr regeneration per rank", 5, 0, 1, null, null, "Eitr"), new TalentNode("mage_blazing", "Blazing Ring", "Ring of Fire deals +8% more per rank", 4, 1, 0, "dst_firepower", null, "StaffFireball"), new TalentNode("dst_ring", "Ring Mastery", "Ring of Fire cooldown -2 s per rank", 4, 1, 1, null, null, "SurtlingCore"), new TalentNode("dst_combustion", "Twin Cinders", "Ring of Fire hurls +1 fireball per rank", 3, 2, 0, "mage_blazing", null, "StaffFireball"), new TalentNode("pyr_cauterize", "Cauterize", "Casting Ring of Fire mends your wounds (per rank)", 4, 2, 1, null, null, "Raspberry"), new TalentNode("syn_flamelord", "Flamelord", "+10% fire damage, Fireball cooldown -2 s", 1, 3, 0, null, "#ffd27a", "TrophySurtling"), new TalentNode("pyr_efficient", "Efficient Casting", "-5% ability stamina cost per rank", 4, 3, 1, null, null, "Honey"), new TalentNode("pyr_waverider", "Wave Rider", "Flame Wave deals +10% more per rank", 5, 4, 0, null, null, "Coal"), new TalentNode("pyr_wavefocus", "Wave Focus", "Flame Wave cooldown -1 s per rank", 3, 4, 1, "pyr_waverider", null, "Flint"), new TalentNode("pyr_pillarforce", "Towering Pillar", "Pillar of Flame deals +10% more per rank", 5, 5, 0, null, null, "GoblinTotem"), new TalentNode("pyr_vitality", "Arcane Vitality", "+5% health regeneration per rank", 5, 5, 1, null, null, "MeadHealthMinor"), new TalentNode("pyr_twinpillar", "Twin Pillars", "Pillar of Flame strikes a second enemy", 1, 6, 0, "pyr_pillarforce", "#ffd27a", "GoblinTotem"), new TalentNode("pyr_pillarfocus", "Pillar Focus", "Pillar of Flame cooldown -2 s per rank", 3, 6, 1, null, null, "Flint"), new TalentNode("mage_cataclysm", "Cataclysm", "Meteors deal +8% more per rank", 5, 7, 0, null, null, "GoblinTotem"), new TalentNode("dst_annihilation", "Annihilation", "Meteor Shower cooldown -5 s per rank", 3, 7, 1, null, null, "GoblinTotem"), new TalentNode("pyr_capstone", "Avatar of Fire", "Your capstone aura blazes and ALL fire deals +20% more", 1, 8, 0, null, "#ffdd55", "TrophySurtling") } }, new SubSpecDef { Name = "Flame Summoner", Role = "Minion Damage", Description = "The forge awakened: Fire Imps, Burning Ground, a Magma Elemental and the Legion of Cinders.", CapstoneId = "smn_capstone", Tree = new TalentNode[17] { new TalentNode("smn_stokeforge", "Stoke the Forge", "Your summons deal +6% more damage per rank", 5, 0, 0, null, null, "Coal"), new TalentNode("smn_manawell", "Mana Well", "+7% eitr regeneration per rank", 5, 0, 1, null, null, "Eitr"), new TalentNode("smn_sturdyimps", "Sturdy Imps", "Your summons have +10% health per rank", 4, 1, 0, "smn_stokeforge", null, "TrophySurtling"), new TalentNode("smn_emberbond", "Ember Bond", "+3% fire damage per rank", 4, 1, 1, null, null, "SurtlingCore"), new TalentNode("smn_twinimp", "Twin Imp", "+1 max Fire Imp", 1, 2, 0, "smn_sturdyimps", "#ffd27a", "TrophySurtling"), new TalentNode("smn_impfury", "Imp Fury", "Your summons deal +8% more damage per rank", 4, 2, 1, "smn_stokeforge", null, "SurtlingCore"), new TalentNode("smn_groundcrew", "Ground Crew", "Burning Ground +1 m radius per rank", 3, 3, 0, null, null, "Tar"), new TalentNode("smn_lastingash", "Lasting Ash", "Burning Ground lasts +2 s per rank", 4, 3, 1, null, null, "Coal"), new TalentNode("smn_emberpact", "Ember Pact", "Burning Ground also mends your summons", 1, 4, 0, "smn_groundcrew", "#ffd27a", "Raspberry"), new TalentNode("smn_searingground", "Searing Ground", "Burning Ground burns +8% hotter per rank", 5, 4, 1, "smn_groundcrew", null, "Ooze"), new TalentNode("smn_magmaborn", "Magma Born", "Magma Elemental +10% damage and health per rank", 4, 5, 0, null, null, "Obsidian"), new TalentNode("smn_elementalfocus", "Elemental Focus", "Magma Elemental cooldown -3 s per rank", 3, 5, 1, null, null, "Flint"), new TalentNode("smn_moltencore", "Molten Core", "Magma Elemental deals +10% more per rank", 4, 6, 0, "smn_magmaborn", null, "SurtlingCore"), new TalentNode("smn_vitality", "Arcane Vitality", "+5% health regeneration per rank", 5, 6, 1, null, null, "MeadHealthMinor"), new TalentNode("smn_legiondrill", "Legion Drill", "Legion of Cinders lasts +10 s per rank", 4, 7, 0, null, null, "TrophySurtling"), new TalentNode("smn_greaterlegion", "Greater Legion", "Legion of Cinders calls +1 imp per rank", 3, 7, 1, "smn_legiondrill", null, "TrophySurtling"), new TalentNode("smn_capstone", "Lord of Cinders", "Your capstone aura smolders, your summons deal +20% more and +1 max Fire Imp", 1, 8, 0, null, "#ffdd55", "TrophySurtling") } } } }, new BranchDef { Name = "Frost", Color = "#7ec8ff", Description = "The biting cold: control, shards and wards.", BaseSpellHint = "Ice Shards", Tree = new TalentNode[6] { new TalentNode("mage_cryo", "Biting Cold", "+4% frost damage per rank", 4, 0, 1, null, null, "FreezeGland"), new TalentNode("dst_shards", "Razor Shards", "Ice Shards deal +10% more per rank", 2, 1, 0, "mage_cryo", null, "StaffIceShards"), new TalentNode("fr_shardfocus", "Shard Focus", "Ice Shards cooldown -1 s per rank", 2, 1, 2, "mage_cryo", null, "Flint"), new TalentNode("mage_splitter", "Splinter", "Ice Shards fires 2 extra shards", 1, 2, 0, "dst_shards", null, "Obsidian"), new TalentNode("fr_rimeguard", "Rimeguard", "+4 armor per rank", 2, 2, 2, null, null, "TrollHide"), new TalentNode("fr_frozenheart", "Frozen Heart", "+10% frost damage and +10% stamina regeneration", 1, 3, 1, "dst_shards", "#ffd27a", "TrophyFenring") }, Subs = new SubSpecDef[2] { new SubSpecDef { Name = "Cryomancer", Role = "Burst Damage", Description = "Winter unleashed: Frost Nova, Glacial Spike, the channeled Blizzard and Absolute Zero.", CapstoneId = "cry_capstone", Tree = new TalentNode[17] { new TalentNode("dst_deepfreeze", "Deep Frost", "+3% frost damage per rank", 5, 0, 0, null, null, "FreezeGland"), new TalentNode("cry_manawell", "Mana Well", "+7% eitr regeneration per rank", 5, 0, 1, null, null, "Eitr"), new TalentNode("mg_frostbite", "Frostbite", "Frost Nova deals +10% more per rank", 4, 1, 0, "dst_deepfreeze", null, "FreezeGland"), new TalentNode("mage_widenova", "Wider Nova", "Frost Nova radius +6% per rank", 4, 1, 1, null, null, "Crystal"), new TalentNode("cry_spikeforce", "Heavy Spike", "Glacial Spike deals +10% more per rank", 4, 2, 0, "mg_frostbite", null, "StaffIceShards"), new TalentNode("cry_spikefocus", "Spike Focus", "Glacial Spike cooldown -1 s per rank", 3, 2, 1, null, null, "Flint"), new TalentNode("syn_frostborn", "Frostborn", "+10% frost damage, Frost Nova cooldown -3 s", 1, 3, 0, null, "#ffd27a", "TrophyFenring"), new TalentNode("cry_efficient", "Efficient Casting", "-5% ability stamina cost per rank", 4, 3, 1, null, null, "Honey"), new TalentNode("cry_blizzforce", "Raging Blizzard", "Blizzard deals +10% more per rank", 5, 4, 0, null, null, "FreezeGland"), new TalentNode("cry_blizzwide", "Wide Blizzard", "Blizzard covers +1 m per rank", 3, 4, 1, null, null, "Crystal"), new TalentNode("cry_shatter", "Shatter", "+3% frost damage per rank", 5, 5, 0, null, null, "Obsidian"), new TalentNode("cry_vitality", "Arcane Vitality", "+5% health regeneration per rank", 5, 5, 1, null, null, "MeadHealthMinor"), new TalentNode("cry_zero", "Deep Winter", "Absolute Zero hits +25% harder and hurls enemies twice as far", 1, 6, 0, "cry_blizzforce", "#ffd27a", "TrophyFenring"), new TalentNode("cry_blizzfocus", "Blizzard Focus", "Blizzard cooldown -2 s per rank", 3, 6, 1, null, null, "Flint"), new TalentNode("cry_zeroforce", "Zero Point", "Absolute Zero deals +8% more per rank", 5, 7, 0, null, null, "TrophyDragonQueen"), new TalentNode("cry_zerofocus", "Winter's Call", "Absolute Zero cooldown -5 s per rank", 3, 7, 1, null, null, "Flint"), new TalentNode("cry_capstone", "Avatar of Winter", "Your capstone aura glitters and ALL frost deals +20% more", 1, 8, 0, null, "#ffdd55", "TrophyDragonQueen") } }, new SubSpecDef { Name = "Frostwarden", Role = "Defense / Support", Description = "The unbreakable ward: Rune Shield, Frost Armor, Winter's Grasp and the Fimbulwinter.", CapstoneId = "fw_capstone", Tree = new TalentNode[17] { new TalentNode("fw_coldblood", "Cold Blood", "+3% frost damage per rank", 5, 0, 0, null, null, "FreezeGland"), new TalentNode("fw_manawell", "Mana Well", "+7% eitr regeneration per rank", 5, 0, 1, null, null, "Eitr"), new TalentNode("mage_runicward", "Runic Ward", "Rune Shield dome +3 m", 1, 1, 0, "fw_coldblood", null, "StaffShield"), new TalentNode("fw_armorforce", "Hardened Rime", "Frost Armor grants +6 armor per rank", 5, 1, 1, null, null, "ArmorWolfChest"), new TalentNode("mage_enduring", "Enduring Runes", "Rune Shield lasts 50% longer", 1, 2, 0, "mage_runicward", null, "StaffShield"), new TalentNode("fw_armorlong", "Lasting Rime", "Frost Armor lasts +5 s per rank", 4, 2, 1, "fw_armorforce", null, "FreezeGland"), new TalentNode("fw_wardkeeper", "Wardkeeper", "+10% frost damage and Rune Shield cooldown -10 s", 1, 3, 0, null, "#ffd27a", "StaffShield"), new TalentNode("fw_efficient", "Efficient Casting", "-5% ability stamina cost per rank", 4, 3, 1, null, null, "Honey"), new TalentNode("mage_secondwind", "Second Wind", "Casting Rune Shield heals you", 1, 4, 0, "mage_enduring", null, "MeadHealthMedium"), new TalentNode("fw_graspwide", "Creeping Winter", "Winter's Grasp covers +1 m per rank", 4, 4, 1, null, null, "Crystal"), new TalentNode("fw_graspforce", "Biting Grasp", "Winter's Grasp bites +10% harder per rank", 5, 5, 0, null, null, "FreezeGland"), new TalentNode("fw_vitality", "Arcane Vitality", "+5% health regeneration per rank", 5, 5, 1, null, null, "MeadHealthMinor"), new TalentNode("fw_chillguard", "Chilling Rebuke", "Frost Armor bites whoever strikes you", 1, 6, 0, "fw_armorforce", "#ffd27a", "ArmorWolfChest"), new TalentNode("fw_graspfocus", "Grasp Focus", "Winter's Grasp cooldown -2 s per rank", 4, 6, 1, null, null, "Flint"), new TalentNode("fw_fimbulforce", "World's End", "Fimbulwinter deals +10% more per rank", 5, 7, 0, null, null, "TrophySGolem"), new TalentNode("fw_fimbulfocus", "Endless Winter", "Fimbulwinter cooldown -5 s per rank", 4, 7, 1, null, null, "Flint"), new TalentNode("fw_capstone", "Heart of the Glacier", "Your capstone aura freezes, Rune Shield +3 m more and Frost Armor 50% stronger", 1, 8, 0, null, "#ffdd55", "TrophySGolem") } } } }, new BranchDef { Name = "Lightning", Color = "#ffe066", Description = "The wrath of the sky: bolts and rolling storms.", BaseSpellHint = "Lightning Bolt", Tree = new TalentNode[6] { new TalentNode("mage_fulm", "Static Charge", "+4% lightning damage per rank", 4, 0, 1, null, null, "Thunderstone"), new TalentNode("dst_boltmastery", "Conduit", "Lightning Bolt deals +10% more per rank", 2, 1, 0, "mage_fulm", null, "StaffLightning"), new TalentNode("dst_arc", "Bolt Focus", "Lightning Bolt cooldown -1 s per rank", 2, 1, 2, "mage_fulm", null, "Flint"), new TalentNode("mage_velocity", "Galvanized", "+15% projectile speed per rank", 2, 2, 0, null, null, "Feathers"), new TalentNode("mage_stormlance", "Stormlance", "Lightning Bolt deals +10% more per rank", 3, 2, 2, "dst_boltmastery", null, "StaffLightning"), new TalentNode("lt_stormsoul", "Storm Soul", "+10% lightning damage and +10% stamina regeneration", 1, 3, 1, "dst_arc", "#ffd27a", "TrophyEikthyr") }, Subs = new SubSpecDef[2] { new SubSpecDef { Name = "Stormcaller", Role = "Area Damage", Description = "The rolling thunder: Chain Lightning, Static Field, Lightning Storm and the Wrath of Thor.", CapstoneId = "st_capstone", Tree = new TalentNode[17] { new TalentNode("st_charged", "Charged", "+3% lightning damage per rank", 5, 0, 0, null, null, "Thunderstone"), new TalentNode("st_manawell", "Mana Well", "+7% eitr regeneration per rank", 5, 0, 1, null, null, "Eitr"), new TalentNode("st_chainforce", "Forked Bolts", "Chain Lightning deals +10% more per rank", 4, 1, 0, "st_charged", null, "StaffLightning"), new TalentNode("st_chainjump", "Long Arc", "Chain Lightning bounces +1 time per rank", 3, 1, 1, null, null, "Chain"), new TalentNode("st_chainfocus", "Chain Focus", "Chain Lightning cooldown -1 s per rank", 3, 2, 0, "st_chainforce", null, "Flint"), new TalentNode("st_efficient", "Efficient Casting", "-5% ability stamina cost per rank", 4, 2, 1, null, null, "Honey"), new TalentNode("st_stormlord", "Stormlord", "+10% lightning damage and Lightning Storm cooldown -5 s", 1, 3, 0, null, "#ffd27a", "TrophyEikthyr"), new TalentNode("st_fieldwide", "Wide Field", "Static Field covers +1 m per rank", 4, 3, 1, null, null, "Chain"), new TalentNode("st_fieldforce", "Live Wire", "Static Field shocks +10% harder per rank", 5, 4, 0, null, null, "Thunderstone"), new TalentNode("st_fieldlong", "Standing Storm", "Static Field lasts +2 s per rank", 3, 4, 1, null, null, "Chain"), new TalentNode("dst_overcharge", "Overcharge", "Storm bolts deal +10% more per rank", 4, 5, 0, null, null, "Thunderstone"), new TalentNode("st_vitality", "Arcane Vitality", "+5% health regeneration per rank", 5, 5, 1, null, null, "MeadHealthMinor"), new TalentNode("mage_tempest", "Tempest", "Lightning Storm strikes 4 extra bolts", 1, 6, 0, "dst_overcharge", "#ffd27a", "Thunderstone"), new TalentNode("st_stormfocus", "Storm Focus", "Lightning Storm cooldown -2 s per rank", 3, 6, 1, null, null, "Flint"), new TalentNode("st_wrathforce", "Thunder God", "Wrath of Thor deals +8% more per rank", 5, 7, 0, null, null, "SledgeStagbreaker"), new TalentNode("st_wrathfocus", "Sky's Favor", "Wrath of Thor cooldown -5 s per rank", 3, 7, 1, null, null, "Flint"), new TalentNode("st_capstone", "Avatar of the Storm", "Your capstone aura crackles and ALL lightning deals +20% more", 1, 8, 0, null, "#ffdd55", "TrophyEikthyr") } }, new SubSpecDef { Name = "Tempest", Role = "Skirmisher", Description = "The storm on the move: Blink, Storm Shroud, Ball Lightning and the Eye of the Storm.", CapstoneId = "tm_capstone", Tree = new TalentNode[17] { new TalentNode("tm_charged", "Static Veins", "+3% lightning damage per rank", 5, 0, 0, null, null, "Thunderstone"), new TalentNode("tm_manawell", "Mana Well", "+7% eitr regeneration per rank", 5, 0, 1, null, null, "Eitr"), new TalentNode("tm_blinkrange", "Long Step", "Blink travels +2 m per rank", 3, 1, 0, "tm_charged", null, "Feathers"), new TalentNode("tm_blinkfocus", "Swift Step", "Blink cooldown -1 s per rank", 3, 1, 1, null, null, "Flint"), new TalentNode("tm_shroudforce", "Sharp Shroud", "Storm Shroud zaps +10% harder per rank", 4, 2, 0, null, null, "Wisp"), new TalentNode("tm_shroudlong", "Clinging Static", "Storm Shroud lasts +5 s per rank", 4, 2, 1, null, null, "Chain"), new TalentNode("tm_slipstream", "Slipstream", "Blinking surges you with power (+attack for 5 s)", 1, 3, 0, "tm_blinkrange", "#ffd27a", "Feathers"), new TalentNode("tm_efficient", "Efficient Casting", "-5% ability stamina cost per rank", 4, 3, 1, null, null, "Honey"), new TalentNode("tm_ballforce", "Thunderball", "Ball Lightning deals +10% more per rank", 4, 4, 0, null, null, "Wisp"), new TalentNode("tm_balllife", "Rolling Sphere", "Ball Lightning lasts +1 s per rank", 3, 4, 1, null, null, "GreydwarfEye"), new TalentNode("tm_ballfocus", "Ball Focus", "Ball Lightning cooldown -2 s per rank", 3, 5, 0, "tm_ballforce", null, "Flint"), new TalentNode("tm_vitality", "Arcane Vitality", "+5% health regeneration per rank", 5, 5, 1, null, null, "MeadHealthMinor"), new TalentNode("tm_stormdancer", "Storm Dancer", "While Storm Shroud crackles you run lighter (-30% stamina drain)", 1, 6, 0, "tm_shroudforce", "#ffd27a", "Feathers"), new TalentNode("tm_eyewide", "Growing Eye", "Eye of the Storm covers +1 m per rank", 3, 6, 1, null, null, "Crystal"), new TalentNode("tm_eyeforce", "Perfect Storm", "Eye of the Storm deals +8% more per rank", 5, 7, 0, null, null, "TrophyEikthyr"), new TalentNode("tm_eyefocus", "Calm Eye", "Eye of the Storm cooldown -5 s per rank", 3, 7, 1, null, null, "Flint"), new TalentNode("tm_capstone", "Avatar of the Tempest", "Your capstone aura dances and ALL lightning deals +20% more", 1, 8, 0, null, "#ffdd55", "TrophyEikthyr") } } } } } }, { PlayerClass.Berserker, new BranchDef[3] { new BranchDef { Name = "Crushing", Color = "#e0803a", Description = "The weight of the mountain: blunt blows that stagger and hurl.", BaseSpellHint = "Crushing Blow", Tree = new TalentNode[6] { new TalentNode("cr_crush", "Crushing Power", "+4% blunt damage per rank", 4, 0, 1, null, null, "MaceBronze"), new TalentNode("cr_stagger", "Stagger", "Crushing Blow staggers +25% harder per rank", 2, 1, 0, "cr_crush", null, "SledgeStagbreaker"), new TalentNode("cr_force", "Brute Force", "Crushing Blow deals +10% more per rank", 2, 1, 2, "cr_crush", null, "MaceIron"), new TalentNode("cr_hardy", "Hardened", "+4 armor per rank", 2, 2, 0, null, null, "ArmorBronzeChest"), new TalentNode("cr_endure", "Endurance", "+4% stamina regeneration per rank", 2, 2, 2, null, null, "Honey"), new TalentNode("cr_notable", "Unstoppable", "+10% blunt damage and Crushing Blow cooldown -1 s", 1, 3, 1, "cr_force", "#ffd27a", "TrophySGolem") }, Subs = new SubSpecDef[2] { new SubSpecDef { Name = "Juggernaut", Role = "Bruiser", Description = "The unstoppable wall: Crushing Blow, Iron Skin, War Cry, Berserker Fury and Titanic Slam.", CapstoneId = "jug_capstone", Tree = new TalentNode[17] { new TalentNode("jug_might", "Might", "+3% blunt damage per rank", 5, 0, 0, null, null, "MaceIron"), new TalentNode("jug_toughness", "Toughness", "+4 armor per rank", 5, 0, 1, null, null, "ArmorBronzeChest"), new TalentNode("jug_ironhide", "Iron Hide", "Iron Skin grants +8 armor per rank", 4, 1, 0, "jug_might", null, "ArmorIronChest"), new TalentNode("jug_warforce", "War Cry Force", "War Cry deals +10% more per rank", 4, 1, 1, null, null, "TrophyBoar"), new TalentNode("jug_ironlong", "Lasting Iron", "Iron Skin lasts +5 s per rank", 3, 2, 0, "jug_ironhide", null, "ArmorIronLegs"), new TalentNode("jug_warpush", "Deafening Cry", "War Cry radius +1 m per rank", 3, 2, 1, "jug_warforce", null, "TankardOdin"), new TalentNode("jug_relentless", "Relentless", "+10% blunt damage and Iron Skin cooldown -10 s", 1, 3, 0, "jug_ironhide", "#ffd27a", "TrophyLox"), new TalentNode("jug_endurance", "Endurance", "+4% stamina regeneration per rank", 4, 3, 1, null, null, "Honey"), new TalentNode("jug_furyforce", "Savage Fury", "Berserker Fury grants +5% more damage per rank", 3, 4, 0, null, null, "Bloodbag"), new TalentNode("jug_furylong", "Enduring Rage", "Berserker Fury lasts +3 s per rank", 4, 4, 1, null, null, "TrophyDeathsquito"), new TalentNode("jug_ironwill", "Iron Will", "Casting Iron Skin heals you", 1, 5, 0, null, null, "MeadHealthMedium"), new TalentNode("jug_vitality", "Vitality", "+5% health regeneration per rank", 5, 5, 1, null, null, "MeadHealthMinor"), new TalentNode("jug_slamforce", "Crushing Slam", "Titanic Slam deals +8% more per rank", 5, 6, 0, null, null, "SledgeIron"), new TalentNode("jug_slamwide", "Wide Slam", "Titanic Slam radius +1 m per rank", 3, 6, 1, null, null, "Stone"), new TalentNode("jug_unbreakable", "Unbreakable", "Iron Skin is 50% stronger", 1, 7, 0, "jug_ironhide", "#ffd27a", "ArmorIronChest"), new TalentNode("jug_slamfocus", "Slam Focus", "Titanic Slam cooldown -5 s per rank", 3, 7, 1, null, null, "Flint"), new TalentNode("jug_capstone", "Avatar of the Mountain", "Your capstone aura quakes and ALL blunt deals +20% more", 1, 8, 0, null, "#ffdd55", "TrophySGolem") } }, new SubSpecDef { Name = "Earthshaker", Role = "Area Damage", Description = "The wrath of the ground: Crushing Blow, Seismic Blow, Fault Line, War Cry and the Cataclysm.", CapstoneId = "ea_capstone", Tree = new TalentNode[17] { new TalentNode("ea_quake", "Quakeblood", "+3% blunt damage per rank", 5, 0, 0, null, null, "SledgeStagbreaker"), new TalentNode("ea_toughness", "Toughness", "+4 armor per rank", 5, 0, 1, null, null, "ArmorBronzeChest"), new TalentNode("ea_seisforce", "Seismic Force", "Seismic Blow deals +10% more per rank", 4, 1, 0, "ea_quake", null, "SledgeIron"), new TalentNode("ea_seiswide", "Wide Tremor", "Seismic Blow radius +1 m per rank", 3, 1, 1, null, null, "Stone"), new TalentNode("ea_faultforce", "Deep Fault", "Fault Line deals +10% more per rank", 5, 2, 0, "ea_seisforce", null, "SledgeStagbreaker"), new TalentNode("ea_faultlong", "Long Fault", "Fault Line reaches +2 m per rank", 3, 2, 1, null, null, "Stone"), new TalentNode("ea_groundbreaker", "Groundbreaker", "+10% blunt damage and Seismic Blow cooldown -3 s", 1, 3, 0, "ea_seisforce", "#ffd27a", "SledgeStagbreaker"), new TalentNode("ea_endurance", "Endurance", "+4% stamina regeneration per rank", 4, 3, 1, null, null, "Honey"), new TalentNode("ea_warforce", "Booming Cry", "War Cry deals +10% more per rank", 4, 4, 0, null, null, "TrophyBoar"), new TalentNode("ea_stagger", "Staggering Blows", "Seismic Blow and Fault Line stagger +50% harder per rank", 2, 4, 1, null, null, "TrophyFenring"), new TalentNode("ea_seisfocus", "Seismic Focus", "Seismic Blow cooldown -2 s per rank", 3, 5, 0, null, null, "Flint"), new TalentNode("ea_vitality", "Vitality", "+5% health regeneration per rank", 5, 5, 1, null, null, "MeadHealthMinor"), new TalentNode("ea_cataforce", "Cataclysmic", "Cataclysm deals +8% more per rank", 5, 6, 0, null, null, "SledgeDemolisher"), new TalentNode("ea_catawide", "Wide Cataclysm", "Cataclysm radius +1 m per rank", 3, 6, 1, null, null, "Stone"), new TalentNode("ea_aftershock", "Aftershock", "Cataclysm's second wave hits 50% harder", 1, 7, 0, "ea_cataforce", "#ffd27a", "SledgeIron"), new TalentNode("ea_catafocus", "Cataclysm Focus", "Cataclysm cooldown -5 s per rank", 3, 7, 1, null, null, "Flint"), new TalentNode("ea_capstone", "Avatar of the Earth", "Your capstone aura shatters the ground and ALL blunt deals +20% more", 1, 8, 0, null, "#ffdd55", "TrophySGolem") } } } }, new BranchDef { Name = "Rending", Color = "#c0424a", Description = "The hungry blade: cuts that bleed and cleave through crowds.", BaseSpellHint = "Cleave", Tree = new TalentNode[6] { new TalentNode("re_edge", "Cutting Edge", "+4% slash damage per rank", 4, 0, 1, null, null, "AxeIron"), new TalentNode("re_bleed", "Bleeding Edge", "Cleave bleeds enemies for +1 s per rank", 2, 1, 0, "re_edge", null, "Bloodbag"), new TalentNode("re_force", "Sharpness", "Cleave deals +10% more per rank", 2, 1, 2, "re_edge", null, "AxeBlackMetal"), new TalentNode("re_hardy", "Hardened", "+4 armor per rank", 2, 2, 0, null, null, "ArmorBronzeChest"), new TalentNode("re_endure", "Endurance", "+4% stamina regeneration per rank", 2, 2, 2, null, null, "Honey"), new TalentNode("re_notable", "Bloodletter", "+10% slash damage and Cleave cooldown -1 s", 1, 3, 1, "re_force", "#ffd27a", "Bloodbag") }, Subs = new SubSpecDef[2] { new SubSpecDef { Name = "Reaver", Role = "Area Damage", Description = "The whirl of blades: Cleave, Whirlwind, Rupture, Iron Skin and the Bloodbath.", CapstoneId = "rv_capstone", Tree = new TalentNode[17] { new TalentNode("rv_edge", "Reaver's Edge", "+3% slash damage per rank", 5, 0, 0, null, null, "AxeBlackMetal"), new TalentNode("rv_toughness", "Toughness", "+4 armor per rank", 5, 0, 1, null, null, "ArmorBronzeChest"), new TalentNode("rv_whirlforce", "Whirling Death", "Whirlwind deals +10% more per rank", 4, 1, 0, "rv_edge", null, "AtgeirBlackmetal"), new TalentNode("rv_whirlwide", "Wide Whirl", "Whirlwind radius +0.5 m per rank", 3, 1, 1, null, null, "SwordIron"), new TalentNode("rv_whirllong", "Endless Spin", "Whirlwind spins +1 tick per rank", 3, 2, 0, "rv_whirlforce", null, "Chain"), new TalentNode("rv_ruptforce", "Deep Rupture", "Rend deals +10% more per rank", 5, 2, 1, null, null, "Bloodbag"), new TalentNode("rv_bloodwhirl", "Bloodwhirl", "+10% slash damage and Whirlwind heals you per enemy hit", 1, 3, 0, "rv_whirlforce", "#ffd27a", "Bloodbag"), new TalentNode("rv_endurance", "Endurance", "+4% stamina regeneration per rank", 4, 3, 1, null, null, "Honey"), new TalentNode("rv_ruptbleed", "Hemorrhage", "Rend bleeds +2 s per rank", 3, 4, 0, null, null, "Bloodbag"), new TalentNode("rv_ruptfocus", "Rupture Focus", "Rend cooldown -1 s per rank", 3, 4, 1, null, null, "Flint"), new TalentNode("rv_ironhide", "Iron Hide", "Iron Skin grants +8 armor per rank", 4, 5, 0, null, null, "ArmorIronChest"), new TalentNode("rv_vitality", "Vitality", "+5% health regeneration per rank", 5, 5, 1, null, null, "MeadHealthMinor"), new TalentNode("rv_bathforce", "Crimson Bath", "Bloodbath deals +8% more per rank", 5, 6, 0, null, null, "AxeBlackMetal"), new TalentNode("rv_bathheal", "Bloodletting", "Bloodbath heals +50% more per rank", 3, 6, 1, null, null, "MeadHealthMedium"), new TalentNode("rv_bathlong", "Endless Bath", "Bloodbath spins 2 extra ticks", 1, 7, 0, "rv_bathforce", "#ffd27a", "AtgeirBlackmetal"), new TalentNode("rv_bathfocus", "Bath Focus", "Bloodbath cooldown -5 s per rank", 3, 7, 1, null, null, "Flint"), new TalentNode("rv_capstone", "Avatar of Blood", "Your capstone aura bleeds and ALL slash deals +20% more", 1, 8, 0, null, "#ffdd55", "TrophyDeathsquito") } }, new SubSpecDef { Name = "Ravager", Role = "Single-Target Damage", Description = "The executioner: Cleave, Charge, Execute, Berserker Fury and the Rampage.", CapstoneId = "ra_capstone", Tree = new TalentNode[17] { new TalentNode("ra_savage", "Savagery", "+3% slash damage per rank", 5, 0, 0, null, null, "AxeIron"), new TalentNode("ra_toughness", "Toughness", "+4 armor per rank", 5, 0, 1, null, null, "ArmorBronzeChest"), new TalentNode("ra_chargeforce", "Brutal Charge", "Charge deals +10% more per rank", 4, 1, 0, "ra_savage", null, "AxeIron"), new TalentNode("ra_chargelong", "Long Charge", "Charge travels 50% farther", 1, 1, 1, null, null, "Feathers"), new TalentNode("ra_execforce", "Executioner", "Execute deals +10% more per rank", 5, 2, 0, "ra_chargeforce", null, "AxeBlackMetal"), new TalentNode("ra_execthresh", "Bloodthirst", "Execute's bonus vs wounded foes improves per rank", 3, 2, 1, null, null, "Bloodbag"), new TalentNode("ra_bloodrage", "Bloodrage", "+10% slash damage and Berserker Fury cooldown -10 s", 1, 3, 0, "ra_execforce", "#ffd27a", "Bloodbag"), new TalentNode("ra_endurance", "Endurance", "+4% stamina regeneration per rank", 4, 3, 1, null, null, "Honey"), new TalentNode("ra_furyforce", "Raging Fury", "Berserker Fury grants +5% more damage per rank", 3, 4, 0, null, null, "TrophyDeathsquito"), new TalentNode("ra_furylong", "Lasting Fury", "Berserker Fury lasts +3 s per rank", 4, 4, 1, null, null, "TrophyWolf"), new TalentNode("ra_chargefocus", "Swift Charge", "Charge cooldown -2 s per rank", 3, 5, 0, null, null, "Flint"), new TalentNode("ra_vitality", "Vitality", "+5% health regeneration per rank", 5, 5, 1, null, null, "MeadHealthMinor"), new TalentNode("ra_rampforce", "Relentless Rampage", "Rampage deals +8% more per rank", 5, 6, 0, null, null, "SwordIron"), new TalentNode("ra_ramphits", "Frenzied Rampage", "Rampage lands +1 strike per rank", 3, 6, 1, null, null, "Chain"), new TalentNode("ra_finisher", "Finisher", "Execute refunds its cooldown when it kills", 1, 7, 0, "ra_execforce", "#ffd27a", "AxeBlackMetal"), new TalentNode("ra_rampfocus", "Rampage Focus", "Rampage cooldown -5 s per rank", 3, 7, 1, null, null, "Flint"), new TalentNode("ra_capstone", "Avatar of Slaughter", "Your capstone aura rages and ALL slash deals +20% more", 1, 8, 0, null, "#ffdd55", "TrophyDeathsquito") } } } }, new BranchDef { Name = "Hunting", Color = "#c8a24a", Description = "The relentless hunter: pierce, reach and the throwing spear.", BaseSpellHint = "Spear Throw", Tree = new TalentNode[6] { new TalentNode("hu_point", "Piercing Point", "+4% pierce damage per rank", 4, 0, 1, null, null, "SpearBronze"), new TalentNode("hu_throw", "Strong Arm", "Spear Throw deals +10% more per rank", 2, 1, 0, "hu_point", null, "SpearChitin"), new TalentNode("hu_swift", "Fleet", "-10% run stamina drain per rank", 2, 1, 2, "hu_point", null, "Feathers"), new TalentNode("hu_hardy", "Hardened", "+4 armor per rank", 2, 2, 0, null, null, "ArmorBronzeChest"), new TalentNode("hu_endure", "Endurance", "+4% stamina regeneration per rank", 2, 2, 2, null, null, "Honey"), new TalentNode("hu_notable", "Hunter's Mark", "+10% pierce damage and Spear Throw cooldown -1 s", 1, 3, 1, "hu_throw", "#ffd27a", "TrophyDeer") }, Subs = new SubSpecDef[2] { new SubSpecDef { Name = "Lancer", Role = "Ranged Burst", Description = "The spear master: Spear Throw, Charge, Spear Volley, Impale and the Spear Storm.", CapstoneId = "la_capstone", Tree = new TalentNode[17] { new TalentNode("la_pierce", "Spearmaster", "+3% pierce damage per rank", 5, 0, 0, null, null, "SpearBronze"), new TalentNode("la_toughness", "Toughness", "+4 armor per rank", 5, 0, 1, null, null, "ArmorBronzeChest"), new TalentNode("la_throwforce", "Strong Throw", "Spear Throw deals +10% more per rank", 4, 1, 0, "la_pierce", null, "SpearChitin"), new TalentNode("la_chargeforce", "Lance Charge", "Charge deals +10% more per rank", 4, 1, 1, null, null, "AxeIron"), new TalentNode("la_volleyforce", "Volley Force", "Spear Volley deals +10% more per rank", 5, 2, 0, "la_throwforce", null, "SpearChitin"), new TalentNode("la_volleycount", "Extra Spears", "Spear Volley throws +1 spear per rank", 2, 2, 1, null, null, "SpearBronze"), new TalentNode("la_spearmaster", "Impaler", "+10% pierce damage and Spear Throw cooldown -1 s", 1, 3, 0, "la_throwforce", "#ffd27a", "SpearChitin"), new TalentNode("la_endurance", "Endurance", "+4% stamina regeneration per rank", 4, 3, 1, null, null, "Honey"), new TalentNode("la_impaleforce", "Deep Impale", "Impale deals +10% more per rank", 5, 4, 0, null, null, "SpearChitin"), new TalentNode("la_impalepull", "Harpoon", "Impale drags struck enemies to you", 1, 4, 1, null, "#ffd27a", "Chain"), new TalentNode("la_chargefocus", "Swift Charge", "Charge cooldown -2 s per rank", 3, 5, 0, null, null, "Flint"), new TalentNode("la_vitality", "Vitality", "+5% health regeneration per rank", 5, 5, 1, null, null, "MeadHealthMinor"), new TalentNode("la_stormforce", "Spear Rain", "Spear Storm deals +8% more per rank", 5, 6, 0, null, null, "SpearChitin"), new TalentNode("la_stormwide", "Wide Rain", "Spear Storm covers +1 m per rank", 3, 6, 1, null, null, "SpearBronze"), new TalentNode("la_stormcount", "Endless Volley", "Spear Storm drops 4 extra spears", 1, 7, 0, "la_stormforce", "#ffd27a", "SpearChitin"), new TalentNode("la_stormfocus", "Storm Focus", "Spear Storm cooldown -5 s per rank", 3, 7, 1, null, null, "Flint"), new TalentNode("la_capstone", "Avatar of the Spear", "Your capstone aura pierces and ALL pierce deals +20% more", 1, 8, 0, null, "#ffdd55", "TrophyDeer") } }, new SubSpecDef { Name = "Warhound", Role = "Skirmisher", Description = "The tireless hunter: Spear Throw, Pounce, Rapid Throw, Berserker Fury and the Wild Hunt.", CapstoneId = "wh_capstone", Tree = new TalentNode[17] { new TalentNode("wh_pierce", "Bloodhound", "+3% pierce damage per rank", 5, 0, 0, null, null, "SpearChitin"), new TalentNode("wh_toughness", "Toughness", "+4 armor per rank", 5, 0, 1, null, null, "ArmorBronzeChest"), new TalentNode("wh_pounceforce", "Savage Pounce", "Pounce deals +10% more per rank", 4, 1, 0, "wh_pierce", null, "SpearChitin"), new TalentNode("wh_pouncerange", "Long Pounce", "Pounce reaches +2 m per rank", 3, 1, 1, null, null, "Feathers"), new TalentNode("wh_rapidforce", "Rapid Force", "Rapid Throw deals +10% more per rank", 5, 2, 0, "wh_pounceforce", null, "SpearBronze"), new TalentNode("wh_rapidcount", "Extra Throws", "Rapid Throw hurls +1 spear per rank", 2, 2, 1, null, null, "SpearChitin"), new TalentNode("wh_bloodhunt", "Predator", "+10% pierce damage and Pounce cooldown -1 s", 1, 3, 0, "wh_pounceforce", "#ffd27a", "TrophyWolf"), new TalentNode("wh_endurance", "Endurance", "+4% stamina regeneration per rank", 4, 3, 1, null, null, "Honey"), new TalentNode("wh_furyforce", "Feral Fury", "Berserker Fury grants +5% more damage per rank", 3, 4, 0, null, null, "TrophyDeathsquito"), new TalentNode("wh_furylong", "Lasting Fury", "Berserker Fury lasts +3 s per rank", 4, 4, 1, null, null, "TrophyWolf"), new TalentNode("wh_pouncefocus", "Swift Pounce", "Pounce cooldown -1 s per rank", 3, 5, 0, null, null, "Flint"), new TalentNode("wh_vitality", "Vitality", "+5% health regeneration per rank", 5, 5, 1, null, null, "MeadHealthMinor"), new TalentNode("wh_huntforce", "Feral Rush", "Wild Hunt grants +5% more attack per rank", 3, 6, 0, null, null, "TrophyWolf"), new TalentNode("wh_huntlong", "Endless Hunt", "Wild Hunt lasts +3 s per rank", 4, 6, 1, null, null, "Feathers"), new TalentNode("wh_swift", "Fleet Hunter", "-10% run stamina drain per rank", 2, 7, 0, null, null, "Feathers"), new TalentNode("wh_huntfocus", "Hunt Focus", "Wild Hunt cooldown -5 s per rank", 3, 7, 1, null, null, "Flint"), new TalentNode("wh_capstone", "Avatar of the Hunt", "Your capstone aura howls and ALL pierce deals +20% more", 1, 8, 0, null, "#ffdd55", "TrophyWolf") } } } } } }, { PlayerClass.Necromancer, new BranchDef[3] { new BranchDef { Name = "Plague", Color = "#8ec86a", Description = "The rotting death: poison, clouds and contagion.", BaseSpellHint = "Ooze Bomb", Tree = new TalentNode[6] { new TalentNode("pl_venom", "Venom", "+4% poison damage per rank", 4, 0, 1, null, null, "Ooze"), new TalentNode("pl_bombforce", "Corrosive", "Ooze Bomb deals +10% more per rank", 2, 1, 0, "pl_venom", null, "BombOoze"), new TalentNode("pl_bombspread", "Wide Burst", "Ooze Bomb cloud reaches +0.5 m per rank", 2, 1, 2, "pl_venom", null, "Guck"), new TalentNode("pl_boneskin", "Bone Skin", "+4 armor per rank", 2, 2, 0, null, null, "BoneFragments"), new TalentNode("pl_darkmind", "Dark Mind", "+5% eitr regeneration per rank", 2, 2, 2, null, null, "Coal"), new TalentNode("pl_notable", "Plaguebearer", "+10% poison damage and Ooze Bomb cooldown -1 s", 1, 3, 1, "pl_bombforce", "#ffd27a", "TrophyBlob") }, Subs = new SubSpecDef[2] { new SubSpecDef { Name = "Pestilent", Role = "Area Damage", Description = "The walking plague: Ooze Bomb, Toxic Cloud, Putrid Rain, Plague Nova and the Pandemic.", CapstoneId = "pes_capstone", Tree = new TalentNode[17] { new TalentNode("pes_pest", "Pestilence", "+3% poison damage per rank", 5, 0, 0, null, null, "Ooze"), new TalentNode("pes_boneskin", "Bone Skin", "+4 armor per rank", 5, 0, 1, null, null, "BoneFragments"), new TalentNode("pes_cloudforce", "Miasma", "Toxic Cloud deals +10% more per rank", 4, 1, 0, "pes_pest", null, "Guck"), new TalentNode("pes_cloudwide", "Wide Cloud", "Toxic Cloud radius +1 m per rank", 3, 1, 1, null, null, "Ooze"), new TalentNode("pes_cloudwaves", "Creeping Rot", "Toxic Cloud lasts +1 wave per rank", 2, 2, 0, "pes_cloudforce", null, "TrophyBonemass"), new TalentNode("pes_rainforce", "Pandemic Rain", "Putrid Rain deals +10% more per rank", 5, 2, 1, null, null, "BombOoze"), new TalentNode("pes_notable", "Plaguelord", "+10% poison damage and Toxic Cloud lasts +1 wave", 1, 3, 0, "pes_cloudforce", "#ffd27a", "TrophyBlob"), new TalentNode("pes_darkmind", "Dark Mind", "+5% eitr regeneration per rank", 4, 3, 1, null, null, "Coal"), new TalentNode("pes_novaforce", "Virulent Nova", "Plague Nova deals +10% more per rank", 5, 4, 0, null, null, "Guck"), new TalentNode("pes_novawide", "Spreading Nova", "Plague Nova radius +1 m per rank", 3, 4, 1, null, null, "Ooze"), new TalentNode("pes_cloudfocus", "Swift Miasma", "Toxic Cloud cooldown -2 s per rank", 3, 5, 0, null, null, "Flint"), new TalentNode("pes_vitality", "Grave Vigor", "+5% health regeneration per rank", 5, 5, 1, null, null, "MeadHealthMinor"), new TalentNode("pes_panforce", "Great Pandemic", "Pandemic deals +8% more per rank", 5, 6, 0, null, null, "TrophyBonemass"), new TalentNode("pes_panwide", "Wide Pandemic", "Pandemic covers +1 m per rank", 3, 6, 1, null, null, "Guck"), new TalentNode("pes_panlong", "Lingering Death", "Pandemic lasts 5 s longer", 1, 7, 0, "pes_panforce", "#ffd27a", "TrophyBlob"), new TalentNode("pes_panfocus", "Pandemic Focus", "Pandemic cooldown -5 s per rank", 3, 7, 1, null, null, "Flint"), new TalentNode("pes_capstone", "Avatar of Pestilence", "Your capstone aura festers and ALL poison deals +20% more", 1, 8, 0, null, "#ffdd55", "TrophyBonemass") } }, new SubSpecDef { Name = "Blightcaller", Role = "Single-Target Damage", Description = "The virulent hand: Ooze Bomb, Plague Bolt, Toxic Cloud, Corrode and Putrid Rain.", CapstoneId = "bli_capstone", Tree = new TalentNode[17] { new TalentNode("bli_blight", "Blight", "+3% poison damage per rank", 5, 0, 0, null, null, "Ooze"), new TalentNode("bli_boneskin", "Bone Skin", "+4 armor per rank", 5, 0, 1, null, null, "BoneFragments"), new TalentNode("bli_boltforce", "Venom Bolt", "Plague Bolt deals +10% more per rank", 4, 1, 0, "bli_blight", null, "Guck"), new TalentNode("bli_boltfocus", "Quick Bolt", "Plague Bolt cooldown -1 s per rank", 3, 1, 1, null, null, "Flint"), new TalentNode("bli_corrodeforce", "Corrosion", "Corrode deals +10% more per rank", 5, 2, 0, "bli_boltforce", null, "Guck"), new TalentNode("bli_corrodelong", "Festering", "Corrode lasts +2 s per rank", 3, 2, 1, null, null, "Entrails"), new TalentNode("bli_notable", "Contagion", "+10% poison damage and Corrode spreads to a nearby enemy", 1, 3, 0, "bli_corrodeforce", "#ffd27a", "TrophyBlob"), new TalentNode("bli_darkmind", "Dark Mind", "+5% eitr regeneration per rank", 4, 3, 1, null, null, "Coal"), new TalentNode("bli_cloudforce", "Miasma", "Toxic Cloud deals +10% more per rank", 4, 4, 0, null, null, "TrophyBonemass"), new TalentNode("bli_bombforce", "Toxic Bombs", "Ooze Bomb deals +10% more per rank", 4, 4, 1, null, null, "BombOoze"), new TalentNode("bli_boltpierce", "Rapid Venom", "Plague Bolt pierces +1 target per rank", 2, 5, 0, "bli_boltforce", null, "Ooze"), new TalentNode("bli_vitality", "Grave Vigor", "+5% health regeneration per rank", 5, 5, 1, null, null, "MeadHealthMinor"), new TalentNode("bli_rainforce", "Acid Rain", "Putrid Rain deals +8% more per rank", 5, 6, 0, null, null, "BombOoze"), new TalentNode("bli_rainbombs", "Epidemic", "Putrid Rain drops +1 bomb per rank", 3, 6, 1, null, null, "BombOoze"), new TalentNode("bli_venomlord", "Venomlord", "Corrode can critically fester (+damage)", 1, 7, 0, "bli_corrodeforce", "#ffd27a", "TrophyBlob"), new TalentNode("bli_rainfocus", "Rain Focus", "Putrid Rain cooldown -2 s per rank", 3, 7, 1, null, null, "Flint"), new TalentNode("bli_capstone", "Avatar of Blight", "Your capstone aura corrodes and ALL poison deals +20% more", 1, 8, 0, null, "#ffdd55", "TrophyBonemass") } } } }, new BranchDef { Name = "Spirit", Color = "#7ec8b0", Description = "The wailing dead: spirit damage and stolen life.", BaseSpellHint = "Life Drain", Tree = new TalentNode[6] { new TalentNode("sp_spirit", "Spiritcaller", "+4% spirit damage per rank", 4, 0, 1, null, null, "TrophyWraith"), new TalentNode("sp_drainforce", "Soul Leech", "Life Drain deals +10% more per rank", 2, 1, 0, "sp_spirit", null, "Bloodbag"), new TalentNode("sp_drainheal", "Sanguine", "Life Drain heals +15% more per rank", 2, 1, 2, "sp_spirit", null, "MeadHealthMedium"), new TalentNode("sp_boneskin", "Bone Skin", "+4 armor per rank", 2, 2, 0, null, null, "BoneFragments"), new TalentNode("sp_gravevigor", "Grave Vigor", "+5% health regeneration per rank", 2, 2, 2, null, null, "MeadHealthMinor"), new TalentNode("sp_notable", "Soulreaver", "+10% spirit damage and Life Drain cooldown -1 s", 1, 3, 1, "sp_drainforce", "#ffd27a", "TrophyWraith") }, Subs = new SubSpecDef[2] { new SubSpecDef { Name = "Reaper", Role = "Drain / Sustain", Description = "The soul harvester: Life Drain, Spectral Wave, Soul Rip, Bone Armor and Death Coil.", CapstoneId = "rea_capstone", Tree = new TalentNode[17] { new TalentNode("rea_reap", "Reaper", "+3% spirit damage per rank", 5, 0, 0, null, null, "TrophyWraith"), new TalentNode("rea_boneskin", "Bone Skin", "+4 armor per rank", 5, 0, 1, null, null, "BoneFragments"), new TalentNode("rea_waveforce", "Wailing Souls", "Spectral Wave deals +10% more per rank", 4, 1, 0, "rea_reap", null, "Entrails"), new TalentNode("rea_drainheal", "Sanguine", "Life Drain heals +15% more per rank", 3, 1, 1, null, null, "MeadHealthMedium"), new TalentNode("rea_ripforce", "Soul Render", "Soul Rip deals +10% more per rank", 5, 2, 0, "rea_waveforce", null, "TrophyWraith"), new TalentNode("rea_ripheal", "Leeching Soul", "Soul Rip heals more per rank", 3, 2, 1, null, null, "Bloodbag"), new TalentNode("rea_notable", "Soulreaper", "+10% spirit damage and Life Drain reaches +2 m", 1, 3, 0, "rea_ripforce", "#ffd27a", "TrophyWraith"), new TalentNode("rea_darkmind", "Dark Mind", "+5% eitr regeneration per rank", 4, 3, 1, null, null, "Coal"), new TalentNode("rea_boneforce", "Bone Ward", "Bone Armor grants +6 armor per rank", 4, 4, 0, null, null, "BoneFragments"), new TalentNode("rea_bonelong", "Lasting Bones", "Bone Armor lasts 10 s longer", 1, 4, 1, null, null, "TrophySkeleton"), new TalentNode("rea_drainwide", "Wide Drain", "Life Drain radius +1 m per rank", 3, 5, 0, null, null, "Bloodbag"), new TalentNode("rea_vitality", "Grave Vigor", "+5% health regeneration per rank", 5, 5, 1, null, null, "MeadHealthMinor"), new TalentNode("rea_coilforce", "Death Coil Power", "Death Coil deals +8% more per rank", 5, 6, 0, null, null, "TrophyDraugr"), new TalentNode("rea_coilheal", "Vampiric Coil", "Death Coil heals more per rank", 3, 6, 1, null, null, "MeadHealthMedium"), new TalentNode("rea_coillife", "Soul Harvest", "Death Coil heals you for every enemy struck", 1, 7, 0, "rea_coilforce", "#ffd27a", "Bloodbag"), new TalentNode("rea_coilfocus", "Coil Focus", "Death Coil cooldown -5 s per rank", 3, 7, 1, null, null, "Flint"), new TalentNode("rea_capstone", "Avatar of Souls", "Your capstone aura drains and ALL spirit deals +20% more", 1, 8, 0, null, "#ffdd55", "TrophyWraith") } }, new SubSpecDef { Name = "Banshee", Role = "Area Burst", Description = "The screaming ghost: Life Drain, Spectral Wave, Wail, Spirit Nova and the Spectral Storm.", CapstoneId = "ban_capstone", Tree = new TalentNode[17] { new TalentNode("ban_wail", "Wailing", "+3% spirit damage per rank", 5, 0, 0, null, null, "TrophyWraith"), new TalentNode("ban_boneskin", "Bone Skin", "+4 armor per rank", 5, 0, 1, null, null, "BoneFragments"), new TalentNode("ban_waveforce", "Screaming Souls", "Spectral Wave deals +10% more per rank", 4, 1, 0, "ban_wail", null, "Entrails"), new TalentNode("ban_wavewide", "Wide Wave", "Spectral Wave radius +1 m per rank", 3, 1, 1, null, null, "TrophyDraugr"), new TalentNode("ban_wailforce", "Terror", "Wail deals +10% more per rank", 5, 2, 0, "ban_waveforce", null, "TrophyDraugr"), new TalentNode("ban_wailfear", "Dread", "Wail repels enemies harder per rank", 2, 2, 1, null, null, "Entrails"), new TalentNode("ban_notable", "Deathshriek", "+10% spirit damage and Wail cooldown -2 s", 1, 3, 0, "ban_wailforce", "#ffd27a", "TrophyWraith"), new TalentNode("ban_darkmind", "Dark Mind", "+5% eitr regeneration per rank", 4, 3, 1, null, null, "Coal"), new TalentNode("ban_novaforce", "Spirit Nova Power", "Spirit Nova deals +10% more per rank", 5, 4, 0, null, null, "TrophyWraith"), new TalentNode("ban_novawide", "Wide Nova", "Spirit Nova radius +1 m per rank", 3, 4, 1, null, null, "TrophyDraugr"), new TalentNode("ban_wavefocus", "Swift Wave", "Spectral Wave cooldown -2 s per rank", 3, 5, 0, null, null, "Flint"), new TalentNode("ban_vitality", "Grave Vigor", "+5% health regeneration per rank", 5, 5, 1, null, null, "MeadHealthMinor"), new TalentNode("ban_stormforce", "Spectral Rain", "Spectral Storm deals +8% more per rank", 5, 6, 0, null, null, "TrophyDraugrElite"), new TalentNode("ban_stormwide", "Wide Storm", "Spectral Storm covers +1 m per rank", 3, 6, 1, null, null, "Entrails"), new TalentNode("ban_stormcount", "Restless Dead", "Spectral Storm calls 4 more spirits", 1, 7, 0, "ban_stormforce", "#ffd27a", "TrophyDraugrElite"), new TalentNode("ban_stormfocus", "Storm Focus", "Spectral Storm cooldown -5 s per rank", 3, 7, 1, null, null, "Flint"), new TalentNode("ban_capstone", "Avatar of the Banshee", "Your capstone aura screams and ALL spirit deals +20% more", 1, 8, 0, null, "#ffdd55", "TrophyWraith") } } } }, new BranchDef { Name = "Bone", Color = "#d8d0b8", Description = "The risen dead: skeletons that fight for you.", BaseSpellHint = "Summon Skeleton", Tree = new TalentNode[6] { new TalentNode("bn_mastery", "Necromastery", "Your minions deal +5% more damage per rank", 4, 0, 1, null, null, "TrophySkeleton"), new TalentNode("bn_summonfocus", "Swift Summon", "Summon Skeleton cooldown -1 s per rank", 2, 1, 0, "bn_mastery", null, "Flint"), new TalentNode("bn_bonearmor", "Bone Skin", "+4 armor per rank", 2, 1, 2, "bn_mastery", null, "BoneFragments"), new TalentNode("bn_darkmind", "Dark Mind", "+5% eitr regeneration per rank", 2, 2, 0, null, null, "Coal"), new TalentNode("bn_vitality", "Grave Vigor", "+5% health regeneration per rank", 2, 2, 2, null, null, "MeadHealthMinor"), new TalentNode("bn_notable", "Gravecaller", "+1 max skeleton and your minions deal +10% more damage", 1, 3, 1, "bn_summonfocus", "#ffd27a", "TrophySkeletonPoison") }, Subs = new SubSpecDef[2] { new SubSpecDef { Name = "Bonelord", Role = "Minion Horde", Description = "The master of the horde: Summon Skeleton, Bone Armor, Raise Horde, Army of the Dead and the Bone Storm.", CapstoneId = "bl_capstone", Tree = new TalentNode[17] { new TalentNode("bl_command", "Bonecaller", "+3% minion damage per rank", 5, 0, 0, null, null, "TrophySkeleton"), new TalentNode("bl_boneskin", "Bone Skin", "+4 armor per rank", 5, 0, 1, null, null, "BoneFragments"), new TalentNode("bl_horde", "Growing Horde", "+1 max skeleton per rank", 2, 1, 0, "bl_command", null, "TrophySkeleton"), new TalentNode("bl_summonfocus", "Swift Raise", "Summon Skeleton cooldown -1 s per rank", 3, 1, 1, null, null, "Flint"), new TalentNode("bl_hordeforce", "Mass Raise", "Raise Horde summons +1 skeleton per rank", 3, 2, 0, "bl_horde", null, "TrophySkeletonPoison"), new TalentNode("bl_might", "Grave Might", "+3% minion damage per rank", 5, 2, 1, null, null, "TrophySkeleton"), new TalentNode("bl_notable", "Skeletal Legion", "+1 max skeleton and your minions deal +10% more damage", 1, 3, 0, "bl_hordeforce", "#ffd27a", "TrophySkeletonPoison"), new TalentNode("bl_darkmind", "Dark Mind", "+5% eitr regeneration per rank", 4, 3, 1, null, null, "Coal"), new TalentNode("bl_boneforce", "Bone Ward", "Bone Armor grants +6 armor per rank", 4, 4, 0, null, null, "BoneFragments"), new TalentNode("bl_bonelong", "Lasting Bones", "Bone Armor lasts 10 s longer", 1, 4, 1, null, null, "TrophySkeleton"), new TalentNode("bl_endless", "Endless Legion", "Army of the Dead raises +1 skeleton per rank", 3, 5, 0, null, null, "TrophyDraugrElite"), new TalentNode("bl_vitality", "Grave Vigor", "+5% health regeneration per rank", 5, 5, 1, null, null, "MeadHealthMinor"), new TalentNode("bl_armylong", "Enduring Army", "Army of the Dead lasts +15 s per rank", 2, 6, 0, null, null, "TrophyDraugrElite"), new TalentNode("bl_stormforce", "Bone Storm Power", "Bone Storm deals +8% more per rank", 5, 6, 1, null, null, "TrophyDraugrElite"), new TalentNode("bl_stormwide", "Wide Storm", "Bone Storm covers +1 m per rank", 3, 7, 0, null, null, "BoneFragments"), new TalentNode("bl_stormfocus", "Storm Focus", "Bone Storm cooldown -5 s per rank", 3, 7, 1, null, null, "Flint"), new TalentNode("bl_capstone", "Avatar of Bone", "+1 max skeleton and ALL your minions deal +20% more damage", 1, 8, 0, null, "#ffdd55", "TrophySkeletonPoison") } }, new SubSpecDef { Name = "Death Knight", Role = "Elite Minion", Description = "The bonded champion: Summon Skeleton, Summon Revenant, Bone Armor, Bone Pact and the Death Pact.", CapstoneId = "dk_capstone", Tree = new TalentNode[17] { new TalentNode("dk_might", "Deathbound", "+3% minion damage per rank", 5, 0, 0, null, null, "TrophySkeletonPoison"), new TalentNode("dk_boneskin", "Bone Skin", "+4 armor per rank", 5, 0, 1, null, null, "BoneFragments"), new TalentNode("dk_revenant", "Revenant Lord", "Summon Revenant minions are +10% stronger per rank", 4, 1, 0, "dk_might", null, "TrophySkeletonPoison"), new TalentNode("dk_swiftsummon", "Swift Revenant", "Summon Revenant cooldown -2 s per rank", 2, 1, 1, null, null, "Flint"), new TalentNode("dk_elite", "Grave Elite", "+4% minion damage per rank", 5, 2, 0, "dk_revenant", null, "TrophySkeleton"), new TalentNode("dk_bonehp", "Bound Bones", "Your Revenants have +15% health per rank", 3, 2, 1, null, null, "TrophySkeleton"), new TalentNode("dk_notable", "Death Knight", "+10% minion damage and Bone Armor grants +8 armor", 1, 3, 0, "dk_elite", "#ffd27a", "TrophySkeletonPoison"), new TalentNode("dk_darkmind", "Dark Mind", "+5% eitr regeneration per rank", 4, 3, 1, null, null, "Coal"), new TalentNode("dk_boneforce", "Bone Ward", "Bone Armor grants +6 armor per rank", 4, 4, 0, null, null, "BoneFragments"), new TalentNode("dk_bonelong", "Lasting Bones", "Bone Armor lasts 10 s longer", 1, 4, 1, null, null, "TrophySkeleton"), new TalentNode("dk_pactfury", "Pact Fury", "Bone Pact grants +5% more minion damage per rank", 3, 5, 0, null, null, "TrophySkeletonPoison"), new TalentNode("dk_vitality", "Grave Vigor", "+5% health regeneration per rank", 5, 5, 1, null, null, "MeadHealthMinor"), new TalentNode("dk_pactheal", "Dark Bond", "Bone Pact heals your minions more per rank", 3, 6, 0, null, null, "MeadHealthMedium"), new TalentNode("dk_pactforce", "Deathpact Power", "Death Pact deals +8% more per rank", 5, 6, 1, null, null, "TrophyDraugr"), new TalentNode("dk_pactwide", "Wide Deathpact", "Death Pact covers +1 m per rank", 3, 7, 0, null, null, "BoneFragments"), new TalentNode("dk_pactfocus", "Deathpact Focus", "Death Pact cooldown -5 s per rank", 3, 7, 1, null, null, "Flint"), new TalentNode("dk_capstone", "Avatar of Death", "Your minions deal +20% more damage and Death Pact also heals you", 1, 8, 0, null, "#ffdd55", "TrophySkeletonPoison") } } } } } }, { PlayerClass.Druid, new BranchDef[3] { new BranchDef { Name = "Wild Shape", Color = "#7fbf5f", Description = "The shapeshifter: become the beast — wolf, bear, raven.", BaseSpellHint = "Raven Form", Tree = new TalentNode[6] { new TalentNode("ws_wild", "Wild Instinct", "+4% damage in animal form per rank", 4, 0, 1, null, null, "TrophyWolf"), new TalentNode("ws_swiftshift", "Swift Shift", "Shapeshift cooldown -1 s per rank", 2, 1, 0, "ws_wild", null, "Feathers"), new TalentNode("ws_thickhide", "Thick Hide", "+4 armor in animal form per rank", 2, 1, 2, "ws_wild", null, "TrollHide"), new TalentNode("ws_endurance", "Feral Vigor", "+5% health regeneration per rank", 2, 2, 0, null, null, "MeadHealthMinor"), new TalentNode("ws_swift", "Fleet", "+4% movement speed in animal form per rank", 2, 2, 2, null, null, "Feathers"), new TalentNode("ws_notable", "Primal Bond", "Shapeshifting heals you 15% (6 s cooldown) and your form abilities deal +10%", 1, 3, 1, "ws_swiftshift", "#ffd27a", "TrophyWolf") }, Subs = new SubSpecDef[2] { new SubSpecDef { Name = "Werewolf", Role = "Agile Melee", Description = "The wolf within: Raven Form, Wolf Form, Pounce, Savage Rend and the Blood Moon.", CapstoneId = "ww_capstone", Tree = new TalentNode[17] { new TalentNode("ww_claws", "Razor Claws", "+3% form damage per rank", 5, 0, 0, null, null, "TrophyWolf"), new TalentNode("ww_thickfur", "Thick Fur", "+4 armor in form per rank", 5, 0, 1, null, null, "TrollHide"), new TalentNode("ww_wolfpower", "Feral Strength", "Wolf Form melee +5% per rank", 4, 1, 0, "ww_claws", null, "TrophyWolf"), new TalentNode("ww_swift", "Fleetfoot", "+4% movement speed in Wolf Form per rank", 3, 1, 1, null, null, "Feathers"), new TalentNode("ww_pounceforce", "Vicious Pounce", "Pounce deals +10% more per rank", 5, 2, 0, "ww_wolfpower", null, "TrophyWolf"), new TalentNode("ww_pouncefar", "Long Leap", "Pounce reaches +2 m per rank", 3, 2, 1, null, null, "Feathers"), new TalentNode("ww_notable", "Alpha", "+10% form damage and Wolf Form move speed +10%", 1, 3, 0, "ww_pounceforce", "#ffd27a", "TrophyWolf"), new TalentNode("ww_vigor", "Feral Vigor", "+5% health regeneration per rank", 4, 3, 1, null, null, "MeadHealthMinor"), new TalentNode("ww_rendforce", "Deep Wounds", "Savage Rend bleed +10% per rank", 5, 4, 0, null, null, "Entrails"), new TalentNode("ww_rendlong", "Hemorrhage", "Savage Rend bleeds +1 tick per rank", 3, 4, 1, null, null, "Entrails"), new TalentNode("ww_bloodheal", "Bloodthirst", "Heal when you make a foe bleed per rank", 3, 5, 0, null, null, "Bloodbag"), new TalentNode("ww_moonforce", "Blood Moon Power", "Blood Moon grants +5% attack per rank", 5, 5, 1, null, null, "TrophyWolf"), new TalentNode("ww_moonlong", "Endless Hunt", "Blood Moon lasts +3 s per rank", 3, 6, 0, null, null, "Feathers"), new TalentNode("ww_packlead", "Pack Leader", "Blood Moon also empowers nearby allies", 1, 6, 1, "ww_moonforce", "#ffd27a", "TrophyWolf"), new TalentNode("ww_moonfocus", "Lunar Focus", "Blood Moon cooldown -5 s per rank", 3, 7, 0, null, null, "Feathers"), new TalentNode("ww_vigor2", "Wild Endurance", "+5% health regeneration per rank", 3, 7, 1, null, null, "MeadHealthMinor"), new TalentNode("ww_capstone", "Avatar of the Wolf", "Your form deals +20% and your bleeds spread to nearby foes", 1, 8, 0, null, "#ffdd55", "TrophyWolf") } }, new SubSpecDef { Name = "Werebear", Role = "Heavy Bruiser", Description = "The bear's fury: Raven Form, Bear Form, Maul, Thunderous Roar and the Rampage.", CapstoneId = "wb_capstone", Tree = new TalentNode[17] { new TalentNode("wb_might", "Crushing Paws", "+3% form damage per rank", 5, 0, 0, null, null, "TrophyBoar"), new TalentNode("wb_hide", "Thick Hide", "+5 armor in form per rank", 5, 0, 1, null, null, "TrollHide"), new TalentNode("wb_bearpower", "Bear Strength", "Bear Form melee +5% per rank", 4, 1, 0, "wb_might", null, "TrophyBoar"), new TalentNode("wb_health", "Bear Constitution", "+5% max health in Bear Form per rank", 3, 1, 1, null, null, "MeadHealthMinor"), new TalentNode("wb_maulforce", "Brutal Maul", "Maul deals +10% more per rank", 5, 2, 0, "wb_bearpower", null, "SledgeStagbreaker"), new TalentNode("wb_maulwide", "Wide Swipe", "Maul arc +1 m per rank", 3, 2, 1, null, null, "SledgeStagbreaker"), new TalentNode("wb_notable", "Dire Bear", "+10% form damage and +20 armor in Bear Form", 1, 3, 0, "wb_maulforce", "#ffd27a", "TrophyBoar"), new TalentNode("wb_vigor", "Feral Vigor", "+5% health regeneration per rank", 4, 3, 1, null, null, "MeadHealthMinor"), new TalentNode("wb_roarforce", "Deafening Roar", "Thunderous Roar deals +10% more per rank", 5, 4, 0, null, null, "TrophyBoar"), new TalentNode("wb_roarwide", "Booming Roar", "Thunderous Roar radius +1 m per rank", 3, 4, 1, null, null, "SledgeStagbreaker"), new TalentNode("wb_thorns", "Spiked Hide", "Reflect damage to attackers in Bear Form per rank", 3, 5, 0, null, null, "Thistle"), new TalentNode("wb_rampforce", "Unstoppable", "Rampage deals +8% more per rank", 5, 5, 1, null, null, "SledgeStagbreaker"), new TalentNode("wb_rampfar", "Thundering Charge", "Rampage reaches +2 m per rank", 3, 6, 0, null, null, "Feathers"), new TalentNode("wb_rampstun", "Flatten", "Rampage knocks foes down", 1, 6, 1, "wb_rampforce", "#ffd27a", "TrophyBoar"), new TalentNode("wb_rampfocus", "Rampage Focus", "Rampage cooldown -5 s per rank", 3, 7, 0, null, null, "Feathers"), new TalentNode("wb_health2", "Ironbark", "+5% max health in Bear Form per rank", 3, 7, 1, null, null, "MeadHealthMinor"), new TalentNode("wb_capstone", "Avatar of the Bear", "Your form deals +20% and you take -15% damage in Bear Form", 1, 8, 0, null, "#ffdd55", "TrophyBoar") } } } }, new BranchDef { Name = "Warden", Color = "#e6c86a", Description = "The wild's voice: blessings, auras and beast companions.", BaseSpellHint = "Forest Blessing", Tree = new TalentNode[6] { new TalentNode("wd_wisdom", "Nature's Wisdom", "+5% buff duration per rank", 4, 0, 1, null, null, "AncientSeed"), new TalentNode("wd_reach", "Far Voice", "Buff radius +1 m per rank", 2, 1, 0, "wd_wisdom", null, "Feathers"), new TalentNode("wd_vigor", "Warden's Vigor", "+5% health regeneration per rank", 2, 1, 2, "wd_wisdom", null, "MeadHealthMinor"), new TalentNode("wd_focus", "Deep Roots", "+5% eitr regeneration per rank", 2, 2, 0, null, null, "Eitr"), new TalentNode("wd_grace", "Windborne", "-8% run stamina drain per rank", 2, 2, 2, null, null, "Feathers"), new TalentNode("wd_notable", "Wildspeaker", "Your blessings are 15% stronger and last longer", 1, 3, 1, "wd_reach", "#ffd27a", "AncientSeed") }, Subs = new SubSpecDef[2] { new SubSpecDef { Name = "Skald", Role = "Group Buffs", Description = "The battle-singer: Forest Blessing, Wind's Grace, Nature's Fury, Forest's Embrace and the War Song.", CapstoneId = "sk_capstone", Tree = new TalentNode[17] { new TalentNode("sk_voice", "Skald's Voice", "+3% buff duration per rank", 5, 0, 0, null, null, "AncientSeed"), new TalentNode("sk_hide", "Barkskin", "+4 armor per rank", 5, 0, 1, null, null, "TrollHide"), new TalentNode("sk_reach", "Carrying Voice", "Buff radius +1 m per rank", 3, 1, 0, "sk_voice", null, "Feathers"), new TalentNode("sk_blessforce", "Inspiring", "Forest Blessing grants +2% attack per rank", 4, 1, 1, null, null, "AncientSeed"), new TalentNode("sk_windgrace", "Tailwind", "Wind's Grace lasts +3 s per rank", 3, 2, 0, "sk_reach", null, "Feathers"), new TalentNode("sk_furyforce", "War Rhythm", "Nature's Fury empowers +3% more per rank", 4, 2, 1, null, null, "Thistle"), new TalentNode("sk_notable", "Warchanter", "+10% buff strength and buffs last +5 s", 1, 3, 0, "sk_windgrace", "#ffd27a", "AncientSeed"), new TalentNode("sk_focus", "Deep Roots", "+5% eitr regeneration per rank", 4, 3, 1, null, null, "Eitr"), new TalentNode("sk_embraceforce", "Nurturing Song", "Forest's Embrace heals +8% more per rank", 4, 4, 0, null, null, "Honey"), new TalentNode("sk_embracelong", "Evergreen Song", "Forest's Embrace regen lasts +5 s per rank", 3, 4, 1, null, null, "Honey"), new TalentNode("sk_vigor", "Warden's Vigor", "+5% health regeneration per rank", 5, 5, 0, null, null, "MeadHealthMinor"), new TalentNode("sk_furylong", "Lasting Fury", "Nature's Fury lasts +3 s per rank", 3, 5, 1, null, null, "Thistle"), new TalentNode("sk_warforce", "Battle Hymn", "War Song grants +2% attack per rank", 5, 6, 0, null, null, "AncientSeed"), new TalentNode("sk_warwide", "Resounding", "War Song radius +1 m per rank", 3, 6, 1, null, null, "Feathers"), new TalentNode("sk_warlong", "Anthem", "War Song lasts +8 s", 1, 7, 0, "sk_warforce", "#ffd27a", "AncientSeed"), new TalentNode("sk_warfocus", "Song Focus", "War Song cooldown -5 s per rank", 3, 7, 1, null, null, "Feathers"), new TalentNode("sk_capstone", "Avatar of the Song", "Your blessings are +20% stronger and reach +3 m", 1, 8, 0, null, "#ffdd55", "AncientSeed") } }, new SubSpecDef { Name = "Beastmaster", Role = "Animal Companions", Description = "The pack-leader: Forest Blessing, Summon Wolf, Summon Bear, Forest's Embrace and the Call of the Wild.", CapstoneId = "bm_capstone", Tree = new TalentNode[17] { new TalentNode("bm_kinship", "Beast Kinship", "+4% companion damage per rank", 5, 0, 0, null, null, "TrophyWolf"), new TalentNode("bm_hide", "Barkskin", "+4 armor per rank", 5, 0, 1, null, null, "TrollHide"), new TalentNode("bm_wolfpower", "Wolf Pack", "Summon Wolf companions are +5% stronger per rank", 4, 1, 0, "bm_kinship", null, "TrophyWolf"), new TalentNode("bm_summonfocus", "Swift Call", "Summon Wolf/Bear cooldown -1 s per rank", 3, 1, 1, null, null, "Feathers"), new TalentNode("bm_bearpower", "Dire Companion", "Summon Bear companions are +5% stronger per rank", 4, 2, 0, "bm_wolfpower", null, "TrophyBoar"), new TalentNode("bm_beasthp", "Thick Pelts", "Companions have +10% health per rank", 3, 2, 1, null, null, "MeadHealthMinor"), new TalentNode("bm_notable", "Alpha Bond", "+1 max companion and companions deal +10% more damage", 1, 3, 0, "bm_bearpower", "#ffd27a", "TrophyWolf"), new TalentNode("bm_focus", "Deep Roots", "+5% eitr regeneration per rank", 4, 3, 1, null, null, "Eitr"), new TalentNode("bm_might", "Feral Might", "+4% companion damage per rank", 5, 4, 0, null, null, "TrophyBoar"), new TalentNode("bm_vigor", "Warden's Vigor", "+5% health regeneration per rank", 4, 4, 1, null, null, "MeadHealthMinor"), new TalentNode("bm_wolfcount", "Growing Pack", "+1 max companion per rank", 2, 5, 0, null, null, "TrophyWolf"), new TalentNode("bm_embraceforce", "Heart of the Wild", "Forest's Embrace heals +8% more per rank", 5, 5, 1, null, null, "Honey"), new TalentNode("bm_callcount", "Great Pack", "Call of the Wild summons +1 wolf per rank", 3, 6, 0, null, null, "TrophyWolf"), new TalentNode("bm_calllong", "Enduring Pack", "Call of the Wild lasts +15 s per rank", 2, 6, 1, null, null, "Feathers"), new TalentNode("bm_callpower", "Rabid Pack", "Call of the Wild wolves deal +8% more per rank", 5, 7, 0, null, null, "TrophyWolf"), new TalentNode("bm_callfocus", "Pack Focus", "Call of the Wild cooldown -5 s per rank", 3, 7, 1, null, null, "Feathers"), new TalentNode("bm_capstone", "Avatar of the Wild", "+1 max companion and ALL companions deal +20% more damage", 1, 8, 0, null, "#ffdd55", "TrophyWolf") } } } }, new BranchDef { Name = "Restoration", Color = "#6ac8a0", Description = "The mender: direct heals and lingering growth.", BaseSpellHint = "Regrowth", Tree = new TalentNode[6] { new TalentNode("rs_mending", "Mending", "+4% healing done per rank", 4, 0, 1, null, null, "Dandelion"), new TalentNode("rs_reach", "Wide Care", "Heal radius +1 m per rank", 2, 1, 0, "rs_mending", null, "Feathers"), new TalentNode("rs_focus", "Deep Roots", "+5% eitr regeneration per rank", 2, 1, 2, "rs_mending", null, "Eitr"), new TalentNode("rs_vigor", "Lifebloom", "+5% health regeneration per rank", 2, 2, 0, null, null, "MeadHealthMinor"), new TalentNode("rs_thickhide", "Barkskin", "+4 armor per rank", 2, 2, 2, null, null, "TrollHide"), new TalentNode("rs_notable", "Lifewarden", "Your heals are 15% stronger and cost less", 1, 3, 1, "rs_reach", "#ffd27a", "Dandelion") }, Subs = new SubSpecDef[2] { new SubSpecDef { Name = "Lifekeeper", Role = "Group Healer", Description = "The life-giver: Regrowth, Healing Bloom, Forest's Embrace, Wrath of Yggdrasil and Tranquility.", CapstoneId = "lif_capstone", Tree = new TalentNode[17] { new TalentNode("lif_grace", "Green Hands", "+3% healing done per rank", 4, 0, 0, null, null, "Dandelion"), new TalentNode("lif_hide", "Barkskin", "+4 armor per rank", 5, 0, 1, null, null, "TrollHide"), new TalentNode("lif_regrow", "Blooming Life", "Regrowth heals +8% more per rank", 4, 1, 0, "lif_grace", null, "Raspberry"), new TalentNode("lif_regrowfocus", "Swift Mending", "Regrowth cooldown -1 s per rank", 2, 1, 1, null, null, "Flint"), new TalentNode("lif_bloomforce", "Lush Bloom", "Healing Bloom heals +10% more per rank", 4, 2, 0, "lif_regrow", null, "Raspberry"), new TalentNode("lif_bloomwide", "Wide Meadow", "Healing Bloom radius +1 m per rank", 3, 2, 1, null, null, "Honey"), new TalentNode("lif_notable", "Lifebloom", "+10% healing and Healing Bloom cooldown -3 s", 1, 3, 0, "lif_bloomforce", "#ffd27a", "Raspberry"), new TalentNode("lif_focus", "Focus", "-5% ability stamina cost per rank", 4, 3, 1, null, null, "GreydwarfEye"), new TalentNode("lif_embraceforce", "Heart of the Forest", "Forest's Embrace heals +8% more per rank", 4, 4, 0, null, null, "Honey"), new TalentNode("lif_embracelong", "Evergreen", "Forest's Embrace regen lasts +5 s per rank", 3, 4, 1, null, null, "Honey"), new TalentNode("lif_vigor", "Renewal", "+5% health regeneration per rank", 3, 5, 0, null, null, "MeadHealthMinor"), new TalentNode("lif_bloomlong", "Perennial", "Healing Bloom lasts +3 s per rank", 3, 5, 1, null, null, "Raspberry"), new TalentNode("lif_yggforce", "Yggdrasil's Favor", "Wrath of Yggdrasil heals +12% more per rank", 4, 6, 0, null, null, "YggdrasilWood"), new TalentNode("lif_yggwide", "World Canopy", "Wrath of Yggdrasil radius +1 m per rank", 3, 6, 1, null, null, "YggdrasilWood"), new TalentNode("lif_tranforce", "Serenity", "Tranquility heals +10% more per rank", 4, 7, 0, null, null, "Honey"), new TalentNode("lif_tranfocus", "Tranquil Focus", "Tranquility cooldown -5 s per rank", 3, 7, 1, null, null, "Flint"), new TalentNode("lif_capstone", "Avatar of Life", "Your heals are +20% stronger and reach +3 m", 1, 8, 0, null, "#ffdd55", "TrophyAbomination") } }, new SubSpecDef { Name = "Grovekeeper", Role = "Sustain / Defense", Description = "The grove-warden: Regrowth, Healing Bloom, Grasping Roots, Wind's Grace and the Barkward.", CapstoneId = "gk_capstone", Tree = new TalentNode[17] { new TalentNode("gk_growth", "Nature's Gift", "+3% healing done per rank", 4, 0, 0, null, null, "Dandelion"), new TalentNode("gk_hide", "Ironbark", "+5 armor per rank", 5, 0, 1, null, null, "TrollHide"), new TalentNode("gk_regrow", "Rejuvenation", "Regrowth heals +8% more per rank", 4, 1, 0, "gk_growth", null, "Raspberry"), new TalentNode("gk_regrowfocus", "Swift Rejuv", "Regrowth cooldown -1 s per rank", 2, 1, 1, null, null, "Flint"), new TalentNode("gk_bloomforce", "Verdant Bloom", "Healing Bloom heals +10% more per rank", 5, 2, 0, "gk_regrow", null, "Raspberry"), new TalentNode("gk_bloomlong", "Perennial", "Healing Bloom lasts +3 s per rank", 3, 2, 1, null, null, "Honey"), new TalentNode("gk_notable", "Grovewarden", "+10% healing and Healing Bloom radius +2 m", 1, 3, 0, "gk_bloomforce", "#ffd27a", "Raspberry"), new TalentNode("gk_focus", "Deep Focus", "-5% ability stamina cost per rank", 4, 3, 1, null, null, "GreydwarfEye"), new TalentNode("gk_rootforce", "Strangling Roots", "Grasping Roots deals +10% more per rank", 4, 4, 0, null, null, "Root"), new TalentNode("gk_rootwide", "Creeping Roots", "Grasping Roots radius +1 m per rank", 3, 4, 1, null, null, "Root"), new TalentNode("gk_rootheal", "Life Thorns", "Grasping Roots heals you per enemy hit", 1, 5, 0, "gk_rootforce", "#ffd27a", "Bloodbag"), new TalentNode("gk_vigor", "Lifebloom", "+5% health regeneration per rank", 4, 5, 1, null, null, "MeadHealthMinor"), new TalentNode("gk_windforce", "Tailwind", "Wind's Grace lasts +3 s per rank", 3, 6, 0, null, null, "Feathers"), new TalentNode("gk_barkforce", "Bark Ward", "Barkward grants +5 armor per rank", 5, 6, 1, null, null, "TrollHide"), new TalentNode("gk_barkwide", "Sheltering Grove", "Barkward radius +1 m per rank", 3, 7, 0, null, null, "Feathers"), new TalentNode("gk_barkfocus", "Ward Focus", "Barkward cooldown -5 s per rank", 3, 7, 1, null, null, "Flint"), new TalentNode("gk_capstone", "Avatar of the Grove", "Your heals are +15% stronger and Barkward also regenerates the group", 1, 8, 0, null, "#ffdd55", "TrophyAbomination") } } } } } }, { PlayerClass.Einherjar, new BranchDef[3] { new BranchDef { Name = "Storm", Color = "#7ec8f0", Description = "Thor's fury: bolts of lightning that smite from afar.", BaseSpellHint = "Thunderbolt", Tree = new TalentNode[6] { new TalentNode("sto_charge", "Storm Charged", "+4% lightning damage per rank", 4, 0, 1, null, null, "Thunderstone"), new TalentNode("sto_boltfocus", "Quick Bolt", "Thunderbolt cooldown -1 s per rank", 2, 1, 0, "sto_charge", null, "Flint"), new TalentNode("sto_ward", "Storm Ward", "+4 armor per rank", 2, 1, 2, "sto_charge", null, "ArmorIronChest"), new TalentNode("sto_focus", "Charged Mind", "+5% eitr regeneration per rank", 2, 2, 0, null, null, "Eitr"), new TalentNode("sto_vigor", "Storm Vigor", "+5% health regeneration per rank", 2, 2, 2, null, null, "MeadHealthMinor"), new TalentNode("sto_notable", "Thunderlord", "+10% lightning and Thunderbolt chains to a second foe", 1, 3, 1, "sto_boltfocus", "#ffd27a", "StaffLightning") }, Subs = new SubSpecDef[2] { new SubSpecDef { Name = "Thunderer", Role = "Single-Target Lightning", Description = "Thor's chosen: Thunderbolt, Judgement, Sky Dive, Thunderclap and Ragnarök.", CapstoneId = "thu_capstone", Tree = new TalentNode[17] { new TalentNode("thu_bolt", "Thunderer", "+3% lightning damage per rank", 5, 0, 0, null, null, "Thunderstone"), new TalentNode("thu_ward", "Storm Ward", "+4 armor per rank", 5, 0, 1, null, null, "ArmorIronChest"), new TalentNode("thu_boltforce", "Charged Bolt", "Thunderbolt deals +10% more per rank", 4, 1, 0, "thu_bolt", null, "StaffLightning"), new TalentNode("thu_boltfocus", "Quick Bolt", "Thunderbolt cooldown -1 s per rank", 3, 1, 1, null, null, "Flint"), new TalentNode("thu_judgeforce", "Thor's Judgement", "Judgement deals +10% more per rank", 5, 2, 0, "thu_boltforce", null, "Thunderstone"), new TalentNode("thu_judgetwin", "Twin Bolts", "Judgement strikes twice", 1, 2, 1, null, null, "StaffLightning"), new TalentNode("thu_notable", "Lightning Lord", "+10% lightning and Judgement radius +2 m", 1, 3, 0, "thu_judgeforce", "#ffd27a", "StaffLightning"), new TalentNode("thu_focus", "Charged Mind", "+5% eitr regeneration per rank", 4, 3, 1, null, null, "Eitr"), new TalentNode("thu_diveforce", "Thunder Dive", "Sky Dive deals +10% more per rank", 4, 4, 0, null, null, "Feathers"), new TalentNode("thu_divefar", "Long Dive", "Sky Dive reaches +2 m per rank", 3, 4, 1, null, null, "Feathers"), new TalentNode("thu_clapforce", "Thunderclap Power", "Thunderclap deals +10% more per rank", 5, 5, 0, null, null, "StaffLightning"), new TalentNode("thu_clapwide", "Wide Clap", "Thunderclap radius +1 m per rank", 3, 5, 1, null, null, "Thunderstone"), new TalentNode("thu_clapfocus", "Clap Focus", "Thunderclap cooldown -2 s per rank", 3, 6, 0, null, null, "Flint"), new TalentNode("thu_vigor", "Storm Vigor", "+5% health regeneration per rank", 4, 6, 1, null, null, "MeadHealthMinor"), new TalentNode("thu_ragforce", "Ragnarök Power", "Ragnarök deals +8% more per rank", 5, 7, 0, null, null, "TrophyDragonQueen"), new TalentNode("thu_ragfocus", "Ragnarök Focus", "Ragnarök cooldown -5 s per rank", 3, 7, 1, null, null, "Flint"), new TalentNode("thu_capstone", "Avatar of the Storm", "Your lightning deals +20% and Judgement chains across foes", 1, 8, 0, null, "#ffdd55", "Thunderstone") } }, new SubSpecDef { Name = "Stormherald", Role = "Area Lightning", Description = "The storm made war: Thunderbolt, Judgement, Thunderstorm, Aegis and Ragnarök.", CapstoneId = "shr_capstone", Tree = new TalentNode[17] { new TalentNode("shr_bolt", "Stormherald", "+3% lightning damage per rank", 5, 0, 0, null, null, "Thunderstone"), new TalentNode("shr_ward", "Storm Ward", "+4 armor per rank", 5, 0, 1, null, null, "ArmorIronChest"), new TalentNode("shr_judgeforce", "Herald's Judgement", "Judgement deals +10% more per rank", 4, 1, 0, "shr_bolt", null, "Thunderstone"), new TalentNode("shr_judgewide", "Wide Judgement", "Judgement radius +1 m per rank", 3, 1, 1, null, null, "StaffLightning"), new TalentNode("shr_stormforce", "Storm Power", "Thunderstorm deals +10% more per rank", 5, 2, 0, "shr_judgeforce", null, "StaffLightning"), new TalentNode("shr_stormwide", "Wide Storm", "Thunderstorm radius +1 m per rank", 3, 2, 1, null, null, "Thunderstone"), new TalentNode("shr_notable", "Storm Herald", "+10% lightning and Thunderstorm lasts +2 s", 1, 3, 0, "shr_stormforce", "#ffd27a", "StaffLightning"), new TalentNode("shr_focus", "Charged Mind", "+5% eitr regeneration per rank", 4, 3, 1, null, null, "Eitr"), new TalentNode("shr_stormlong", "Lasting Storm", "Thunderstorm lasts +2 s per rank", 3, 4, 0, null, null, "Thunderstone"), new TalentNode("shr_stormfocus", "Storm Focus", "Thunderstorm cooldown -3 s per rank", 3, 4, 1, null, null, "Flint"), new TalentNode("shr_aegisforce", "Host's Aegis", "Aegis of Valhalla lasts +5 s per rank", 3, 5, 0, null, null, "ShieldSilver"), new TalentNode("shr_vigor", "Storm Vigor", "+5% health regeneration per rank", 5, 5, 1, null, null, "MeadHealthMinor"), new TalentNode("shr_ragforce", "Ragnarök Power", "Ragnarök deals +8% more per rank", 5, 6, 0, null, null, "TrophyDragonQueen"), new TalentNode("shr_ragbolts", "Endless Storm", "Ragnarök calls +1 bolt per rank", 3, 6, 1, null, null, "StaffLightning"), new TalentNode("shr_ragwide", "World Breaker", "Ragnarök radius +2 m", 1, 7, 0, "shr_ragforce", "#ffd27a", "TrophyDragonQueen"), new TalentNode("shr_ragfocus", "Ragnarök Focus", "Ragnarök cooldown -5 s per rank", 3, 7, 1, null, null, "Flint"), new TalentNode("shr_capstone", "Avatar of the Tempest", "Your lightning deals +20% and Thunderstorm reaches +3 m", 1, 8, 0, null, "#ffdd55", "Thunderstone") } } } }, new BranchDef { Name = "Spear", Color = "#e0c890", Description = "Odin's chosen: divine spears, thrown and hurled from the sky.", BaseSpellHint = "Spear of the Gods", Tree = new TalentNode[6] { new TalentNode("spr_point", "Sharpened", "+4% pierce damage per rank", 4, 0, 1, null, null, "SpearBronze"), new TalentNode("spr_spearfocus", "Quick Throw", "Spear of the Gods cooldown -1 s per rank", 2, 1, 0, "spr_point", null, "Flint"), new TalentNode("spr_ward", "Battle Ward", "+4 armor per rank", 2, 1, 2, "spr_point", null, "ArmorIronChest"), new TalentNode("spr_focus", "Warrior's Wind", "+5% stamina regeneration per rank", 2, 2, 0, null, null, "MeadStaminaMedium"), new TalentNode("spr_vigor", "Warrior Vigor", "+5% health regeneration per rank", 2, 2, 2, null, null, "MeadHealthMinor"), new TalentNode("spr_notable", "Spear of Odin", "+10% pierce and Spear of the Gods pierces an extra foe", 1, 3, 1, "spr_spearfocus", "#ffd27a", "SpearChitin") }, Subs = new SubSpecDef[2] { new SubSpecDef { Name = "Spearmaster", Role = "Ranged Pierce", Description = "The spear-thrower: Spear of the Gods, Spear Volley, Sky Dive, Battle Blessing and Skyfall Spears.", CapstoneId = "spm_capstone", Tree = new TalentNode[17] { new TalentNode("spm_point", "Spearmaster", "+3% pierce damage per rank", 4, 0, 0, null, null, "SpearBronze"), new TalentNode("spm_ward", "Battle Ward", "+4 armor per rank", 5, 0, 1, null, null, "ArmorIronChest"), new TalentNode("spm_spearforce", "Heavy Point", "Spear of the Gods deals +10% more per rank", 4, 1, 0, "spm_point", null, "SpearChitin"), new TalentNode("spm_spearfocus", "Quick Throw", "Spear of the Gods cooldown -1 s per rank", 3, 1, 1, null, null, "Flint"), new TalentNode("spm_volleyforce", "Volley Master", "Spear Volley deals +10% more per rank", 5, 2, 0, "spm_spearforce", null, "SpearChitin"), new TalentNode("spm_volleycount", "Wide Volley", "Spear Volley throws +1 spear per rank", 3, 2, 1, null, null, "SpearBronze"), new TalentNode("spm_notable", "Master of Spears", "+10% pierce and Spear Volley throws +2 spears", 1, 3, 0, "spm_volleyforce", "#ffd27a", "SpearChitin"), new TalentNode("spm_focus", "Warrior's Wind", "+5% stamina regeneration per rank", 4, 3, 1, null, null, "MeadStaminaMedium"), new TalentNode("spm_diveforce", "Diving Spear", "Sky Dive deals +10% more per rank", 4, 4, 0, null, null, "Feathers"), new TalentNode("spm_divefar", "Long Dive", "Sky Dive reaches +2 m per rank", 3, 4, 1, null, null, "Feathers"), new TalentNode("spm_blessforce", "War Blessing", "Battle Blessing grants +5% more attack per rank", 3, 5, 0, null, null, "MeadStaminaMedium"), new TalentNode("spm_vigor", "Warrior Vigor", "+5% health regeneration per rank", 5, 5, 1, null, null, "MeadHealthMinor"), new TalentNode("spm_skyforce", "Skyfall Power", "Skyfall Spears deals +8% more per rank", 4, 6, 0, null, null, "SpearChitin"), new TalentNode("spm_skycount", "Spear Rain", "Skyfall Spears drops +2 spears per rank", 3, 6, 1, null, null, "SpearBronze"), new TalentNode("spm_skywide", "Wide Skyfall", "Skyfall Spears covers +1 m per rank", 3, 7, 0, null, null, "Feathers"), new TalentNode("spm_skyfocus", "Skyfall Focus", "Skyfall Spears cooldown -5 s per rank", 3, 7, 1, null, null, "Flint"), new TalentNode("spm_capstone", "Avatar of the Spear", "Your pierce deals +20% and Spear Volley throws +2 spears", 1, 8, 0, null, "#ffdd55", "SpearChitin") } }, new SubSpecDef { Name = "Valkyrie Knight", Role = "Dive Bruiser", Description = "The sky-warrior: Spear of the Gods, Sky Dive, Battle Blessing, Judgement and Ragnarök.", CapstoneId = "vk_capstone", Tree = new TalentNode[17] { new TalentNode("vk_point", "Valkyrie Knight", "+3% pierce damage per rank", 4, 0, 0, null, null, "SpearBronze"), new TalentNode("vk_ward", "Battle Ward", "+5 armor per rank", 5, 0, 1, null, null, "ArmorIronChest"), new TalentNode("vk_diveforce", "Crashing Dive", "Sky Dive deals +10% more per rank", 4, 1, 0, "vk_point", null, "Feathers"), new TalentNode("vk_divefar", "Long Dive", "Sky Dive reaches +2 m per rank", 3, 1, 1, null, null, "Feathers"), new TalentNode("vk_might", "Battle Might", "+3% pierce damage per rank", 4, 2, 0, "vk_diveforce", null, "SpearChitin"), new TalentNode("vk_blessforce", "War Blessing", "Battle Blessing grants +5% more attack per rank", 4, 2, 1, null, null, "MeadStaminaMedium"), new TalentNode("vk_notable", "Chosen Champion", "+10% damage and Sky Dive radius +2 m", 1, 3, 0, "vk_might", "#ffd27a", "TrophyValkyrie"), new TalentNode("vk_focus", "Warrior's Wind", "+5% stamina regeneration per rank", 4, 3, 1, null, null, "MeadStaminaMedium"), new TalentNode("vk_judgeforce", "Divine Judgement", "Judgement deals +10% more per rank", 5, 4, 0, null, null, "Thunderstone"), new TalentNode("vk_judgewide", "Wide Judgement", "Judgement radius +1 m per rank", 3, 4, 1, null, null, "StaffLightning"), new TalentNode("vk_blesslong", "Enduring Blessing", "Battle Blessing lasts +5 s per rank", 3, 5, 0, null, null, "MeadStaminaMedium"), new TalentNode("vk_vigor", "Warrior Vigor", "+5% health regeneration per rank", 5, 5, 1, null, null, "MeadHealthMinor"), new TalentNode("vk_ragforce", "Ragnarök Power", "Ragnarök deals +8% more per rank", 5, 6, 0, null, null, "TrophyDragonQueen"), new TalentNode("vk_ragfocus", "Ragnarök Focus", "Ragnarök cooldown -5 s per rank", 3, 6, 1, null, null, "Flint"), new TalentNode("vk_ragstun", "World Ender", "Ragnarök knocks foes down", 1, 7, 0, "vk_ragforce", "#ffd27a", "TrophyDragonQueen"), new TalentNode("vk_ward2", "Ironward", "+5 armor per rank", 3, 7, 1, null, null, "ArmorIronChest"), new TalentNode("vk_capstone", "Avatar of Valhalla", "Your damage deals +20% and Sky Dive also blesses you", 1, 8, 0, null, "#ffdd55", "TrophyValkyrie") } } } }, new BranchDef { Name = "Valhalla", Color = "#e6dca0", Description = "The hall of the slain: blessings, shields and fallen spirits.", BaseSpellHint = "Valkyrie's Blessing", Tree = new TalentNode[6] { new TalentNode("val_grace", "Valkyrie's Grace", "+5% buff duration per rank", 4, 0, 1, null, null, "TrophyValkyrie"), new TalentNode("val_reach", "Far Blessing", "Buff radius +1 m per rank", 2, 1, 0, "val_grace", null, "Feathers"), new TalentNode("val_ward", "Host's Ward", "+4 armor per rank", 2, 1, 2, "val_grace", null, "ShieldSilver"), new TalentNode("val_focus", "Divine Mind", "+5% eitr regeneration per rank", 2, 2, 0, null, null, "Eitr"), new TalentNode("val_vigor", "Host's Vigor", "+5% health regeneration per rank", 2, 2, 2, null, null, "MeadHealthMinor"), new TalentNode("val_notable", "Chooser of the Slain", "Your blessings are 15% stronger and last longer", 1, 3, 1, "val_reach", "#ffd27a", "TrophyValkyrie") }, Subs = new SubSpecDef[2] { new SubSpecDef { Name = "Valkyrie", Role = "Group Support", Description = "The battle-maiden: Valkyrie's Blessing, Aegis of the Host, Honor Guard, Valhalla's Grace and Ragnarök.", CapstoneId = "vlk_capstone", Tree = new TalentNode[17] { new TalentNode("vlk_grace", "Battle-Maiden", "+3% buff duration per rank", 5, 0, 0, null, null, "TrophyValkyrie"), new TalentNode("vlk_ward", "Host's Plate", "+4 armor per rank", 5, 0, 1, null, null, "ShieldSilver"), new TalentNode("vlk_reach", "Winged Voice", "Buff radius +1 m per rank", 3, 1, 0, "vlk_grace", null, "Feathers"), new TalentNode("vlk_blessforce", "Inspiring Host", "Valkyrie's Blessing grants +2% attack per rank", 4, 1, 1, null, null, "TrophyValkyrie"), new TalentNode("vlk_aegisforce", "Host's Aegis", "Aegis of the Host lasts +5 s per rank", 3, 2, 0, "vlk_reach", null, "ShieldSilver"), new TalentNode("vlk_aegisward", "Shielding", "Aegis grants +6 armor per rank", 4, 2, 1, null, null, "ShieldSilver"), new TalentNode("vlk_notable", "Shieldmaiden", "+10% buff strength and buffs last +5 s", 1, 3, 0, "vlk_aegisforce", "#ffd27a", "TrophyValkyrie"), new TalentNode("vlk_focus", "Divine Mind", "+5% eitr regeneration per rank", 4, 3, 1, null, null, "Eitr"), new TalentNode("vlk_honorforce", "Honored Dead", "Honor Guard spirits are +10% stronger per rank", 4, 4, 0, null, null, "TrophyWraith"), new TalentNode("vlk_honorcap", "Great Host", "+1 max spirit per rank", 2, 4, 1, null, null, "TrophyWraith"), new TalentNode("vlk_graceforce", "Grace of Valhalla", "Valhalla's Grace heals +8% more per rank", 5, 5, 0, null, null, "MeadHealthMedium"), new TalentNode("vlk_vigor", "Host's Vigor", "+5% health regeneration per rank", 5, 5, 1, null, null, "MeadHealthMinor"), new TalentNode("vlk_gracelong", "Lasting Grace", "Valhalla's Grace regen lasts +3 s per rank", 3, 6, 0, null, null, "Honey"), new TalentNode("vlk_gracewide", "Wide Grace", "Valhalla's Grace radius +1 m per rank", 3, 6, 1, null, null, "Feathers"), new TalentNode("vlk_ragforce", "Ragnarök Power", "Ragnarök deals +8% more per rank", 4, 7, 0, null, null, "TrophyDragonQueen"), new TalentNode("vlk_ragfocus", "Ragnarök Focus", "Ragnarök cooldown -5 s per rank", 3, 7, 1, null, null, "Flint"), new TalentNode("vlk_capstone", "Avatar of Valhalla", "Your blessings are +20% stronger and reach +3 m", 1, 8, 0, null, "#ffdd55", "TrophyValkyrie") } }, new SubSpecDef { Name = "Herald of the Slain", Role = "Spirit Summoner", Description = "The death-caller: Valkyrie's Blessing, Call the Fallen, Soul Spear, Wail of the Fallen and Legion of Valhalla.", CapstoneId = "her_capstone", Tree = new TalentNode[17] { new TalentNode("her_soul", "Soulcaller", "+3% spirit damage per rank", 5, 0, 0, null, null, "TrophyWraith"), new TalentNode("her_ward", "Grave Plate", "+4 armor per rank", 5, 0, 1, null, null, "ShieldSilver"), new TalentNode("her_fallenforce", "Honored Fallen", "Call the Fallen spirits are +10% stronger per rank", 4, 1, 0, "her_soul", null, "TrophyWraith"), new TalentNode("her_fallencap", "Endless Host", "+1 max spirit per rank", 2, 1, 1, null, null, "TrophyWraith"), new TalentNode("her_spearforce", "Soul Spear Power", "Soul Spear deals +10% more per rank", 5, 2, 0, "her_fallenforce", null, "SpearChitin"), new TalentNode("her_spearfocus", "Quick Soul", "Soul Spear cooldown -1 s per rank", 3, 2, 1, null, null, "Flint"), new TalentNode("her_notable", "Herald of Death", "+10% spirit and Soul Spear pierces through foes", 1, 3, 0, "her_spearforce", "#ffd27a", "TrophyWraith"), new TalentNode("her_focus", "Divine Mind", "+5% eitr regeneration per rank", 4, 3, 1, null, null, "Eitr"), new TalentNode("her_wailforce", "Wailing Dead", "Wail of the Fallen deals +10% more per rank", 5, 4, 0, null, null, "TrophyWraith"), new TalentNode("her_wailwide", "Echoing Wail", "Wail of the Fallen radius +1 m per rank", 3, 4, 1, null, null, "TrophyDraugr"), new TalentNode("her_wailfocus", "Wail Focus", "Wail of the Fallen cooldown -2 s per rank", 3, 5, 0, null, null, "Flint"), new TalentNode("her_vigor", "Grave Vigor", "+5% health regeneration per rank", 5, 5, 1, null, null, "MeadHealthMinor"), new TalentNode("her_legionforce", "Legion Power", "Legion of Valhalla spirits deal +8% more per rank", 5, 6, 0, null, null, "TrophyDraugrElite"), new TalentNode("her_legioncount", "Great Legion", "Legion of Valhalla calls +1 spirit per rank", 3, 6, 1, null, null, "TrophyWraith"), new TalentNode("her_legionlong", "Enduring Legion", "Legion of Valhalla lasts +15 s per rank", 2, 7, 0, null, null, "Feathers"), new TalentNode("her_legionfocus", "Legion Focus", "Legion of Valhalla cooldown -5 s per rank", 3, 7, 1, null, null, "Flint"), new TalentNode("her_capstone", "Avatar of the Slain", "Your spirit deals +20% and +1 max spirit", 1, 8, 0, null, "#ffdd55", "TrophyWraith") } } } } } }, { PlayerClass.Guardian, new BranchDef[3] { new BranchDef { Name = "Bulwark", Color = "#8fb8e0", Description = "The living shield: taunts, walls and unbreakable armor.", BaseSpellHint = "Shield Bash", Tree = new TalentNode[6] { new TalentNode("gb_guard", "Guardian", "+4 armor per rank", 4, 0, 1, null, null, "ShieldBanded"), new TalentNode("gb_bashfocus", "Quick Bash", "Shield Bash cooldown -1 s per rank", 2, 1, 0, "gb_guard", null, "Flint"), new TalentNode("gb_bashforce", "Heavy Bash", "Shield Bash deals +10% more per rank", 2, 1, 2, "gb_guard", null, "ShieldBanded"), new TalentNode("gb_vigor", "Stalwart", "+5% health regeneration per rank", 2, 2, 0, null, null, "MeadHealthMinor"), new TalentNode("gb_stamina", "Endurance", "+5% stamina regeneration per rank", 2, 2, 2, null, null, "MeadStaminaMedium"), new TalentNode("gb_notable", "Ironclad", "+10 armor and Shield Bash taunts a wider area", 1, 3, 1, "gb_bashfocus", "#ffd27a", "ShieldIronTower") }, Subs = new SubSpecDef[2] { new SubSpecDef { Name = "Warden", Role = "Party Protection", Description = "The shield of the fellowship: Shield Bash, Challenge, Shield Wall, Living Fortress and Gjallarhorn.", CapstoneId = "wrd_capstone", Tree = new TalentNode[17] { new TalentNode("wrd_guard", "Warden", "+4 armor per rank", 5, 0, 0, null, null, "ShieldBanded"), new TalentNode("wrd_vigor", "Stalwart", "+5% health regeneration per rank", 5, 0, 1, null, null, "MeadHealthMinor"), new TalentNode("wrd_challforce", "Defiance", "Challenge grants +3 armor per rank", 4, 1, 0, "wrd_guard", null, "ShieldWood"), new TalentNode("wrd_challwide", "Wide Challenge", "Challenge radius +1 m per rank", 3, 1, 1, null, null, "ShieldWood"), new TalentNode("wrd_wallforce", "Shield Wall Power", "Shield Wall grants allies +4 armor per rank", 5, 2, 0, "wrd_challforce", null, "ShieldIronTower"), new TalentNode("wrd_walllong", "Lasting Wall", "Shield Wall lasts +3 s per rank", 3, 2, 1, null, null, "ShieldIronTower"), new TalentNode("wrd_notable", "Bulwark of the Host", "+10 armor and Shield Wall reaches +2 m", 1, 3, 0, "wrd_wallforce", "#ffd27a", "ShieldIronTower"), new TalentNode("wrd_stamina", "Endurance", "+5% stamina regeneration per rank", 4, 3, 1, null, null, "MeadStaminaMedium"), new TalentNode("wrd_fortforce", "Living Fortress Power", "Living Fortress grants +6 armor per rank", 4, 4, 0, null, null, "ShieldSerpentscale"), new TalentNode("wrd_fortlong", "Enduring Fortress", "Living Fortress lasts +5 s per rank", 3, 4, 1, null, null, "ShieldSerpentscale"), new TalentNode("wrd_reach", "Rallying Cry", "Party buffs reach +1 m per rank", 3, 5, 0, null, null, "TankardOdin"), new TalentNode("wrd_vigor2", "Ironheart", "+5% health regeneration per rank", 5, 5, 1, null, null, "MeadHealthMinor"), new TalentNode("wrd_hornforce", "Gjallarhorn Power", "Gjallarhorn deals +8% more per rank", 5, 6, 0, null, null, "TankardOdin"), new TalentNode("wrd_hornwide", "Wide Horn", "Gjallarhorn radius +1 m per rank", 3, 6, 1, null, null, "TankardOdin"), new TalentNode("wrd_hornstun", "Deafening Horn", "Gjallarhorn knocks foes down", 1, 7, 0, "wrd_hornforce", "#ffd27a", "TankardOdin"), new TalentNode("wrd_hornfocus", "Horn Focus", "Gjallarhorn cooldown -5 s per rank", 3, 7, 1, null, null, "Flint"), new TalentNode("wrd_capstone", "Avatar of the Wall", "+15 armor and your party shields are +20% stronger", 1, 8, 0, null, "#ffdd55", "ShieldIronTower") } }, new SubSpecDef { Name = "Sentinel", Role = "Immovable Self-Tank", Description = "The immovable wall: Shield Bash, Iron Bulwark, Challenge, Thornplate and Gjallarhorn.", CapstoneId = "snt_capstone", Tree = new TalentNode[17] { new TalentNode("snt_guard", "Sentinel", "+5 armor per rank", 4, 0, 0, null, null, "ShieldBanded"), new TalentNode("snt_vigor", "Stoneskin", "+5% health regeneration per rank", 5, 0, 1, null, null, "MeadHealthMinor"), new TalentNode("snt_bulwarkforce", "Iron Will", "Iron Bulwark grants +8 armor per rank", 4, 1, 0, "snt_guard", null, "ArmorPaddedCuirass"), new TalentNode("snt_bulwarklong", "Lasting Bulwark", "Iron Bulwark lasts +5 s per rank", 3, 1, 1, null, null, "ArmorPaddedCuirass"), new TalentNode("snt_reflect", "Spiked Shield", "Reflect damage to melee attackers per rank", 4, 2, 0, "snt_bulwarkforce", null, "ShieldSerpentscale"), new TalentNode("snt_challforce", "Defiance", "Challenge grants +3 armor per rank", 3, 2, 1, null, null, "ShieldWood"), new TalentNode("snt_notable", "Immovable", "+15 armor and you cannot be staggered", 1, 3, 0, "snt_reflect", "#ffd27a", "ShieldIronTower"), new TalentNode("snt_stamina", "Endurance", "+5% stamina regeneration per rank", 4, 3, 1, null, null, "MeadStaminaMedium"), new TalentNode("snt_thornforce", "Thornplate Power", "Thornplate reflects +10% more per rank", 5, 4, 0, null, null, "ShieldSerpentscale"), new TalentNode("snt_thornlong", "Lasting Thorns", "Thornplate lasts +5 s per rank", 3, 4, 1, null, null, "ShieldSerpentscale"), new TalentNode("snt_vigor2", "Rockheart", "+5% health regeneration per rank", 5, 5, 0, null, null, "MeadHealthMinor"), new TalentNode("snt_bashforce", "Shield Master", "Shield Bash deals +10% more per rank", 3, 5, 1, null, null, "ShieldBanded"), new TalentNode("snt_hornforce", "Gjallarhorn Power", "Gjallarhorn deals +8% more per rank", 5, 6, 0, null, null, "TankardOdin"), new TalentNode("snt_hornfocus", "Horn Focus", "Gjallarhorn cooldown -5 s per rank", 3, 6, 1, null, null, "Flint"), new TalentNode("snt_bulwarkfocus", "Bulwark Focus", "Iron Bulwark cooldown -5 s per rank", 3, 7, 0, null, null, "Flint"), new TalentNode("snt_ward2", "Adamant", "+5 armor per rank", 3, 7, 1, null, null, "ArmorIronChest"), new TalentNode("snt_capstone", "Avatar of Stone", "+20 armor and reflect a portion of all damage taken", 1, 8, 0, null, "#ffdd55", "ShieldIronTower") } } } }, new BranchDef { Name = "Vanguard", Color = "#e0a060", Description = "The spearhead of the warband: shield and mace, in the enemy's face.", BaseSpellHint = "Skull Crusher", Tree = new TalentNode[6] { new TalentNode("van_might", "Vanguard", "+4% blunt damage per rank", 4, 0, 1, null, null, "MaceBronze"), new TalentNode("van_crushfocus", "Quick Crush", "Skull Crusher cooldown -1 s per rank", 2, 1, 0, "van_might", null, "Flint"), new TalentNode("van_ward", "War Plate", "+4 armor per rank", 2, 1, 2, "van_might", null, "ArmorIronChest"), new TalentNode("van_vigor", "Battle Vigor", "+5% health regeneration per rank", 2, 2, 0, null, null, "MeadHealthMinor"), new TalentNode("van_stamina", "War Stamina", "+5% stamina regeneration per rank", 2, 2, 2, null, null, "MeadStaminaMedium"), new TalentNode("van_notable", "Warbreaker", "+10% blunt and Skull Crusher heals you per foe hit", 1, 3, 1, "van_crushfocus", "#ffd27a", "MaceIron") }, Subs = new SubSpecDef[2] { new SubSpecDef { Name = "Crusher", Role = "Area Blunt", Description = "The earthbreaker: Skull Crusher, Ground Slam, Assault Leap, Shield Storm and Earthbreaker.", CapstoneId = "cru_capstone", Tree = new TalentNode[17] { new TalentNode("cru_might", "Crusher", "+3% blunt damage per rank", 4, 0, 0, null, null, "MaceBronze"), new TalentNode("cru_ward", "War Plate", "+4 armor per rank", 5, 0, 1, null, null, "ArmorIronChest"), new TalentNode("cru_crushforce", "Skullbreaker", "Skull Crusher deals +10% more per rank", 4, 1, 0, "cru_might", null, "MaceIron"), new TalentNode("cru_crushheal", "Bloodthirst", "Skull Crusher heals you per foe hit per rank", 3, 1, 1, null, null, "Bloodbag"), new TalentNode("cru_slamforce", "Ground Slam Power", "Ground Slam deals +10% more per rank", 5, 2, 0, "cru_crushforce", null, "SledgeIron"), new TalentNode("cru_slamwide", "Wide Slam", "Ground Slam radius +1 m per rank", 3, 2, 1, null, null, "SledgeIron"), new TalentNode("cru_notable", "Earthshaker", "+10% blunt and Ground Slam radius +2 m", 1, 3, 0, "cru_slamforce", "#ffd27a", "SledgeDemolisher"), new TalentNode("cru_stamina", "War Stamina", "+5% stamina regeneration per rank", 4, 3, 1, null, null, "MeadStaminaMedium"), new TalentNode("cru_leapforce", "Assault Power", "Assault Leap deals +10% more per rank", 4, 4, 0, null, null, "ShieldBronzeBuckler"), new TalentNode("cru_leapfar", "Long Leap", "Assault Leap reaches +2 m per rank", 3, 4, 1, null, null, "Feathers"), new TalentNode("cru_stormforce", "Shield Storm Power", "Shield Storm deals +10% more per rank", 4, 5, 0, null, null, "ShieldIronSquare"), new TalentNode("cru_vigor", "Battle Vigor", "+5% health regeneration per rank", 5, 5, 1, null, null, "MeadHealthMinor"), new TalentNode("cru_earthforce", "Earthbreaker Power", "Earthbreaker deals +8% more per rank", 5, 6, 0, null, null, "SledgeDemolisher"), new TalentNode("cru_earthwide", "Wide Earthbreaker", "Earthbreaker radius +1 m per rank", 3, 6, 1, null, null, "SledgeIron"), new TalentNode("cru_earthstun", "Fissure", "Earthbreaker knocks foes down", 1, 7, 0, "cru_earthforce", "#ffd27a", "SledgeDemolisher"), new TalentNode("cru_earthfocus", "Earthbreaker Focus", "Earthbreaker cooldown -5 s per rank", 3, 7, 1, null, null, "Flint"), new TalentNode("cru_capstone", "Avatar of the Crush", "Your blunt deals +20% and Ground Slam strikes twice", 1, 8, 0, null, "#ffdd55", "SledgeDemolisher") } }, new SubSpecDef { Name = "Warbringer", Role = "Frenzy Melee", Description = "The frenzied vanguard: Skull Crusher, Assault Leap, Battle Frenzy, Shattering Shout and Horn of War.", CapstoneId = "wbr_capstone", Tree = new TalentNode[17] { new TalentNode("wbr_might", "Warbringer", "+3% blunt damage per rank", 5, 0, 0, null, null, "MaceBronze"), new TalentNode("wbr_ward", "War Plate", "+4 armor per rank", 5, 0, 1, null, null, "ArmorIronChest"), new TalentNode("wbr_leapforce", "Assault Power", "Assault Leap deals +10% more per rank", 4, 1, 0, "wbr_might", null, "ShieldBronzeBuckler"), new TalentNode("wbr_leapfar", "Long Leap", "Assault Leap reaches +2 m per rank", 3, 1, 1, null, null, "Feathers"), new TalentNode("wbr_frenzyforce", "Frenzy", "Battle Frenzy grants +5% more attack per rank", 5, 2, 0, "wbr_leapforce", null, "TrophyFenring"), new TalentNode("wbr_frenzylong", "Endless Frenzy", "Battle Frenzy lasts +5 s per rank", 3, 2, 1, null, null, "TrophyFenring"), new TalentNode("wbr_notable", "Berserker Guard", "+10% blunt and Battle Frenzy also grants lifesteal", 1, 3, 0, "wbr_frenzyforce", "#ffd27a", "TrophyFenring"), new TalentNode("wbr_vigor", "Battle Vigor", "+5% health regeneration per rank", 4, 3, 1, null, null, "MeadHealthMinor"), new TalentNode("wbr_shoutforce", "Shattering Power", "Shattering Shout deals +10% more per rank", 5, 4, 0, null, null, "Club"), new TalentNode("wbr_shoutwide", "Wide Shout", "Shattering Shout radius +1 m per rank", 3, 4, 1, null, null, "Club"), new TalentNode("wbr_crushheal", "Bloodthirst", "Skull Crusher heals you per foe hit per rank", 3, 5, 0, null, null, "Bloodbag"), new TalentNode("wbr_stamina", "War Stamina", "+5% stamina regeneration per rank", 5, 5, 1, null, null, "MeadStaminaMedium"), new TalentNode("wbr_hornforce", "Horn of War Power", "Horn of War deals +8% more per rank", 5, 6, 0, null, null, "TankardOdin"), new TalentNode("wbr_hornwide", "Wide Horn", "Horn of War radius +1 m per rank", 3, 6, 1, null, null, "TankardOdin"), new TalentNode("wbr_hornstun", "Warbreaker", "Horn of War knocks foes down", 1, 7, 0, "wbr_hornforce", "#ffd27a", "TankardOdin"), new TalentNode("wbr_hornfocus", "Horn Focus", "Horn of War cooldown -5 s per rank", 3, 7, 1, null, null, "Flint"), new TalentNode("wbr_capstone", "Avatar of War", "Your blunt deals +20% and Battle Frenzy lasts +10 s", 1, 8, 0, null, "#ffdd55", "TrophyFenring") } } } }, new BranchDef { Name = "Paladin", Color = "#f0e0a0", Description = "The blessed shield: holy auras, mending light and divine wards.", BaseSpellHint = "Blessing of Light", Tree = new TalentNode[6] { new TalentNode("pal_faith", "Faith", "+4% healing done per rank", 4, 0, 1, null, null, "TrophyValkyrie"), new TalentNode("pal_reach", "Holy Reach", "Aura radius +1 m per rank", 2, 1, 0, "pal_faith", null, "Feathers"), new TalentNode("pal_ward", "Blessed Plate", "+4 armor per rank", 2, 1, 2, "pal_faith", null, "ShieldSilver"), new TalentNode("pal_focus", "Devotion", "+5% eitr regeneration per rank", 2, 2, 0, null, null, "Eitr"), new TalentNode("pal_vigor", "Sanctity", "+5% health regeneration per rank", 2, 2, 2, null, null, "MeadHealthMinor"), new TalentNode("pal_notable", "Chosen of the Light", "Your blessings are 15% stronger and mend the wounded", 1, 3, 1, "pal_reach", "#ffd27a", "TrophyValkyrie") }, Subs = new SubSpecDef[2] { new SubSpecDef { Name = "Templar", Role = "Holy Protection", Description = "The blessed shield: Blessing of Light, Consecration, Lay on Hands, Divine Shield and Beacon of Light.", CapstoneId = "tmp_capstone", Tree = new TalentNode[17] { new TalentNode("tmp_faith", "Devout", "+3% healing done per rank", 4, 0, 0, null, null, "TrophyValkyrie"), new TalentNode("tmp_ward", "Blessed Plate", "+5 armor per rank", 5, 0, 1, null, null, "ShieldSilver"), new TalentNode("tmp_blessforce", "Inspiring Light", "Blessing of Light grants +2% attack per rank", 4, 1, 0, "tmp_faith", null, "TrophyValkyrie"), new TalentNode("tmp_reach", "Wide Blessing", "Aura radius +1 m per rank", 3, 1, 1, null, null, "Feathers"), new TalentNode("tmp_consforce", "Holy Ground", "Consecration heals +10% more per rank", 4, 2, 0, "tmp_blessforce", null, "Honey"), new TalentNode("tmp_conslong", "Lasting Ground", "Consecration lasts +2 s per rank", 3, 2, 1, null, null, "Honey"), new TalentNode("tmp_notable", "Templar", "+10% healing and Consecration radius +2 m", 1, 3, 0, "tmp_consforce", "#ffd27a", "TrophyValkyrie"), new TalentNode("tmp_focus", "Devotion", "+5% eitr regeneration per rank", 4, 3, 1, null, null, "Eitr"), new TalentNode("tmp_handforce", "Mending Hands", "Lay on Hands heals +10% more per rank", 5, 4, 0, null, null, "MeadHealthMedium"), new TalentNode("tmp_handfocus", "Quick Hands", "Lay on Hands cooldown -1 s per rank", 3, 4, 1, null, null, "Flint"), new TalentNode("tmp_shieldforce", "Divine Ward", "Divine Shield grants +6 armor per rank", 4, 5, 0, null, null, "ShieldSilver"), new TalentNode("tmp_vigor", "Sanctity", "+5% health regeneration per rank", 5, 5, 1, null, null, "MeadHealthMinor"), new TalentNode("tmp_shieldlong", "Lasting Shield", "Divine Shield lasts +5 s per rank", 3, 6, 0, null, null, "ShieldSilver"), new TalentNode("tmp_beaconforce", "Radiant Beacon", "Beacon of Light heals +10% more per rank", 4, 6, 1, null, null, "MeadHealthMedium"), new TalentNode("tmp_beaconlong", "Enduring Beacon", "Beacon of Light regen lasts +3 s per rank", 3, 7, 0, null, null, "Honey"), new TalentNode("tmp_beaconfocus", "Beacon Focus", "Beacon of Light cooldown -5 s per rank", 3, 7, 1, null, null, "Flint"), new TalentNode("tmp_capstone", "Avatar of Light", "Your heals are +20% stronger and Blessing of Light also mends allies", 1, 8, 0, null, "#ffdd55", "TrophyValkyrie") } }, new SubSpecDef { Name = "Lightbringer", Role = "Holy Damage", Description = "The wrath of the light: Blessing of Light, Smite, Holy Nova, Consecration and Wrath of Light.", CapstoneId = "lbr_capstone", Tree = new TalentNode[17] { new TalentNode("lbr_light", "Lightbringer", "+3% spirit damage per rank", 5, 0, 0, null, null, "TrophyValkyrie"), new TalentNode("lbr_ward", "Blessed Plate", "+4 armor per rank", 5, 0, 1, null, null, "ShieldSilver"), new TalentNode("lbr_smiteforce", "Smite Power", "Smite deals +10% more per rank", 4, 1, 0, "lbr_light", null, "StaffLightning"), new TalentNode("lbr_smitefocus", "Quick Smite", "Smite cooldown -1 s per rank", 3, 1, 1, null, null, "Flint"), new TalentNode("lbr_novaforce", "Holy Nova Power", "Holy Nova deals +10% more per rank", 5, 2, 0, "lbr_smiteforce", null, "TrophyValkyrie"), new TalentNode("lbr_novawide", "Wide Nova", "Holy Nova radius +1 m per rank", 3, 2, 1, null, null, "TrophyValkyrie"), new TalentNode("lbr_notable", "Radiant", "+10% spirit and Smite pierces through foes", 1, 3, 0, "lbr_novaforce", "#ffd27a", "TrophyValkyrie"), new TalentNode("lbr_focus", "Devotion", "+5% eitr regeneration per rank", 4, 3, 1, null, null, "Eitr"), new TalentNode("lbr_consforce", "Searing Ground", "Consecration deals +10% more per rank", 5, 4, 0, null, null, "StaffLightning"), new TalentNode("lbr_conswide", "Wide Ground", "Consecration radius +1 m per rank", 3, 4, 1, null, null, "TrophyValkyrie"), new TalentNode("lbr_conslong", "Lasting Ground", "Consecration lasts +2 s per rank", 3, 5, 0, null, null, "TrophyValkyrie"), new TalentNode("lbr_vigor", "Sanctity", "+5% health regeneration per rank", 5, 5, 1, null, null, "MeadHealthMinor"), new TalentNode("lbr_wrathforce", "Wrath Power", "Wrath of Light deals +8% more per rank", 5, 6, 0, null, null, "TrophyDragonQueen"), new TalentNode("lbr_wrathwide", "Wide Wrath", "Wrath of Light radius +2 m per rank", 3, 6, 1, null, null, "TrophyValkyrie"), new TalentNode("lbr_wrathheal", "Radiant Wrath", "Wrath of Light heals you for each foe struck", 1, 7, 0, "lbr_wrathforce", "#ffd27a", "MeadHealthMedium"), new TalentNode("lbr_wrathfocus", "Wrath Focus", "Wrath of Light cooldown -5 s per rank", 3, 7, 1, null, null, "Flint"), new TalentNode("lbr_capstone", "Avatar of Wrath", "Your spirit deals +20% and Holy Nova strikes twice", 1, 8, 0, null, "#ffdd55", "TrophyValkyrie") } } } } } }, { PlayerClass.Ranger, RangerBranchDefinitions() } }; IdCache = new Dictionary>(); foreach (BranchDef[] value in Defs.Values) { for (int i = 0; i < value.Length; i++) { SubSpecDef[] subs = value[i].Subs; for (int j = 0; j < subs.Length; j++) { ExpandForLevel70(subs[j]); } } } } private static void ExpandForLevel70(SubSpecDef sub) { if (sub != null && sub.Tree != null && !string.IsNullOrEmpty(sub.CapstoneId)) { string text = sub.CapstoneId.Replace("_capstone", ""); TalentNode talentNode = sub.Tree.FirstOrDefault((TalentNode n) => n.Id == sub.CapstoneId); if (talentNode != null) { talentNode.Row = 11; } TalentNode[] second = new TalentNode[6] { new TalentNode(text + "_omenforce", "Omen Mastery", "Your level 30 path spell gains +6% power per rank", 5, 8, 0, null, null, "YggdrasilWood"), new TalentNode(text + "_omenreach", "Widening Omen", "Your level 30 path spell gains +0.5 m radius per rank", 5, 8, 1, null, null, "Crystal"), new TalentNode(text + "_mythicforce", "Mythic Mastery", "Your level 50 path spell gains +6% power per rank", 5, 9, 0, text + "_omenforce", null, "TrophyDragonQueen"), new TalentNode(text + "_mythicfocus", "Lingering Myth", "Your level 50 path spell gains +0.5 s duration per rank", 5, 9, 1, text + "_omenreach", null, "FlametalNew"), new TalentNode(text + "_asc_vigor", "Ascendant Vigor", "Both ascendant path spells gain +3% power per rank", 6, 10, 0, text + "_mythicforce", null, "MeadHealthMedium"), new TalentNode(text + "_asc_efficiency", "Divine Reservoir", "Both ascendant path spells cost 3% less stamina per rank", 6, 10, 1, text + "_mythicfocus", null, "MeadStaminaMedium") }; sub.Tree = sub.Tree.Concat(second).ToArray(); } } public static bool Has(PlayerClass cls) { return Defs.ContainsKey(cls); } public static int GetBranch(Player player) { if ((Object)(object)player == (Object)null || player.m_customData == null || !player.m_customData.TryGetValue("cdv_branch", out var value) || !int.TryParse(value, out var result)) { return -1; } BranchDef[] value2; int num = (Defs.TryGetValue(ClassSystem.GetClass(player), out value2) ? value2.Length : 0); if (result < 0 || result >= num) { return -1; } return result; } public static int GetSubSpec(Player player) { if ((Object)(object)player == (Object)null || player.m_customData == null || !player.m_customData.TryGetValue("cdv_subspec", out var value) || !int.TryParse(value, out var result)) { return -1; } if (result != 0 && result != 1) { return -1; } return result; } public static BranchDef CurrentBranch(Player player) { int branch = GetBranch(player); if (branch < 0 || !Defs.TryGetValue(ClassSystem.GetClass(player), out var value)) { return null; } return value[branch]; } public static SubSpecDef CurrentSub(Player player) { BranchDef branchDef = CurrentBranch(player); int subSpec = GetSubSpec(player); if (branchDef == null || subSpec < 0 || subSpec >= branchDef.Subs.Length) { return null; } return branchDef.Subs[subSpec]; } public static void SetBranch(Player player, int index) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)player == (Object)null) && GetBranch(player) < 0 && Defs.TryGetValue(ClassSystem.GetClass(player), out var value) && index >= 0 && index < value.Length && !value[index].ComingSoon) { player.m_customData["cdv_branch"] = index.ToString(); ((Character)player).Message((MessageType)2, "You embrace the " + value[index].Name + "!", 0, (Sprite)null); Effects.TryPlayAt(((Component)player).transform.position, "vfx_odin_despawn"); Effects.TryPlayAt(((Component)player).transform.position, "sfx_offering"); } } public static void SetSubSpec(Player player, int index) { //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) BranchDef branchDef = CurrentBranch(player); if (!((Object)(object)player == (Object)null) && branchDef != null && GetSubSpec(player) < 0 && index >= 0 && index < branchDef.Subs.Length) { if (!Abilities.DebugUnlockAll && ClassSystem.GetLevel(player) < 10) { ((Character)player).Message((MessageType)2, "Your path splits at level 10", 0, (Sprite)null); return; } player.m_customData["cdv_subspec"] = index.ToString(); ((Character)player).Message((MessageType)2, "You are now a " + branchDef.Subs[index].Name + "!", 0, (Sprite)null); Effects.TryPlayAt(((Component)player).transform.position, "vfx_odin_despawn"); Effects.TryPlayAt(((Component)player).transform.position, "sfx_offering"); } } public static void ClearChoices(Player player) { if (!((Object)(object)player == (Object)null) && player.m_customData != null) { player.m_customData.Remove("cdv_branch"); player.m_customData.Remove("cdv_subspec"); } } public static string Label(Player player) { SubSpecDef subSpecDef = CurrentSub(player); if (subSpecDef != null) { return subSpecDef.Name; } BranchDef branchDef = CurrentBranch(player); if (branchDef == null) { return string.Empty; } return branchDef.Name; } public static HashSet ValidIds(PlayerClass cls) { if (IdCache.TryGetValue(cls, out var value)) { return value; } HashSet hashSet = new HashSet(); if (Defs.TryGetValue(cls, out var value2)) { BranchDef[] array = value2; foreach (BranchDef branchDef in array) { TalentNode[] tree = branchDef.Tree; foreach (TalentNode talentNode in tree) { hashSet.Add(talentNode.Id); } SubSpecDef[] subs = branchDef.Subs; for (int j = 0; j < subs.Length; j++) { tree = subs[j].Tree; foreach (TalentNode talentNode2 in tree) { hashSet.Add(talentNode2.Id); } } } } IdCache[cls] = hashSet; return hashSet; } public static TalentNode FindDef(PlayerClass cls, string id) { if (!Defs.TryGetValue(cls, out var value)) { return null; } BranchDef[] array = value; foreach (BranchDef branchDef in array) { TalentNode talentNode = branchDef.Tree.FirstOrDefault((TalentNode n) => n.Id == id) ?? branchDef.Subs.SelectMany((SubSpecDef s) => s.Tree).FirstOrDefault((TalentNode n) => n.Id == id); if (talentNode != null) { return talentNode; } } return null; } public static bool HasCapstone(Player player) { if (!Defs.TryGetValue(ClassSystem.GetClass(player), out var value)) { return false; } return value.SelectMany((BranchDef b) => b.Subs).Any((SubSpecDef s) => !string.IsNullOrEmpty(s.CapstoneId) && TreeV2.StoredRank(player, s.CapstoneId) > 0); } private static BranchDef[] RangerBranchDefinitions() { return new BranchDef[3] { new BranchDef { Name = "Marksmanship", Color = "#d9b35f", Description = "Patient ranged execution: precision bows and armor-breaking crossbows.", BaseSpellHint = "Marked Shot", Tree = RangerBranchTree("rng_mark", "Steady Hand", "Measured Breath", "Keen Eye", "Predator's Patience", "Unerring Aim", "Master Marksman", "Bow", "ArrowBronze"), Subs = new SubSpecDef[2] { RangerCalling("de", "Deadeye", "Precision Bow", "A patient archer who marks one prey and ends the hunt with a single impossible shot.", "Aimed Shot", "Hunter's Mark", "Heartseeker", "One Shot", "BowHuntsman", "ArrowSilver", "TrophySerpent", "BowSpineSnap", "Eye of the Hunt", "Bow damage +20%; shots against distant enemies can critically strike."), RangerCalling("arb", "Arbalist", "Heavy Crossbow", "A siege hunter who cracks armor, holds ground and turns a crossbow into a field ballista.", "Armor Breaker", "Pavise", "Siege Bolt", "Ballista Salvo", "CrossbowArbalest", "ShieldIronTower", "BoltCarapace", "CrossbowRipper", "Walking Ballista", "Crossbow damage +20%; heavy bolts punch through an additional target.") } }, new BranchDef { Name = "Skirmishing", Color = "#59b8b0", Description = "Relentless movement: loose arrows while repositioning and control whole battle lines.", BaseSpellHint = "Evasive Shot", Tree = RangerBranchTree("rng_skirm", "Fleet Archer", "Light Quiver", "Loose Formation", "Wind Reader", "Running Shot", "Never Cornered", "BowFineWood", "Feathers"), Subs = new SubSpecDef[2] { RangerCalling("pf", "Pathfinder", "Mobile Archery", "A tireless scout who attacks while moving and vanishes down paths only they can see.", "Quickstep", "Rapid Fire", "Windrunner", "Ghost Trail", "Feathers", "BowFineWood", "MeadStaminaMedium", "TrophyHare", "Wayfinder", "Movement abilities cost less stamina and leave no opening for pursuit."), RangerCalling("vm", "Volley Master", "Area Archery", "A battlefield archer who splits shots and blankets chosen ground in disciplined volleys.", "Split Shot", "Arrow Rain", "Suppressing Volley", "Skyfall Barrage", "ArrowBronze", "BowDraugrFang", "ArrowCarapace", "TrophyGjall", "Lord of Arrows", "Volleys gain +20% damage and cover a wider battlefield.") } }, new BranchDef { Name = "Wilderness", Color = "#79a85b", Description = "Own the hunting ground with traps, venom and a temporary winged companion.", BaseSpellHint = "Snare Trap", Tree = RangerBranchTree("rng_wild", "Trailcraft", "Forager", "Hidden Threat", "Wild Instinct", "Patient Hunter", "Master of the Wild", "TrophyDeer", "Root"), Subs = new SubSpecDef[2] { RangerCalling("tr", "Trapper", "Control & Explosives", "A methodical hunter who turns terrain into a chain of snares, caltrops and violent surprises.", "Caltrops", "Explosive Trap", "Venom Mine", "Grand Hunt", "BronzeNails", "BombOoze", "Guck", "TrophyGoblinShaman", "Perfect Ambush", "Traps arm faster, strike harder and reset Snare Trap after the Grand Hunt."), RangerCalling("fal", "Falconer", "Winged Companion", "A wild scout fighting beside a temporary raptor that marks prey and tears open the battlefield.", "Falcon Strike", "Scout's Mark", "Wingstorm", "Apex Companion", "Feathers", "TrophyHatchling", "TrophyDeathsquito", "TrophySeeker", "Bond of the Sky", "Your companion lasts longer and coordinated attacks deal +20% damage.") } } }; } private static TalentNode[] RangerBranchTree(string prefix, string first, string second, string third, string fourth, string fifth, string notable, string iconA, string iconB) { return new TalentNode[6] { new TalentNode(prefix + "_power", first, "+4% Ranger ability damage per rank", 4, 0, 1, null, null, iconA), new TalentNode(prefix + "_breath", second, "+4% stamina regeneration per rank", 2, 1, 0, prefix + "_power", null, "MeadStaminaMinor"), new TalentNode(prefix + "_focus", third, "+3% bow and crossbow damage per rank", 2, 1, 2, prefix + "_power", null, iconB), new TalentNode(prefix + "_reach", fourth, "+4% projectile speed per rank", 2, 2, 0, prefix + "_breath", null, "Feathers"), new TalentNode(prefix + "_economy", fifth, "Ranger ability stamina cost -5% per rank", 2, 2, 2, prefix + "_focus", null, "MeadStaminaMedium"), new TalentNode(prefix + "_notable", notable, "+10% Ranger damage and Hunter's Focus activates 2 m sooner", 1, 3, 1, prefix + "_reach", "#ffd27a", "TrophySerpent") }; } private static SubSpecDef RangerCalling(string prefix, string name, string role, string description, string abilityA, string abilityB, string abilityC, string abilityD, string iconA, string iconB, string iconC, string iconD, string capstoneName, string capstoneDescription) { SubSpecDef subSpecDef = new SubSpecDef(); subSpecDef.Name = name; subSpecDef.Role = role; subSpecDef.Description = description; subSpecDef.CapstoneId = prefix + "_capstone"; subSpecDef.Tree = new TalentNode[17] { new TalentNode(prefix + "_power", "Hunter's Discipline", "+3% Ranger ability damage per rank", 5, 0, 0, null, null, iconA), new TalentNode(prefix + "_vigor", "Endless Quiver", "+4% stamina regeneration per rank", 5, 0, 1, null, null, "MeadStaminaMedium"), new TalentNode(prefix + "_a_force", abilityA + " Mastery", abilityA + " deals +8% damage per rank", 4, 1, 0, prefix + "_power", null, iconA), new TalentNode(prefix + "_a_focus", "Swift " + abilityA, abilityA + " cooldown -1 s per rank", 3, 1, 1, prefix + "_vigor", null, "Flint"), new TalentNode(prefix + "_b_force", abilityB + " Mastery", abilityB + " gains +8% power per rank", 4, 2, 0, prefix + "_a_force", null, iconB), new TalentNode(prefix + "_b_reach", "Far-reaching " + abilityB, abilityB + " radius or range +1 m per rank", 3, 2, 1, prefix + "_a_focus", null, "Feathers"), new TalentNode(prefix + "_notable", "Relentless Hunter", "+10% damage and +10% movement endurance", 1, 3, 0, prefix + "_b_force", "#ffd27a", iconA), new TalentNode(prefix + "_economy", "Efficient Technique", "Ability stamina cost -4% per rank", 4, 3, 1, prefix + "_b_reach", null, "MeadStaminaMinor"), new TalentNode(prefix + "_c_force", abilityC + " Mastery", abilityC + " deals +8% damage per rank", 5, 4, 0, prefix + "_notable", null, iconC), new TalentNode(prefix + "_c_reach", "Wide " + abilityC, abilityC + " radius or reach +1 m per rank", 3, 4, 1, prefix + "_economy", null, "ArrowBronze"), new TalentNode(prefix + "_tempo", "Hunting Rhythm", "Cooldowns recover 2% faster per rank", 5, 5, 0, prefix + "_c_force", null, "MeadStaminaMedium"), new TalentNode(prefix + "_survival", "Wilderness Sense", "+3 armor and +3% stamina regeneration per rank", 5, 5, 1, prefix + "_c_reach", null, "TrollHide"), new TalentNode(prefix + "_d_force", abilityD + " Mastery", abilityD + " deals +8% damage per rank", 5, 6, 0, prefix + "_tempo", null, iconD), new TalentNode(prefix + "_d_reach", "Unbound " + abilityD, abilityD + " radius or reach +1 m per rank", 3, 6, 1, prefix + "_survival", null, "YggdrasilWood"), new TalentNode(prefix + "_execution", "Clean Kill", "+15% damage against enemies below 35% health", 1, 7, 0, prefix + "_d_force", "#ffd27a", "TrophyGjall"), new TalentNode(prefix + "_d_focus", "Perfect Timing", abilityD + " cooldown -5 s per rank", 3, 7, 1, prefix + "_d_reach", null, "Flint"), new TalentNode(prefix + "_capstone", capstoneName, capstoneDescription, 1, 8, 0, prefix + "_execution", "#ffdd55", iconD) }; return subSpecDef; } } public enum CapstoneAuraVisibility { All, OthersOnly, Off } public static class CapstoneAura { private const string ZdoKey = "cdv_aura"; private static readonly Dictionary Auras = new Dictionary(); private static readonly Dictionary AuraClass = new Dictionary(); private static ConfigEntry Visibility; public static void Update(Player local) { EnsureConfig(); if (!ClassiPlugin.TalentsEnabled || (Object)(object)local == (Object)null) { RemoveAll(); return; } PlayerClass playerClass = ClassSystem.GetClass(local); bool flag = playerClass != PlayerClass.None && TalentSystem.HasCapstone(local); ZNetView nview = ((Character)local).m_nview; if ((Object)(object)nview != (Object)null && nview.IsValid()) { nview.GetZDO().Set("cdv_aura", (int)(flag ? playerClass : PlayerClass.None)); } CapstoneAuraVisibility capstoneAuraVisibility = ((Visibility != null) ? Visibility.Value : CapstoneAuraVisibility.All); if (capstoneAuraVisibility == CapstoneAuraVisibility.Off) { RemoveAll(); return; } HashSet hashSet = new HashSet(); foreach (Player allPlayer in Player.GetAllPlayers()) { if (!((Object)(object)allPlayer == (Object)null) && (!((Object)(object)allPlayer == (Object)(object)local) || capstoneAuraVisibility != CapstoneAuraVisibility.OthersOnly)) { int num; if ((Object)(object)allPlayer == (Object)(object)local) { num = (int)(flag ? playerClass : PlayerClass.None); } else { ZNetView nview2 = ((Character)allPlayer).m_nview; num = (((Object)(object)nview2 != (Object)null && nview2.IsValid()) ? nview2.GetZDO().GetInt("cdv_aura", 0) : 0); } if (num > 0) { hashSet.Add(allPlayer); Apply(allPlayer, (PlayerClass)num); } } } foreach (Player item in Auras.Keys.ToList()) { if ((Object)(object)item == (Object)null || !hashSet.Contains(item)) { Remove(item); } } } private static void EnsureConfig() { if (Visibility == null && !((Object)(object)ClassiPlugin.Instance == (Object)null)) { Visibility = ((BaseUnityPlugin)ClassiPlugin.Instance).Config.Bind("Accessibility", "CapstoneAuraVisibility", CapstoneAuraVisibility.All, "Which permanent capstone aura visuals this client renders: All, OthersOnly (hide your own), or Off. Gameplay bonuses and what other players see are unaffected."); } } private static void Apply(Player player, PlayerClass cls) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0300: Unknown result type (might be due to invalid IL or missing references) //IL_0305: Unknown result type (might be due to invalid IL or missing references) //IL_031b: Unknown result type (might be due to invalid IL or missing references) //IL_0328: Unknown result type (might be due to invalid IL or missing references) //IL_032f: Unknown result type (might be due to invalid IL or missing references) if (Auras.TryGetValue(player, out var value) && (Object)(object)value != (Object)null && AuraClass.TryGetValue(player, out var value2) && value2 == cls) { return; } Remove(player); AuraClass[player] = cls; GameObject val = new GameObject("cdv_capstone_aura"); val.transform.SetParent(((Component)player).transform, false); val.transform.localPosition = new Vector3(0f, 0.9f, 0f); Auras[player] = val; Light val2 = val.AddComponent(); val2.type = (LightType)2; val2.range = 5f; val2.intensity = 2f; val2.shadows = (LightShadows)0; switch (cls) { case PlayerClass.Mage: val2.color = new Color(0.45f, 0.65f, 1f); break; case PlayerClass.Berserker: val2.color = new Color(1f, 0.45f, 0.25f); break; case PlayerClass.Einherjar: val2.color = new Color(1f, 0.9f, 0.5f); break; case PlayerClass.Guardian: val2.color = new Color(0.75f, 0.85f, 1f); break; case PlayerClass.Druid: val2.color = new Color(0.6f, 1f, 0.55f); break; case PlayerClass.Ranger: val2.color = new Color(0.75f, 0.95f, 0.55f); break; default: val2.color = new Color(0.45f, 1f, 0.5f); break; } string text; Vector3 localPosition = default(Vector3); float num; switch (cls) { case PlayerClass.Mage: text = "demister_ball"; ((Vector3)(ref localPosition))..ctor(0.4f, 0.8f, 0f); num = 0.8f; break; case PlayerClass.Berserker: text = "vfx_Burning"; ((Vector3)(ref localPosition))..ctor(0f, -0.6f, 0f); num = 0.9f; break; case PlayerClass.Einherjar: text = "fx_Lightning"; ((Vector3)(ref localPosition))..ctor(0f, -0.8f, 0f); num = 0.35f; break; case PlayerClass.Guardian: text = "vfx_StaffShield"; ((Vector3)(ref localPosition))..ctor(0f, 0.1f, 0f); num = 0.5f; break; case PlayerClass.Druid: text = "demister_ball"; ((Vector3)(ref localPosition))..ctor(0f, 1.4f, 0f); num = 0.5f; break; case PlayerClass.Ranger: text = "vfx_Dodge"; ((Vector3)(ref localPosition))..ctor(0f, -0.7f, 0f); num = 0.7f; break; default: text = "vfx_Freezing"; ((Vector3)(ref localPosition))..ctor(0f, -0.6f, 0f); num = 1f; break; } GameObject val3 = Effects.FindPrefab(text); if ((Object)(object)val3 != (Object)null) { GameObject obj = Effects.InstantiateLocal(val3, val.transform.position, Quaternion.identity, val.transform); obj.transform.localPosition = localPosition; obj.transform.localScale = Vector3.one * num; MonoBehaviour[] componentsInChildren = obj.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); } } } private static void Remove(Player player) { if (Auras.TryGetValue(player, out var value) && (Object)(object)value != (Object)null) { Object.Destroy((Object)(object)value); } Auras.Remove(player); AuraClass.Remove(player); } private static void RemoveAll() { foreach (GameObject value in Auras.Values) { if ((Object)(object)value != (Object)null) { Object.Destroy((Object)(object)value); } } Auras.Clear(); AuraClass.Clear(); } } public static class ClassEquipment { private static readonly PlayerClass[] AllClasses = new PlayerClass[7] { PlayerClass.Mage, PlayerClass.Berserker, PlayerClass.Necromancer, PlayerClass.Einherjar, PlayerClass.Guardian, PlayerClass.Druid, PlayerClass.Ranger }; private static readonly Dictionary ModItems = new Dictionary(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary AffinityCache = new Dictionary(StringComparer.OrdinalIgnoreCase); private static readonly HashSet Marked = new HashSet(); private static ObjectDB _markedDb; private static bool _marking; private static bool _tooltipWarned; public static Color ColorOf(PlayerClass cls) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) return (Color)(cls switch { PlayerClass.Mage => new Color(0.45f, 0.72f, 1f), PlayerClass.Berserker => new Color(1f, 0.4f, 0.3f), PlayerClass.Necromancer => new Color(0.55f, 0.82f, 0.55f), PlayerClass.Einherjar => new Color(0.95f, 0.76f, 0.35f), PlayerClass.Ranger => new Color(0.55f, 0.82f, 0.42f), PlayerClass.Guardian => new Color(0.48f, 0.7f, 0.95f), PlayerClass.Druid => new Color(0.42f, 0.82f, 0.55f), _ => new Color(0.82f, 0.72f, 0.57f), }); } public static void Apply(Harmony harmony) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.GetDeclaredMethods(typeof(ItemData)).FirstOrDefault((MethodInfo m) => m.Name == "GetTooltip" && m.IsStatic && m.GetParameters().Length >= 3); if (methodInfo == null) { Logger.LogWarning((object)"ItemDrop.ItemData.GetTooltip not found: class equipment hints are disabled."); } else { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(ClassEquipment), "TooltipPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } public static void Decorate(CustomItem item, PlayerClass cls, string label, Color tint) { //IL_0070: Unknown result type (might be due to invalid IL or missing references) if (item == null || (Object)(object)item.ItemDrop == (Object)null || item.ItemDrop.m_itemData == null) { return; } SharedData shared = item.ItemDrop.m_itemData.m_shared; if (shared != null) { if (!string.IsNullOrEmpty(shared.m_name)) { ModItems[shared.m_name] = cls; } shared.m_description = Tag(cls, label) + "\n" + shared.m_description; RebuildIcons(shared, tint, null); } } private static Sprite RenderIcon(GameObject prefab) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown if ((Object)(object)prefab == (Object)null) { return null; } try { return RenderManager.Instance.Render(new RenderRequest(prefab) { Rotation = RenderManager.IsometricRotation, Width = 128, Height = 128, UseCache = true }); } catch (Exception ex) { Logger.LogWarning((object)("Could not render icon for " + ((Object)prefab).name + ": " + ex.Message)); return null; } } private static Sprite LoadCustomIcon(string prefab) { if (string.IsNullOrEmpty(prefab)) { return null; } try { string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); if (string.IsNullOrEmpty(directoryName)) { return null; } string text = Path.Combine(Path.Combine(directoryName, "icons"), prefab + ".png"); return File.Exists(text) ? AssetUtils.LoadSpriteFromFile(text) : null; } catch (Exception ex) { Logger.LogWarning((object)("Could not load custom icon for " + prefab + ": " + ex.Message)); return null; } } public static string Tag(PlayerClass cls, string label) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return "" + $"Way of the Gods — {cls} {label}"; } public static void EnsureMarks() { if (!_marking && !((Object)(object)ClassiPlugin.Instance == (Object)null) && ClassiPlugin.ClassEquipmentMarks != null && ClassiPlugin.ClassEquipmentMarks.Value) { ObjectDB instance = ObjectDB.instance; if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance == (Object)(object)_markedDb) && instance.m_items != null) { _markedDb = instance; _marking = true; ((MonoBehaviour)ClassiPlugin.Instance).StartCoroutine(MarkRoutine(instance)); } } } private static IEnumerator MarkRoutine(ObjectDB db) { int marked = 0; int batch = 0; foreach (GameObject item in db.m_items.ToList()) { if ((Object)(object)item == (Object)null) { continue; } ItemDrop component = item.GetComponent(); if ((Object)(object)component == (Object)null || component.m_itemData == null || component.m_itemData.m_shared == null) { continue; } PlayerClass[] array = ClassesFor(component.m_itemData); if (array.Length == 0) { continue; } SharedData shared = component.m_itemData.m_shared; Sprite val = ((shared.m_icons != null && shared.m_icons.Length != 0) ? shared.m_icons[0] : null); if (ModItems.ContainsKey(shared.m_name ?? string.Empty) && ((Object)(object)val == (Object)null || !Marked.Contains(val))) { Sprite val2 = LoadCustomIcon(((Object)item).name) ?? RenderIcon(item); if ((Object)(object)val2 != (Object)null) { shared.m_icons = (Sprite[])(object)new Sprite[1] { val2 }; } } if (RebuildIcons(shared, null, array)) { marked++; } int num = batch + 1; batch = num; if (num >= 12) { batch = 0; yield return null; } } _marking = false; Logger.LogInfo((object)$"Marked {marked} item icons with their class colours."); } private static PlayerClass[] ClassesFor(ItemData item) { if (item == null || item.m_shared == null) { return new PlayerClass[0]; } string name = item.m_shared.m_name; if (!string.IsNullOrEmpty(name) && AffinityCache.TryGetValue(name, out var value)) { return value; } PlayerClass value2; PlayerClass[] array = ((!string.IsNullOrEmpty(name) && ModItems.TryGetValue(name, out value2)) ? new PlayerClass[1] { value2 } : (IsCombatGear(item) ? AllClasses.Where((PlayerClass cls) => MagicProgression.FitsClassProfile(cls, item)).ToArray() : new PlayerClass[0])); if (!string.IsNullOrEmpty(name)) { AffinityCache[name] = array; } return array; } private static void TooltipPostfix(ItemData item, ref string __result) { try { string text = ClassLines(Player.m_localPlayer, item); if (!string.IsNullOrEmpty(text)) { __result = __result + "\n" + text; } } catch (Exception arg) { if (!_tooltipWarned) { _tooltipWarned = true; Logger.LogWarning((object)$"Class equipment tooltip failed: {arg}"); } } } private static string ClassLines(Player player, ItemData item) { if (item == null || item.m_shared == null || ClassiPlugin.ClassEquipmentMarks == null || !ClassiPlugin.ClassEquipmentMarks.Value) { return null; } List list = new List(); string name = item.m_shared.m_name; PlayerClass[] array = ((!string.IsNullOrEmpty(name) && ModItems.ContainsKey(name)) ? new PlayerClass[0] : ClassesFor(item)); if (array.Length != 0) { IEnumerable source = array.Select((PlayerClass cls) => $"{cls}"); list.Add("Way of the Gods — " + string.Join(" / ", source.ToArray()) + " " + KindOf(item)); } string text = AffinityLine(player, item); if (!string.IsNullOrEmpty(text)) { list.Add(text); } if (list.Count != 0) { return string.Join("\n", list.ToArray()); } return null; } private static string AffinityLine(Player player, ItemData item) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || ClassiPlugin.EquipmentRestrictions == null || ClassiPlugin.EquipmentRestrictions.Value == EquipmentRestrictionMode.Off) { return null; } PlayerClass playerClass = ClassSystem.GetClass(player); if (playerClass == PlayerClass.None || !IsCombatGear(item)) { return null; } if (MagicProgression.ItemFitsCalling(player, item)) { string text = ColorUtility.ToHtmlStringRGB(ColorOf(playerClass)); return "Channels your " + CallingName(player, playerClass) + " abilities"; } string text2 = MagicProgression.CallingRequirement(player); if (!string.IsNullOrEmpty(text2)) { return "" + text2 + " to cast"; } return null; } private static string CallingName(Player player, PlayerClass cls) { BranchDef branchDef = BranchSystem.CurrentBranch(player); if (branchDef != null) { return $"{cls} — {branchDef.Name}"; } return cls.ToString(); } private static string KindOf(ItemData item) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Invalid comparison between Unknown and I4 //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Invalid comparison between Unknown and I4 //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Invalid comparison between Unknown and I4 ItemType itemType = item.m_shared.m_itemType; if ((int)itemType != 4) { if ((int)itemType == 5) { return "shield"; } if ((int)item.m_shared.m_skillType != 9 && (int)item.m_shared.m_skillType != 10) { return "weapon"; } return "catalyst"; } return "ranged weapon"; } private static bool IsCombatGear(ItemData item) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Invalid comparison between Unknown and I4 //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Invalid comparison between Unknown and I4 ItemType itemType = item.m_shared.m_itemType; if (itemType - 3 <= 2 || (int)itemType == 14 || (int)itemType == 22) { return true; } return false; } private static bool RebuildIcons(SharedData shared, Color? tint, PlayerClass[] classes) { if (shared.m_icons == null || shared.m_icons.Length == 0) { return false; } Sprite[] array = (Sprite[])(object)new Sprite[shared.m_icons.Length]; bool flag = false; for (int i = 0; i < shared.m_icons.Length; i++) { Sprite val = (array[i] = shared.m_icons[i]); if ((Object)(object)val == (Object)null || Marked.Contains(val)) { continue; } Sprite val2 = Rebuild(val, tint, classes); if (!((Object)(object)val2 == (Object)null)) { if (classes != null && classes.Length != 0) { Marked.Add(val2); } array[i] = val2; flag = true; } } if (flag) { shared.m_icons = array; } return flag; } private static Sprite Rebuild(Sprite source, Color? tint, PlayerClass[] classes) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Expected O, but got Unknown if ((Object)(object)source == (Object)null || (Object)(object)source.texture == (Object)null || (source.packed && (int)source.packingRotation != 0)) { return null; } Texture2D texture = source.texture; Rect textureRect = source.textureRect; int num = Mathf.RoundToInt(((Rect)(ref textureRect)).width); int num2 = Mathf.RoundToInt(((Rect)(ref textureRect)).height); if (num <= 0 || num2 <= 0) { return null; } RenderTexture val = null; RenderTexture active = RenderTexture.active; try { Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(((Rect)(ref textureRect)).width / (float)((Texture)texture).width, ((Rect)(ref textureRect)).height / (float)((Texture)texture).height); Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(((Rect)(ref textureRect)).x / (float)((Texture)texture).width, ((Rect)(ref textureRect)).y / (float)((Texture)texture).height); val = RenderTexture.GetTemporary(num, num2, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)1); Graphics.Blit((Texture)(object)texture, val, val2, val3); RenderTexture.active = val; Texture2D val4 = new Texture2D(num, num2, (TextureFormat)4, false) { name = ((Object)texture).name + "_wotg", filterMode = ((Texture)texture).filterMode, wrapMode = (TextureWrapMode)1 }; val4.ReadPixels(new Rect(0f, 0f, (float)num, (float)num2), 0, 0); Color[] pixels = val4.GetPixels(); if (tint.HasValue) { Colorize(pixels, tint.Value); } if (classes != null && classes.Length != 0) { Stamp(pixels, num, num2, classes); } val4.SetPixels(pixels); val4.Apply(false, false); return Sprite.Create(val4, new Rect(0f, 0f, (float)num, (float)num2), new Vector2(0.5f, 0.5f), source.pixelsPerUnit); } catch (Exception ex) { Logger.LogWarning((object)("Could not rebuild item icon: " + ex.Message)); return null; } finally { RenderTexture.active = active; if ((Object)(object)val != (Object)null) { RenderTexture.ReleaseTemporary(val); } } } private static void Colorize(Color[] pixels, Color tint) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < pixels.Length; i++) { Color val = pixels[i]; if (!(val.a <= 0.01f)) { float num = 0.299f * val.r + 0.587f * val.g + 0.114f * val.b; float num2 = 0.25f + 0.85f * num; pixels[i] = new Color(Mathf.Clamp01(tint.r * num2), Mathf.Clamp01(tint.g * num2), Mathf.Clamp01(tint.b * num2), val.a); } } } private static void Stamp(Color[] pixels, int width, int height, PlayerClass[] classes) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) int num = Mathf.Min(classes.Length, 3); int num2 = Mathf.Max(3, Mathf.RoundToInt((float)width * 0.08f)); Color val = default(Color); ((Color)(ref val))..ctor(0.04f, 0.05f, 0.06f, 1f); for (int i = 0; i < height; i++) { int num3 = Mathf.Clamp(i * num / Mathf.Max(1, height), 0, num - 1); Color val2 = ColorOf(classes[num - 1 - num3]); for (int j = 0; j < num2 && j < width; j++) { bool flag = j == num2 - 1 || i == 0 || i == height - 1; pixels[i * width + j] = (Color)(flag ? val : new Color(val2.r, val2.g, val2.b, 1f)); } } } } public static class ClassGUI { private sealed class ClassPresentation { public readonly PlayerClass Class; public readonly string Role; public readonly string Description; public readonly string Equipment; public readonly string Resource; public readonly string PreviewPath; public readonly string PreviewResource; public readonly Color Accent; public ClassPresentation(PlayerClass cls, string role, string description, string equipment, string resource, string previewPath, string previewResource, Color accent) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) Class = cls; Role = role; Description = description; Equipment = equipment; Resource = resource; PreviewPath = previewPath; PreviewResource = previewResource; Accent = accent; } } [CompilerGenerated] private static class <>O { public static Action <0>__CloseClassGuide; public static Action <1>__Close; public static UnityAction <2>__Close; public static UnityAction <3>__CloseClassGuide; public static UnityAction <4>__EnterTrainingHall; public static UnityAction <5>__OpenClassGuide; public static UnityAction <6>__ChooseCarouselClass; } [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static UnityAction <>9__23_0; public static UnityAction <>9__24_0; public static UnityAction <>9__24_1; public static UnityAction <>9__24_2; public static UnityAction <>9__24_3; public static UnityAction <>9__52_0; public static UnityAction <>9__52_1; public static UnityAction <>9__52_3; internal void b__23_0() { TrainingHall.Leave(); Close(); } internal void b__24_0() { MoveCarousel(-1); } internal void b__24_1() { MoveCarousel(1); } internal void b__24_2() { MoveCarousel(-1); } internal void b__24_3() { MoveCarousel(1); } internal void b__52_0() { if (ClassTrialSystem.TryStart(Player.m_localPlayer)) { Close(); } } internal void b__52_1() { OfferTrophy(Player.m_localPlayer); Rebuild(); } internal void b__52_3() { Close(); TalentGUI.Open(); } } private const int BossTrophyXp = 500; private static readonly ClassPresentation[] CarouselClasses = new ClassPresentation[7] { new ClassPresentation(PlayerClass.Mage, "DAMAGE", "Fire, frost and lightning answer your call.", "Elemental staves", "Eitr", "FIRE / PYROMANCER", "Eitr", ClassEquipment.ColorOf(PlayerClass.Mage)), new ClassPresentation(PlayerClass.Berserker, "DAMAGE", "Break enemy lines with charges and devastating heavy blows.", "Two-handed melee", "Stamina", "CRUSHING / JUGGERNAUT", "Stamina", ClassEquipment.ColorOf(PlayerClass.Berserker)), new ClassPresentation(PlayerClass.Necromancer, "DAMAGE", "Spread corruption and command an army beyond death.", "Blood magic staves", "Eitr", "PLAGUE / PESTILENT", "Eitr", ClassEquipment.ColorOf(PlayerClass.Necromancer)), new ClassPresentation(PlayerClass.Einherjar, "DAMAGE", "Fight beneath the storm with radiant spears and Valhalla's glory.", "Spears and polearms", "Eitr / Stamina", "STORM / THUNDERER", "Eitr", ClassEquipment.ColorOf(PlayerClass.Einherjar)), new ClassPresentation(PlayerClass.Ranger, "DAMAGE", "Master bowcraft, precision shots, traps and a wild companion.", "Bows and crossbows", "Stamina", "MARKSMANSHIP / DEADEYE", "Stamina", ClassEquipment.ColorOf(PlayerClass.Ranger)), new ClassPresentation(PlayerClass.Guardian, "TANK", "Stand as the living shield: endure, taunt and protect the clan.", "Shield and melee", "Stamina / Eitr", "BULWARK / WARDEN", "Stamina", ClassEquipment.ColorOf(PlayerClass.Guardian)), new ClassPresentation(PlayerClass.Druid, "HEALER / HYBRID", "Mend allies, bind enemies and assume the forms of the wild.", "Nature foci, claws or bare hands", "Stamina / Eitr", "WILD SHAPE / WEREWOLF", "Stamina", ClassEquipment.ColorOf(PlayerClass.Druid)) }; private static readonly Dictionary ClassArtworkTextures = new Dictionary(); private static readonly Dictionary ClassArtworkSprites = new Dictionary(); private static readonly HashSet MissingClassArtwork = new HashSet(); private static readonly HashSet BossTrophyTokens = new HashSet { "$item_trophy_eikthyr", "$item_trophy_elder", "$item_trophy_bonemass", "$item_trophy_dragonqueen", "$item_trophy_goblinking", "$item_trophy_seekerqueen", "$item_trophy_fader" }; private static readonly HashSet BossTrophyPrefabs = new HashSet { "TrophyEikthyr", "TrophyTheElder", "TrophyBonemass", "TrophyDragonQueen", "TrophyGoblinKing", "TrophySeekerQueen", "TrophyFader" }; private static GameObject _panel; private static int _carouselIndex; private static bool _classSelectionOpen; private static bool _classGuideOpen; private static int _guideBranch; private static int _guideSub; private static float _panelWidth = 700f; private static float _panelHeight = 700f; public static bool IsOpen => (Object)(object)_panel != (Object)null; public static void UpdateController() { if (_classGuideOpen) { if (Input.GetKeyDown((KeyCode)27) || Input.GetKeyDown((KeyCode)8)) { if (TrainingHall.IsActive) { Close(); } else { CloseClassGuide(); } } else if (Input.GetKeyDown((KeyCode)276)) { MoveGuideCalling(-1); } else if (Input.GetKeyDown((KeyCode)275)) { MoveGuideCalling(1); } else { ControllerSupport.UpdatePanel(_panel, CloseClassGuide); } return; } if (_classSelectionOpen) { if (Input.GetKeyDown((KeyCode)276)) { MoveCarousel(-1); return; } if (Input.GetKeyDown((KeyCode)275)) { MoveCarousel(1); return; } if (Input.GetKeyDown((KeyCode)13) || Input.GetKeyDown((KeyCode)271)) { ChooseCarouselClass(); return; } if (Input.GetKeyDown((KeyCode)105) || ControllerSupport.TryConsumePanelDetails()) { OpenClassGuide(); return; } if (ControllerSupport.TryConsumeHorizontalPanelNavigation(out var direction)) { MoveCarousel(direction); return; } } ControllerSupport.UpdatePanel(_panel, Close); } public static void Toggle() { if (IsOpen) { Close(); } else { Open(); } } public static void Open() { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && GUIManager.Instance != null && !((Object)(object)GUIManager.CustomGUIFront == (Object)null)) { Build(localPlayer); GUIManager.BlockInput(true); } } public static void Close() { if ((Object)(object)_panel != (Object)null) { Object.Destroy((Object)(object)_panel); _panel = null; } _classSelectionOpen = false; _classGuideOpen = false; GUIManager.BlockInput(false); } private static void Rebuild() { if ((Object)(object)_panel != (Object)null) { Object.Destroy((Object)(object)_panel); _panel = null; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { Build(localPlayer); } } private static void Build(Player player) { //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_02f0: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_030f: Unknown result type (might be due to invalid IL or missing references) //IL_0314: Unknown result type (might be due to invalid IL or missing references) //IL_031a: Expected O, but got Unknown //IL_026b: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Unknown result type (might be due to invalid IL or missing references) //IL_024b: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Expected O, but got Unknown //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Expected O, but got Unknown //IL_02af: Unknown result type (might be due to invalid IL or missing references) //IL_028a: Unknown result type (might be due to invalid IL or missing references) //IL_028f: Unknown result type (might be due to invalid IL or missing references) //IL_0295: Expected O, but got Unknown //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Expected O, but got Unknown //IL_02ce: Unknown result type (might be due to invalid IL or missing references) //IL_02d3: Unknown result type (might be due to invalid IL or missing references) //IL_02d9: Expected O, but got Unknown if (TrainingHall.IsActive) { _classGuideOpen = true; _guideBranch = Mathf.Max(0, TrainingHall.CurrentBranch); _guideSub = Mathf.Max(0, TrainingHall.CurrentSub); } _classSelectionOpen = ClassSystem.GetClass(player) == PlayerClass.None; int num; float panelWidth; if (!_classSelectionOpen) { num = (_classGuideOpen ? 1 : 0); if (num == 0) { panelWidth = 700f; goto IL_0074; } } else { num = 1; } panelWidth = Mathf.Max(560f, Mathf.Min(1380f, (float)Screen.width - 40f)); goto IL_0074; IL_0074: _panelWidth = panelWidth; _panelHeight = ((num != 0) ? Mathf.Max(560f, Mathf.Min(820f, (float)Screen.height - 40f)) : 700f); _panel = GUIManager.Instance.CreateWoodpanel(GUIManager.CustomGUIFront.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, _panelWidth, _panelHeight, false); ((Object)_panel).name = (_classGuideOpen ? "cdv_class_guide" : (_classSelectionOpen ? "cdv_class_carousel" : "cdv_class_info")); AddLine("Temple of Classes", -45f, 28, GUIManager.Instance.ValheimOrange, 44f); if (_classGuideOpen) { BuildClassGuide(player); } else if (_classSelectionOpen) { BuildClassSelection(); _panel.AddComponent(); } else { BuildClassInfo(player); } if (_classGuideOpen && TrainingHall.IsActive) { Vector2 position = new Vector2(-105f, 30f); object obj = <>c.<>9__23_0; if (obj == null) { UnityAction val = delegate { TrainingHall.Leave(); Close(); }; <>c.<>9__23_0 = val; obj = (object)val; } AddButton("Leave training hall", position, 250f, 40f, (UnityAction)obj, anchorBottom: true, "cdv_training_leave"); Vector2 position2 = new Vector2(125f, 30f); object obj2 = <>O.<2>__Close; if (obj2 == null) { UnityAction val2 = Close; <>O.<2>__Close = val2; obj2 = (object)val2; } AddButton("Keep training", position2, 190f, 40f, (UnityAction)obj2, anchorBottom: true); } else if (_classGuideOpen) { Vector2 position3 = new Vector2(-235f, 30f); object obj3 = <>O.<3>__CloseClassGuide; if (obj3 == null) { UnityAction val3 = CloseClassGuide; <>O.<3>__CloseClassGuide = val3; obj3 = (object)val3; } AddButton("Back to classes", position3, 190f, 40f, (UnityAction)obj3, anchorBottom: true, "cdv_class_guide_back"); Vector2 position4 = new Vector2(0f, 30f); object obj4 = <>O.<4>__EnterTrainingHall; if (obj4 == null) { UnityAction val4 = EnterTrainingHall; <>O.<4>__EnterTrainingHall = val4; obj4 = (object)val4; } AddButton("Train this calling", position4, 230f, 40f, (UnityAction)obj4, anchorBottom: true, "cdv_training_enter"); Vector2 position5 = new Vector2(235f, 30f); object obj5 = <>O.<2>__Close; if (obj5 == null) { UnityAction val5 = Close; <>O.<2>__Close = val5; obj5 = (object)val5; } AddButton("Close", position5, 160f, 40f, (UnityAction)obj5, anchorBottom: true); } else { Vector2 position6 = new Vector2(0f, 30f); object obj6 = <>O.<2>__Close; if (obj6 == null) { UnityAction val6 = Close; <>O.<2>__Close = val6; obj6 = (object)val6; } AddButton("Close", position6, 160f, 40f, (UnityAction)obj6, anchorBottom: true); } } private static void BuildClassSelection() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Expected O, but got Unknown //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Expected O, but got Unknown //IL_02a6: Unknown result type (might be due to invalid IL or missing references) //IL_027e: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Expected O, but got Unknown //IL_02ce: Unknown result type (might be due to invalid IL or missing references) //IL_02d3: Unknown result type (might be due to invalid IL or missing references) //IL_02d9: Expected O, but got Unknown //IL_031a: Unknown result type (might be due to invalid IL or missing references) AddLine("Choose your path, viking.", -78f, 15, Color.white); AddLine("Nothing is lost by changing class: level, talents and callings are kept for every class you play.", -100f, 12, new Color(0.75f, 0.78f, 0.82f), 20f, Mathf.Min(880f, _panelWidth - 120f)); AddLine($"{_carouselIndex + 1} / {CarouselClasses.Length}", -47f, 13, new Color(0.72f, 0.75f, 0.8f), 30f, 90f, _panelWidth / 2f - 72f); float num = _panelHeight / 2f - 114f; float num2 = (0f - _panelHeight) / 2f + 88f; float num3 = num - num2; float num4 = Mathf.Min(560f, num3); float num5 = Mathf.Min(640f, _panelWidth * 0.52f); float num6 = Mathf.Clamp((_panelWidth - num5 - 124f) / 2f, 145f, 230f); float height = Mathf.Min(370f, num4 * 0.72f); float num7 = (num + num2) / 2f + 8f; float num8 = num5 / 2f + num6 / 2f + 27f; ClassPresentation presentation = CarouselClasses[_carouselIndex]; int num9 = (_carouselIndex - 1 + CarouselClasses.Length) % CarouselClasses.Length; int num10 = (_carouselIndex + 1) % CarouselClasses.Length; ClassPresentation presentation2 = CarouselClasses[num9]; Vector2 position = new Vector2(0f - num8, num7); object obj = <>c.<>9__24_0; if (obj == null) { UnityAction val = delegate { MoveCarousel(-1); }; <>c.<>9__24_0 = val; obj = (object)val; } DrawClassCard(presentation2, position, num6, height, selected: false, "cdv_class_previous", (UnityAction)obj); DrawClassCard(presentation, new Vector2(0f, num7), num5, num4, selected: true, "cdv_class_selected", null); ClassPresentation presentation3 = CarouselClasses[num10]; Vector2 position2 = new Vector2(num8, num7); object obj2 = <>c.<>9__24_1; if (obj2 == null) { UnityAction val2 = delegate { MoveCarousel(1); }; <>c.<>9__24_1 = val2; obj2 = (object)val2; } DrawClassCard(presentation3, position2, num6, height, selected: false, "cdv_class_next", (UnityAction)obj2); Vector2 position3 = new Vector2((0f - _panelWidth) / 2f + 34f, num7); object obj3 = <>c.<>9__24_2; if (obj3 == null) { UnityAction val3 = delegate { MoveCarousel(-1); }; <>c.<>9__24_2 = val3; obj3 = (object)val3; } AddCarouselButton("<", position3, 48f, 48f, "cdv_class_arrow_previous", (UnityAction)obj3); Vector2 position4 = new Vector2(_panelWidth / 2f - 34f, num7); object obj4 = <>c.<>9__24_3; if (obj4 == null) { UnityAction val4 = delegate { MoveCarousel(1); }; <>c.<>9__24_3 = val4; obj4 = (object)val4; } AddCarouselButton(">", position4, 48f, 48f, "cdv_class_arrow_next", (UnityAction)obj4); DrawCarouselDots(num2 + 5f); AddLine(ControllerSupport.ShowControllerLabels ? "D-pad / stick: browse Y: abilities A: choose B: close" : "Arrow keys, wheel or side cards: browse I: abilities Enter: choose", 0f - _panelHeight + 60f, 12, new Color(0.75f, 0.78f, 0.82f), 30f, Mathf.Min(700f, _panelWidth - 220f)); } private static void DrawClassCard(ClassPresentation presentation, Vector2 position, float width, float height, bool selected, string objectName, UnityAction onClick) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_0270: Expected O, but got Unknown //IL_0295: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Unknown result type (might be due to invalid IL or missing references) //IL_02bf: Unknown result type (might be due to invalid IL or missing references) //IL_02ca: Unknown result type (might be due to invalid IL or missing references) //IL_02da: Unknown result type (might be due to invalid IL or missing references) //IL_031f: Unknown result type (might be due to invalid IL or missing references) //IL_0304: Unknown result type (might be due to invalid IL or missing references) //IL_0336: Unknown result type (might be due to invalid IL or missing references) //IL_05af: Unknown result type (might be due to invalid IL or missing references) //IL_05c3: Unknown result type (might be due to invalid IL or missing references) //IL_05f4: Unknown result type (might be due to invalid IL or missing references) //IL_0607: Unknown result type (might be due to invalid IL or missing references) //IL_035f: Unknown result type (might be due to invalid IL or missing references) //IL_0373: Unknown result type (might be due to invalid IL or missing references) //IL_03a4: Unknown result type (might be due to invalid IL or missing references) //IL_03b7: Unknown result type (might be due to invalid IL or missing references) //IL_03d9: Unknown result type (might be due to invalid IL or missing references) //IL_03fb: Unknown result type (might be due to invalid IL or missing references) //IL_0430: Unknown result type (might be due to invalid IL or missing references) //IL_0452: Unknown result type (might be due to invalid IL or missing references) //IL_0491: Unknown result type (might be due to invalid IL or missing references) //IL_04a0: Unknown result type (might be due to invalid IL or missing references) //IL_04b9: Unknown result type (might be due to invalid IL or missing references) //IL_052a: Unknown result type (might be due to invalid IL or missing references) //IL_0539: Unknown result type (might be due to invalid IL or missing references) //IL_0551: Unknown result type (might be due to invalid IL or missing references) //IL_04ef: Unknown result type (might be due to invalid IL or missing references) //IL_04f4: Unknown result type (might be due to invalid IL or missing references) //IL_04fa: Expected O, but got Unknown //IL_0587: Unknown result type (might be due to invalid IL or missing references) //IL_058c: Unknown result type (might be due to invalid IL or missing references) //IL_0592: Expected O, but got Unknown GameObject val = new GameObject(objectName, new Type[1] { typeof(RectTransform) }); val.transform.SetParent(_panel.transform, false); RectTransform component = val.GetComponent(); Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(0.5f, 0.5f); component.anchorMax = val2; component.anchorMin = val2; component.anchoredPosition = position; component.sizeDelta = new Vector2(width, height); Image val3 = val.AddComponent(); ((Graphic)val3).color = (selected ? new Color(0.025f, 0.03f, 0.038f, 0.98f) : new Color(0.025f, 0.03f, 0.038f, 0.82f)); Outline obj = val.AddComponent(); ((Shadow)obj).effectColor = (selected ? new Color(presentation.Accent.r, presentation.Accent.g, presentation.Accent.b, 0.9f) : new Color(0.55f, 0.52f, 0.47f, 0.55f)); ((Shadow)obj).effectDistance = (selected ? new Vector2(2f, -2f) : new Vector2(1f, -1f)); ((Shadow)obj).useGraphicAlpha = false; val.AddComponent(); float num = (selected ? Mathf.Clamp(height * 0.37f, 164f, 190f) : 76f); float height2 = (selected ? (height - num) : height); Sprite artwork = ClassArtworkSprite(presentation.Class); DrawClassArtwork(val.transform, artwork, width, height2, selected ? (num / 2f) : 0f, selected ? 1f : 0.67f); GameObject val4 = new GameObject("shade", new Type[1] { typeof(RectTransform) }); val4.transform.SetParent(val.transform, false); RectTransform component2 = val4.GetComponent(); component2.anchorMin = Vector2.zero; component2.anchorMax = Vector2.one; component2.offsetMin = Vector2.zero; component2.offsetMax = Vector2.zero; Image obj2 = val4.AddComponent(); ((Graphic)obj2).color = (selected ? new Color(0f, 0f, 0f, 0.05f) : new Color(0f, 0f, 0f, 0.2f)); ((Graphic)obj2).raycastTarget = false; GameObject val5 = new GameObject("class_info", new Type[1] { typeof(RectTransform) }); val5.transform.SetParent(val.transform, false); RectTransform component3 = val5.GetComponent(); component3.anchorMin = new Vector2(0f, 0f); component3.anchorMax = new Vector2(1f, 0f); component3.pivot = new Vector2(0.5f, 0f); component3.anchoredPosition = Vector2.zero; component3.sizeDelta = new Vector2(0f, num); Image obj3 = val5.AddComponent(); ((Graphic)obj3).color = (selected ? new Color(0.015f, 0.02f, 0.027f, 0.96f) : new Color(0.015f, 0.02f, 0.027f, 0.9f)); ((Graphic)obj3).raycastTarget = false; DrawAccentStrip(val.transform, presentation.Accent, width); if (selected) { AddCardText(val5.transform, presentation.Role, new Vector2(18f, -14f), width - 36f, 22f, 12, presentation.Accent, (TextAnchor)3); AddCardText(val5.transform, presentation.Class.ToString(), new Vector2(18f, -36f), width - 36f, 30f, 25, Color.white, (TextAnchor)3); AddCardText(val5.transform, presentation.Description, new Vector2(18f, -68f), width - 36f, 34f, 13, new Color(0.86f, 0.88f, 0.91f), (TextAnchor)0); AddCardText(val5.transform, presentation.Equipment + " - Uses " + presentation.Resource, new Vector2(18f, 0f - (num - 64f)), width - 36f, 20f, 12, new Color(0.82f, 0.72f, 0.57f), (TextAnchor)3); float num2 = Mathf.Min(238f, (width - 54f) / 2f); GameObject obj4 = GUIManager.Instance.CreateButton("View abilities", val5.transform, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2((0f - num2) / 2f - 5f, 23f), num2, 34f); ((Object)obj4).name = "cdv_class_guide_open"; ButtonClickedEvent onClick2 = obj4.GetComponent