Decompiled source of T4ylorSurvivors v1.0.0

plugins/TaylorsBalancePatch.dll

Decompiled 7 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using EntityStates;
using EntityStates.Bandit2.Weapon;
using EntityStates.Chef;
using EntityStates.Commando;
using EntityStates.Commando.CommandoWeapon;
using EntityStates.Croco;
using EntityStates.Drifter;
using EntityStates.Drone.DroneWeapon;
using EntityStates.DroneTech.Weapon;
using EntityStates.Engi.EngiWeapon;
using EntityStates.Engi.Mine;
using EntityStates.FalseSon;
using EntityStates.Huntress;
using EntityStates.Loader;
using EntityStates.Mage.Weapon;
using EntityStates.Merc;
using EntityStates.Merc.Weapon;
using EntityStates.Railgunner.Weapon;
using EntityStates.Treebot;
using EntityStates.Treebot.Weapon;
using EntityStates.VoidSurvivor.Weapon;
using IL.EntityStates.Chef;
using IL.EntityStates.Commando.CommandoWeapon;
using IL.EntityStates.Drifter;
using IL.EntityStates.FalseSon;
using IL.EntityStates.Mage;
using IL.EntityStates.Mage.Weapon;
using IL.EntityStates.Merc;
using IL.EntityStates.Treebot.Weapon;
using IL.EntityStates.VoidSurvivor.Weapon;
using IL.RoR2;
using IL.RoR2.Projectile;
using IL.RoR2.UI;
using KinematicCharacterController;
using Microsoft.CodeAnalysis;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Collections.Generic;
using MonoMod.Cil;
using MonoMod.RuntimeDetour;
using On;
using On.EntityStates;
using On.EntityStates.Bandit2.Weapon;
using On.EntityStates.Chef;
using On.EntityStates.Commando;
using On.EntityStates.Commando.CommandoWeapon;
using On.EntityStates.Croco;
using On.EntityStates.Drone.DroneWeapon;
using On.EntityStates.DroneTech.Weapon;
using On.EntityStates.Engi.Mine;
using On.EntityStates.FalseSon;
using On.EntityStates.Loader;
using On.EntityStates.Mage.Weapon;
using On.EntityStates.Merc;
using On.EntityStates.Merc.Weapon;
using On.EntityStates.Railgunner.Weapon;
using On.EntityStates.Treebot;
using On.EntityStates.Treebot.Weapon;
using On.EntityStates.VoidSurvivor.Weapon;
using On.RoR2;
using On.RoR2.Projectile;
using On.RoR2.Skills;
using On.RoR2.UI;
using RoR2;
using RoR2.AsyncManagement;
using RoR2.ContentManagement;
using RoR2.Networking;
using RoR2.Projectile;
using RoR2.Skills;
using RoR2.UI;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("TaylorsBalancePatch")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("T4ylorSurvivors balance changes for Risk of Rain 2.")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+44d523b5fbe8978c8f396df84e4f4ce33addf3e5")]
[assembly: AssemblyProduct("TaylorsBalancePatch")]
[assembly: AssemblyTitle("TaylorsBalancePatch")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 TaylorsBalancePatch
{
	internal static class AcolyteBalance
	{
	}
	internal sealed class AcolyteChanges : IDisposable
	{
		internal AcolyteChanges(ManualLogSource log)
		{
		}

		internal void Enable()
		{
		}

		public void Dispose()
		{
		}
	}
	internal static class AcridBalance
	{
		internal const string ConfigSection = "Acrid";

		internal const string ConfigKey = "EnableAcridChanges";

		internal const string ConfigDescription = "Enable all Acrid passive and skill changes and descriptions. Restart the game after changing this setting.";

		internal const float BlightBaseDuration = 8f;

		internal const float BlightProcPerStack = 0.1f;

		internal const int BreathBlightTickInterval = 4;

		internal const float NeurotoxinCooldown = 2.5f;

		internal const int FrenziedLeapStock = 1;

		internal const float FrenziedLeapCooldown = 8f;

		internal const float BreathPoisonDuration = 10f;

		internal const float SpawnProtectionTail = 2f;

		internal static float GetBlightProcCoefficient(int totalStacks, int attackerStacks)
		{
			if (totalStacks <= 0 || attackerStacks <= 0)
			{
				return 0f;
			}
			return Math.Min(1f, (float)totalStacks * 0.1f) * (float)Math.Min(attackerStacks, totalStacks) / (float)totalStacks;
		}

		internal static string? GetDescription(string token)
		{
			return token switch
			{
				"CROCO_PASSIVE_ALT_DESCRIPTION" => "Attacks that apply <style=cIsHealing>Poison</style> apply stacking <style=cIsDamage>Blight</style> instead, dealing <style=cIsDamage>60% damage per second</style>. <color=#C586FF><b>Each stack lasts 8 seconds. Each Blight tick has 0.1 proc coefficient per stack, capped at 1.0 total per victim per tick across all attackers; ticks can trigger on-hit items.</b></color>", 
				"CROCO_SECONDARY_DESCRIPTION" => "<style=cIsHealing>Poisonous</style>. Spit toxic bile for <style=cIsDamage>240% damage</style>. <color=#C586FF><b>Base cooldown: 2.5 seconds.</b></color>", 
				"CROCO_UTILITY_ALT1_DESCRIPTION" => "<style=cIsDamage>Stunning</style>. Leap in the air, dealing <style=cIsDamage>550% damage</style>. <style=cIsUtility>Reduce</style> the cooldown by <style=cIsUtility>2s</style> for every enemy hit. <color=#C586FF><b>Poisonous. Holds 1 charge. Base cooldown: 8 seconds.</b></color>", 
				"CROCO_SPECIAL_ALT_DESCRIPTION" => "<style=cIsHealing>Poisonous</style>. Emit a lingering cloud of toxic breath for <style=cIsDamage>240% damage per second</style>. <color=#C586FF><b>Uses your equipped passive: Poison applies every accepted tick; Blight applies on the first tick and every 4 ticks after that, per enemy and cloud.</b></color>", 
				_ => null, 
			};
		}
	}
	internal sealed class BreathTickSequence
	{
		private int tick;

		internal bool NextAppliesBlight()
		{
			bool result = tick == 0;
			tick = (tick + 1) % 4;
			return result;
		}
	}
	internal sealed class BlightProcBudget<T> where T : notnull
	{
		private readonly Dictionary<T, int> stacks = new Dictionary<T, int>();

		private readonly HashSet<T> consumed = new HashSet<T>();

		private int totalStacks;

		internal void AddStack(T attacker)
		{
			totalStacks++;
			stacks.TryGetValue(attacker, out var value);
			stacks[attacker] = value + 1;
		}

		internal void AddUnattributedStack()
		{
			totalStacks++;
		}

		internal float TakeProc(T attacker)
		{
			if (!consumed.Add(attacker) || !stacks.TryGetValue(attacker, out var value))
			{
				return 0f;
			}
			return AcridBalance.GetBlightProcCoefficient(totalStacks, value);
		}
	}
	internal sealed class AcridChanges : IDisposable
	{
		private sealed class BlightTickContext
		{
			internal readonly GameObject controllerObject;

			internal readonly BlightProcBudget<GameObject> budget = new BlightProcBudget<GameObject>();

			internal BlightTickContext(GameObject controllerObject)
			{
				this.controllerObject = controllerObject;
			}
		}

		[CompilerGenerated]
		private static class <>O
		{
			public static hook_InflictDot_refInflictDotInfo <0>__BlightDuration;

			public static hook_TakeDamage <1>__BlightDamage;

			public static hook_GetBlastDamageType <2>__FrenziedLeapDamageType;

			public static hook_FireProjectile <3>__BreathProjectile;

			public static hook_GetDamageType <4>__CrocoDamageType;

			public static hook_GetLocalizedStringByToken <5>__Description;
		}

		[ThreadStatic]
		private static int breathProjectileSetupDepth;

		private readonly ManualLogSource log;

		private readonly List<Action> cleanup = new List<Action>();

		private readonly Dictionary<Spawn, CharacterBody> protectedSpawns = new Dictionary<Spawn, CharacterBody>();

		private SkillDef? neurotoxin;

		private SkillDef? frenziedLeap;

		private float originalNeurotoxinCooldown;

		private int originalFrenziedLeapStock;

		private float originalFrenziedLeapCooldown;

		private GameObject? breathProjectilePrefab;

		private ConditionalWeakTable<ProjectileController, ConditionalWeakTable<HealthComponent, BreathTickSequence>> breathTicks = new ConditionalWeakTable<ProjectileController, ConditionalWeakTable<HealthComponent, BreathTickSequence>>();

		private FieldInfo? dotStacksField;

		private FieldInfo? stackIndexField;

		private FieldInfo? stackAttackerField;

		[ThreadStatic]
		private static BlightTickContext? activeBlightTick;

		internal AcridChanges(ManualLogSource log)
		{
			this.log = log;
		}

		internal void Enable()
		{
			try
			{
				dotStacksField = typeof(DotController).GetField("dotStackList", BindingFlags.Instance | BindingFlags.NonPublic) ?? throw new MissingFieldException("DotController.dotStackList");
				Type type = dotStacksField.FieldType.GetGenericArguments()[0];
				stackIndexField = type.GetField("dotIndex") ?? throw new MissingFieldException("DotStack.dotIndex");
				stackAttackerField = type.GetField("attackerObject") ?? throw new MissingFieldException("DotStack.attackerObject");
				Add(delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_0011: Expected O, but got Unknown
					SkillCatalog.SetSkillDefs += new hook_SetSkillDefs(SkillDefs);
				}, delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_0011: Expected O, but got Unknown
					SkillCatalog.SetSkillDefs -= new hook_SetSkillDefs(SkillDefs);
				});
				Add(delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_0011: Expected O, but got Unknown
					ProjectileCatalog.SetProjectilePrefabs += new hook_SetProjectilePrefabs(Projectiles);
				}, delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_0011: Expected O, but got Unknown
					ProjectileCatalog.SetProjectilePrefabs -= new hook_SetProjectilePrefabs(Projectiles);
				});
				Add(delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<0>__BlightDuration;
					if (obj == null)
					{
						hook_InflictDot_refInflictDotInfo val = BlightDuration;
						<>O.<0>__BlightDuration = val;
						obj = (object)val;
					}
					DotController.InflictDot_refInflictDotInfo += (hook_InflictDot_refInflictDotInfo)obj;
				}, delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<0>__BlightDuration;
					if (obj == null)
					{
						hook_InflictDot_refInflictDotInfo val = BlightDuration;
						<>O.<0>__BlightDuration = val;
						obj = (object)val;
					}
					DotController.InflictDot_refInflictDotInfo -= (hook_InflictDot_refInflictDotInfo)obj;
				});
				Add(delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_0011: Expected O, but got Unknown
					DotController.EvaluateDotStacksForType += new hook_EvaluateDotStacksForType(BlightTick);
				}, delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_0011: Expected O, but got Unknown
					DotController.EvaluateDotStacksForType -= new hook_EvaluateDotStacksForType(BlightTick);
				});
				Add(delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<1>__BlightDamage;
					if (obj == null)
					{
						hook_TakeDamage val = BlightDamage;
						<>O.<1>__BlightDamage = val;
						obj = (object)val;
					}
					HealthComponent.TakeDamage += (hook_TakeDamage)obj;
				}, delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<1>__BlightDamage;
					if (obj == null)
					{
						hook_TakeDamage val = BlightDamage;
						<>O.<1>__BlightDamage = val;
						obj = (object)val;
					}
					HealthComponent.TakeDamage -= (hook_TakeDamage)obj;
				});
				Add(delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_0011: Expected O, but got Unknown
					Spawn.OnEnter += new hook_OnEnter(ProtectSpawn);
				}, delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_0011: Expected O, but got Unknown
					Spawn.OnEnter -= new hook_OnEnter(ProtectSpawn);
				});
				Add(delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_0011: Expected O, but got Unknown
					Spawn.OnExit += new hook_OnExit(EndSpawnProtection);
				}, delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_0011: Expected O, but got Unknown
					Spawn.OnExit -= new hook_OnExit(EndSpawnProtection);
				});
				Add(delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<2>__FrenziedLeapDamageType;
					if (obj == null)
					{
						hook_GetBlastDamageType val = FrenziedLeapDamageType;
						<>O.<2>__FrenziedLeapDamageType = val;
						obj = (object)val;
					}
					ChainableLeap.GetBlastDamageType += (hook_GetBlastDamageType)obj;
				}, delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<2>__FrenziedLeapDamageType;
					if (obj == null)
					{
						hook_GetBlastDamageType val = FrenziedLeapDamageType;
						<>O.<2>__FrenziedLeapDamageType = val;
						obj = (object)val;
					}
					ChainableLeap.GetBlastDamageType -= (hook_GetBlastDamageType)obj;
				});
				Add(delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<3>__BreathProjectile;
					if (obj == null)
					{
						hook_FireProjectile val = BreathProjectile;
						<>O.<3>__BreathProjectile = val;
						obj = (object)val;
					}
					Breath.FireProjectile += (hook_FireProjectile)obj;
				}, delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<3>__BreathProjectile;
					if (obj == null)
					{
						hook_FireProjectile val = BreathProjectile;
						<>O.<3>__BreathProjectile = val;
						obj = (object)val;
					}
					Breath.FireProjectile -= (hook_FireProjectile)obj;
				});
				Add(delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<4>__CrocoDamageType;
					if (obj == null)
					{
						hook_GetDamageType val = CrocoDamageType;
						<>O.<4>__CrocoDamageType = val;
						obj = (object)val;
					}
					CrocoDamageTypeController.GetDamageType += (hook_GetDamageType)obj;
				}, delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<4>__CrocoDamageType;
					if (obj == null)
					{
						hook_GetDamageType val = CrocoDamageType;
						<>O.<4>__CrocoDamageType = val;
						obj = (object)val;
					}
					CrocoDamageTypeController.GetDamageType -= (hook_GetDamageType)obj;
				});
				Add(delegate
				{
					GlobalEventManager.onServerDamageDealt += DamageDealt;
				}, delegate
				{
					GlobalEventManager.onServerDamageDealt -= DamageDealt;
				});
				Add(delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<5>__Description;
					if (obj == null)
					{
						hook_GetLocalizedStringByToken val = Description;
						<>O.<5>__Description = val;
						obj = (object)val;
					}
					Language.GetLocalizedStringByToken += (hook_GetLocalizedStringByToken)obj;
				}, delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<5>__Description;
					if (obj == null)
					{
						hook_GetLocalizedStringByToken val = Description;
						<>O.<5>__Description = val;
						obj = (object)val;
					}
					Language.GetLocalizedStringByToken -= (hook_GetLocalizedStringByToken)obj;
				});
				log.LogInfo((object)"Acrid changes ENABLED: spawn protection, non-Poisonous Vicious Wounds finisher, 8s Blight with 0.1 proc per stack/capped 1.0 per tick, Neurotoxin cooldown 2.5s, one-charge Poisonous Frenzied Leap, and Cloying Breath Poison every tick or Blight on ticks 1/5/9 with no bonus roll.");
			}
			catch (Exception error)
			{
				Fail(error);
			}
		}

		private void Add(Action install, Action remove)
		{
			install();
			cleanup.Add(remove);
		}

		private void Fail(Exception error)
		{
			Dispose();
			log.LogError((object)$"Acrid setup failed; restored its values and removed its hooks. {error}");
		}

		public void Dispose()
		{
			if (NetworkServer.active)
			{
				foreach (CharacterBody value in protectedSpawns.Values)
				{
					if (Object.op_Implicit((Object)(object)value))
					{
						value.RemoveBuff(Buffs.HiddenInvincibility);
					}
				}
			}
			protectedSpawns.Clear();
			if ((Object)(object)neurotoxin != (Object)null)
			{
				neurotoxin.baseRechargeInterval = originalNeurotoxinCooldown;
			}
			if ((Object)(object)frenziedLeap != (Object)null)
			{
				frenziedLeap.baseMaxStock = originalFrenziedLeapStock;
				frenziedLeap.baseRechargeInterval = originalFrenziedLeapCooldown;
			}
			neurotoxin = null;
			frenziedLeap = null;
			breathProjectilePrefab = null;
			breathProjectileSetupDepth = 0;
			breathTicks = new ConditionalWeakTable<ProjectileController, ConditionalWeakTable<HealthComponent, BreathTickSequence>>();
			for (int num = cleanup.Count - 1; num >= 0; num--)
			{
				try
				{
					cleanup[num]();
				}
				catch (Exception arg)
				{
					log.LogError((object)$"Acrid hook cleanup failed: {arg}");
				}
			}
			cleanup.Clear();
		}

		private void SkillDefs(orig_SetSkillDefs orig, SkillDef[] skillDefs)
		{
			try
			{
				if ((Object)(object)neurotoxin == (Object)null || (Object)(object)frenziedLeap == (Object)null)
				{
					SkillDef val = skillDefs.Single((SkillDef s) => s.skillNameToken == "CROCO_SECONDARY_NAME");
					SkillDef val2 = skillDefs.Single((SkillDef s) => s.skillNameToken == "CROCO_UTILITY_ALT1_NAME");
					originalNeurotoxinCooldown = val.baseRechargeInterval;
					originalFrenziedLeapStock = val2.baseMaxStock;
					originalFrenziedLeapCooldown = val2.baseRechargeInterval;
					neurotoxin = val;
					frenziedLeap = val2;
					val.baseRechargeInterval = 2.5f;
					val2.baseMaxStock = 1;
					val2.baseRechargeInterval = 8f;
				}
			}
			catch (Exception error)
			{
				Fail(error);
			}
			orig.Invoke(skillDefs);
		}

		private void Projectiles(orig_SetProjectilePrefabs orig, GameObject[] prefabs)
		{
			try
			{
				if (!Object.op_Implicit((Object)(object)breathProjectilePrefab))
				{
					GameObject val = prefabs.Single((GameObject p) => ((Object)p).name == "CrocoBreathProjectile");
					if (!Object.op_Implicit((Object)(object)val.GetComponent<ProjectileController>()) || !Object.op_Implicit((Object)(object)val.GetComponent<ProjectileDotZone>()))
					{
						throw new InvalidOperationException("Cloying Breath's projectile layout changed.");
					}
					breathProjectilePrefab = val;
				}
			}
			catch (Exception error)
			{
				Fail(error);
			}
			orig.Invoke(prefabs);
		}

		private static void BlightDuration(orig_InflictDot_refInflictDotInfo orig, ref InflictDotInfo info)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			if ((int)info.dotIndex == 5)
			{
				info.duration = 8f;
			}
			orig.Invoke(ref info);
		}

		private void BlightTick(orig_EvaluateDotStacksForType orig, DotController self, DotIndex index, float deltaTime, out int remainingActive)
		{
			//IL_000d: 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_0009: Invalid comparison between Unknown and I4
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Invalid comparison between Unknown and I4
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active || (int)index != 5)
			{
				orig.Invoke(self, index, deltaTime, ref remainingActive);
				return;
			}
			IEnumerable obj = (IEnumerable)dotStacksField.GetValue(self);
			BlightTickContext blightTickContext = new BlightTickContext(((Component)self).gameObject);
			foreach (object item in obj)
			{
				if ((int)(DotIndex)stackIndexField.GetValue(item) == 5)
				{
					GameObject val = (GameObject)stackAttackerField.GetValue(item);
					if (Object.op_Implicit((Object)(object)val))
					{
						blightTickContext.budget.AddStack(val);
					}
					else
					{
						blightTickContext.budget.AddUnattributedStack();
					}
				}
			}
			BlightTickContext blightTickContext2 = activeBlightTick;
			activeBlightTick = blightTickContext;
			try
			{
				orig.Invoke(self, index, deltaTime, ref remainingActive);
			}
			finally
			{
				activeBlightTick = blightTickContext2;
			}
		}

		private static void BlightDamage(orig_TakeDamage orig, HealthComponent self, DamageInfo info)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Invalid comparison between Unknown and I4
			BlightTickContext blightTickContext = activeBlightTick;
			int num;
			if (NetworkServer.active && blightTickContext != null && (int)info.dotIndex == 5)
			{
				num = (((Object)(object)info.inflictor == (Object)(object)blightTickContext.controllerObject) ? 1 : 0);
				if (num != 0 && Object.op_Implicit((Object)(object)info.attacker))
				{
					info.procCoefficient = blightTickContext.budget.TakeProc(info.attacker);
				}
			}
			else
			{
				num = 0;
			}
			orig.Invoke(self, info);
			if (num != 0 && !info.rejected && Object.op_Implicit((Object)(object)info.attacker) && info.procCoefficient > 0f && Object.op_Implicit((Object)(object)GlobalEventManager.instance))
			{
				GlobalEventManager.instance.OnHitEnemy(info, ((Component)self).gameObject);
				GlobalEventManager.instance.OnHitAll(info, ((Component)self).gameObject);
			}
		}

		private void ProtectSpawn(orig_OnEnter orig, Spawn self)
		{
			orig.Invoke(self);
			CharacterBody val = (Object.op_Implicit((Object)(object)((EntityState)self).outer) ? ((Component)((EntityState)self).outer).GetComponent<CharacterBody>() : null);
			if (NetworkServer.active && Object.op_Implicit((Object)(object)val) && !protectedSpawns.ContainsKey(self))
			{
				val.AddBuff(Buffs.HiddenInvincibility);
				protectedSpawns.Add(self, val);
			}
		}

		private void EndSpawnProtection(orig_OnExit orig, Spawn self)
		{
			if (protectedSpawns.TryGetValue(self, out CharacterBody value))
			{
				protectedSpawns.Remove(self);
				if (NetworkServer.active && Object.op_Implicit((Object)(object)value))
				{
					value.RemoveBuff(Buffs.HiddenInvincibility);
					if (Object.op_Implicit((Object)(object)value.healthComponent) && value.healthComponent.alive)
					{
						value.AddTimedBuff(Buffs.HiddenInvincibility, 2f);
					}
				}
			}
			orig.Invoke(self);
		}

		private static DamageTypeCombo FrenziedLeapDamageType(orig_GetBlastDamageType orig, ChainableLeap self)
		{
			//IL_0002: 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_0029: 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_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_0028: Unknown result type (might be due to invalid IL or missing references)
			DamageTypeCombo val = orig.Invoke(self);
			CrocoDamageTypeController component = ((Component)((EntityState)self).outer).GetComponent<CrocoDamageTypeController>();
			if (Object.op_Implicit((Object)(object)component))
			{
				val |= component.GetDamageType();
			}
			return val;
		}

		private static void BreathProjectile(orig_FireProjectile orig, Breath self)
		{
			breathProjectileSetupDepth++;
			try
			{
				orig.Invoke(self);
			}
			finally
			{
				breathProjectileSetupDepth--;
			}
		}

		private static DamageTypeCombo CrocoDamageType(orig_GetDamageType orig, CrocoDamageTypeController self)
		{
			//IL_0011: 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)
			if (breathProjectileSetupDepth <= 0)
			{
				return orig.Invoke(self);
			}
			return DamageTypeCombo.op_Implicit((DamageType)0);
		}

		private void DamageDealt(DamageReport report)
		{
			//IL_0130: 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)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active || !Object.op_Implicit((Object)(object)breathProjectilePrefab) || report.damageDealt <= 0f || report.damageInfo.rejected || !Object.op_Implicit((Object)(object)report.victimBody) || !Object.op_Implicit((Object)(object)report.attacker))
			{
				return;
			}
			ProjectileController val = (Object.op_Implicit((Object)(object)report.damageInfo.inflictor) ? report.damageInfo.inflictor.GetComponent<ProjectileController>() : null);
			GameObject val2 = breathProjectilePrefab;
			if (val == null || !Object.op_Implicit((Object)(object)val) || (Object)(object)ProjectileCatalog.GetProjectilePrefab(val.catalogIndex) != (Object)(object)val2)
			{
				return;
			}
			CrocoDamageTypeController component = report.attacker.GetComponent<CrocoDamageTypeController>();
			if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.passiveSkillSlot))
			{
				bool flag = (Object)(object)component.passiveSkillSlot.skillDef == (Object)(object)component.blightSkillDef;
				if (!flag || breathTicks.GetValue(val, (ProjectileController _) => new ConditionalWeakTable<HealthComponent, BreathTickSequence>()).GetValue(report.victim, (HealthComponent _) => new BreathTickSequence()).NextAppliesBlight())
				{
					InflictDotInfo val3 = new InflictDotInfo
					{
						victimObject = ((Component)report.victimBody).gameObject,
						attackerObject = report.attacker,
						dotIndex = (DotIndex)(flag ? 5 : 4),
						duration = (flag ? 8f : 10f),
						damageMultiplier = 1f
					};
					DotController.InflictDot(ref val3);
				}
			}
		}

		private static string Description(orig_GetLocalizedStringByToken orig, Language self, string token)
		{
			return AcridBalance.GetDescription(token) ?? orig.Invoke(self, token);
		}
	}
	internal sealed class AfterDamageQueue<T>
	{
		private readonly Queue<T> pending = new Queue<T>();

		private int depth;

		private bool draining;

		internal void Enter()
		{
			depth++;
		}

		internal void Enqueue(T hit)
		{
			pending.Enqueue(hit);
		}

		internal void Clear()
		{
			pending.Clear();
		}

		internal void Exit(Action<T> apply)
		{
			if (--depth != 0 || draining)
			{
				return;
			}
			draining = true;
			try
			{
				while (pending.Count > 0)
				{
					apply(pending.Dequeue());
				}
			}
			finally
			{
				draining = false;
			}
		}
	}
	internal static class ArtificerBalance
	{
		internal const float BaseAcceleration = 60f;

		internal const float PlasmaDamage = 3.1f;

		internal const float SnapfreezeDamage = 3f;

		internal const float SlowDuration = 2f;

		internal const float LaunchSpeed = 7f;

		internal const float FlameRange = 30f;

		internal const float FlameLengthScale = 1.5f;

		internal static void PatchWallDamage(MethodBody body)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			Instruction[] array = ((IEnumerable<Instruction>)body.Instructions).Where(delegate(Instruction i)
			{
				//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)
				if (i.OpCode == OpCodes.Ldsfld)
				{
					object operand = i.Operand;
					FieldReference val = (FieldReference)((operand is FieldReference) ? operand : null);
					if (val != null && ((MemberReference)((MemberReference)val).DeclaringType).FullName == "EntityStates.Mage.Weapon.PrepWall")
					{
						return ((MemberReference)val).Name == "damageCoefficient";
					}
				}
				return false;
			}).ToArray();
			if (array.Length != 2)
			{
				throw new InvalidOperationException("Snapfreeze's two wall damage reads changed.");
			}
			Instruction[] array2 = array;
			foreach (Instruction obj in array2)
			{
				obj.OpCode = OpCodes.Ldc_R4;
				obj.Operand = 3f;
			}
		}

		internal static float CappedLaunchSpeed(float moveSpeed)
		{
			return Math.Max(0f, Math.Min(14f, moveSpeed));
		}

		internal static float TectonicPushMultiplier(float aimY)
		{
			double num = (1.0 - (double)Math.Max(-1f, Math.Min(1f, aimY))) / 2.0;
			return (float)(1.1571428571428573 * (1.0 - Math.Pow(20.25, 0.0 - num)));
		}

		internal static float FrozenExecuteFraction(string bodyName)
		{
			switch (bodyName)
			{
			case "BrotherBody":
			case "BrotherHurtBody":
			case "FalseSonBossBody":
			case "FalseSonBossBodyLunarShard":
			case "FalseSonBossBodyBrokenLunarShard":
				return 0.1f;
			default:
				return 0.3f;
			}
		}

		internal static Instruction TectonicPushSite(MethodBody body)
		{
			Instruction[] array = ((IEnumerable<Instruction>)body.Instructions).Where(delegate(Instruction i)
			{
				//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)
				if (i.OpCode == OpCodes.Ldsfld)
				{
					object operand2 = i.Operand;
					FieldReference val2 = (FieldReference)((operand2 is FieldReference) ? operand2 : null);
					if (val2 != null && ((MemberReference)((MemberReference)val2).DeclaringType).FullName == "EntityStates.Mage.Weapon.FireEarthShards")
					{
						return ((MemberReference)val2).Name == "selfKnockbackSpeed";
					}
				}
				return false;
			}).ToArray();
			if (array.Length == 1)
			{
				object operand = array[0].Next.Operand;
				MethodReference val = (MethodReference)((operand is MethodReference) ? operand : null);
				if (val != null && !(((MemberReference)val).Name != "op_Multiply"))
				{
					return array[0];
				}
			}
			throw new InvalidOperationException("Tectonic Blast self-knockback layout changed.");
		}

		internal static Instruction[] FrozenExecuteSites(MethodBody body, bool healthBar)
		{
			Instruction[] array = body.Instructions.ToArray();
			int num = Array.FindIndex(array, delegate(Instruction i)
			{
				object operand = i.Operand;
				MethodReference val = (MethodReference)((operand is MethodReference) ? operand : null);
				return val != null && ((MemberReference)val).Name == "get_isInFrozenState";
			});
			int num2 = Array.FindIndex(array, Math.Max(0, num), delegate(Instruction i)
			{
				object operand = i.Operand;
				FieldReference val = (FieldReference)((operand is FieldReference) ? operand : null);
				return val != null && ((!healthBar) ? (((MemberReference)((MemberReference)val).DeclaringType).FullName == "EntityStates.FrozenState" && ((MemberReference)val).Name == "executeEffectPrefab") : (((MemberReference)val).Name == "cullFraction"));
			});
			if (num < 0 || num2 <= num)
			{
				throw new InvalidOperationException("Frozen execution block was not found.");
			}
			Instruction[] array2 = (from i in array.Skip(num).Take(num2 - num)
				where i.OpCode == OpCodes.Ldc_R4 && (float)i.Operand == 0.3f
				select i).ToArray();
			if (array2.Length != (healthBar ? 1 : 2))
			{
				throw new InvalidOperationException("Frozen execution threshold layout changed.");
			}
			return array2;
		}

		internal static string? GetDescription(string token)
		{
			return token switch
			{
				"MAGE_PRIMARY_LIGHTNING_DESCRIPTION" => "<style=cIsUtility>Rapid</style>. Fire a bolt for <style=cIsDamage><color=#C586FF><b>310%</b></color> damage</style> that <style=cIsDamage>explodes</style> in a small area. Hold up to 4. <color=#C586FF><b>Direct and splash hits slow enemies by 30% for 2 seconds.</b></color>", 
				"MAGE_UTILITY_ICE_DESCRIPTION" => "<style=cIsUtility>Freezing</style>. Create a barrier that hurts enemies for <style=cIsDamage><color=#C586FF><b>300%</b></color> damage</style>. <color=#C586FF><b>Special slot.</b></color>", 
				"MAGE_SPECIAL_LIGHTNING_DESCRIPTION" => "<style=cIsDamage>Stunning</style>. Burst into the sky, dealing <style=cIsDamage>800% damage</style>. <color=#C586FF><b>Utility slot. Launch distance scales with movement speed, capped at twice the vanilla base distance.</b></color>", 
				"MAGE_SPECIAL_FIRE_DESCRIPTION" => "<style=cIsDamage>Ignite</style>. Burn all enemies in front of you for <style=cIsDamage>2000% damage</style>. <color=#C586FF><b>Reaches 30 meters; hand effects extend forward by 50%.</b></color>", 
				"MAGE_UTILITY_ALT_DESCRIPTION" => "Fire a spread of shards that deal <style=cIsDamage>8x100% damage</style> and <style=cIsUtility>oil</style> enemies. <color=#C586FF><b>Aiming downward provides more aerial knockback.</b></color>", 
				"MAGE_SECONDARY_ICE_DESCRIPTION" => "<style=cIsUtility>Freezing</style>. Charge up a <style=cIsDamage>piercing</style> nano-spear that deals <style=cIsDamage>400%-1200%</style> damage. <color=#C586FF><b>Frozen Mithrix and False Son bosses execute below 10% health; other enemies retain the 30% threshold.</b></color>", 
				"KEYWORD_FREEZING" => "<style=cKeywordName>Freezing</style><style=cSub>Freeze enemies in place. Frozen enemies are <style=cIsHealth>instantly killed</style> if below <style=cIsHealth>30%</style> health.</style> <color=#C586FF><b>Frozen Mithrix and False Son bosses execute below 10% health; other enemies retain the 30% threshold.</b></color>", 
				_ => null, 
			};
		}

		internal static void PatchWallInput(MethodBody body)
		{
			ReplaceField(body, "RoR2.InputBankTest", "skill3", "skill4");
		}

		internal static void PatchWallRefund(MethodBody body)
		{
			ReplaceField(body, "RoR2.SkillLocator", "utility", "special");
		}

		private static void ReplaceField(MethodBody body, string type, string from, string to)
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Expected O, but got Unknown
			Instruction[] array = ((IEnumerable<Instruction>)body.Instructions).Where(delegate(Instruction i)
			{
				object operand = i.Operand;
				FieldReference val2 = (FieldReference)((operand is FieldReference) ? operand : null);
				return val2 != null && ((MemberReference)((MemberReference)val2).DeclaringType).FullName == type && ((MemberReference)val2).Name == from;
			}).ToArray();
			if (array.Length != 1)
			{
				throw new InvalidOperationException($"Expected one {type}.{from}, found {array.Length}.");
			}
			FieldReference val = (FieldReference)array[0].Operand;
			array[0].Operand = (object)new FieldReference(to, val.FieldType, ((MemberReference)val).DeclaringType);
		}

		internal static Instruction LaunchSpeedSite(MethodBody body)
		{
			//IL_003e: 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)
			Instruction[] array = ((IEnumerable<Instruction>)body.Instructions).Where(delegate(Instruction i)
			{
				//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)
				if (i.OpCode == OpCodes.Ldfld)
				{
					object operand = i.Operand;
					FieldReference val = (FieldReference)((operand is FieldReference) ? operand : null);
					if (val != null)
					{
						return ((MemberReference)val).Name == "moveSpeedStat";
					}
				}
				return false;
			}).ToArray();
			if (array.Length != 1 || array[0].Previous.OpCode != OpCodes.Ldarg_0)
			{
				throw new InvalidOperationException("Ion Surge movement layout changed.");
			}
			return array[0];
		}

		internal static void PatchLaunchSource(MethodBody body)
		{
			//IL_003e: 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_0062: Unknown result type (might be due to invalid IL or missing references)
			Instruction[] array = ((IEnumerable<Instruction>)body.Instructions).Where(delegate(Instruction i)
			{
				//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)
				if (i.OpCode == OpCodes.Stfld)
				{
					object operand = i.Operand;
					FieldReference val = (FieldReference)((operand is FieldReference) ? operand : null);
					if (val != null)
					{
						return ((MemberReference)val).FullName == "RoR2.DamageSource RoR2.DamageTypeCombo::damageSource";
					}
				}
				return false;
			}).ToArray();
			if (array.Length != 1 || array[0].Previous.OpCode != OpCodes.Ldc_I4_8)
			{
				throw new InvalidOperationException("Ion Surge damage source layout changed.");
			}
			array[0].Previous.OpCode = OpCodes.Ldc_I4_4;
		}
	}
	internal sealed class ArtificerChanges : IDisposable
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static Manipulator <0>__TectonicPush;

			public static Manipulator <1>__WallInput;

			public static Manipulator <2>__WallRefund;

			public static Manipulator <3>__LaunchSpeed;

			public static Manipulator <4>__LaunchSource;

			public static Manipulator <5>__FlameVisuals;

			public static hook_OnEnter <6>__FlameEnter;

			public static hook_ModifyProjectileInfo <7>__Plasma;

			public static Action<DamageReport> <8>__Slow;

			public static hook_GetLocalizedStringByToken <9>__Description;

			public static Func<float, float> <10>__CappedLaunchSpeed;

			public static Func<GameObject, GameObject> <11>__ExtendFlame;
		}

		private readonly ManualLogSource log;

		private readonly List<Action> cleanup = new List<Action>();

		private SkillFamily? utility;

		private SkillFamily? special;

		private Variant[]? originalUtility;

		private Variant[]? originalSpecial;

		private ProjectileDamage? wallDamage;

		private DamageTypeCombo originalWallDamageType;

		private CharacterBody? artificerBody;

		private float originalAcceleration;

		internal ArtificerChanges(ManualLogSource log)
		{
			this.log = log;
		}

		internal void Enable()
		{
			try
			{
				Add(delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_0011: Expected O, but got Unknown
					BodyCatalog.SetBodyPrefabs += new hook_SetBodyPrefabs(Bodies);
				}, delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_0011: Expected O, but got Unknown
					BodyCatalog.SetBodyPrefabs -= new hook_SetBodyPrefabs(Bodies);
				});
				Add(delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<0>__TectonicPush;
					if (obj == null)
					{
						Manipulator val = TectonicPush;
						<>O.<0>__TectonicPush = val;
						obj = (object)val;
					}
					FireEarthShards.PlayAttackEffect += (Manipulator)obj;
				}, delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<0>__TectonicPush;
					if (obj == null)
					{
						Manipulator val = TectonicPush;
						<>O.<0>__TectonicPush = val;
						obj = (object)val;
					}
					FireEarthShards.PlayAttackEffect -= (Manipulator)obj;
				});
				cleanup.Add(SharedFreezeChanges.Acquire().Dispose);
				Add(delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<1>__WallInput;
					if (obj == null)
					{
						Manipulator val = WallInput;
						<>O.<1>__WallInput = val;
						obj = (object)val;
					}
					PrepWall.FixedUpdate += (Manipulator)obj;
				}, delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<1>__WallInput;
					if (obj == null)
					{
						Manipulator val = WallInput;
						<>O.<1>__WallInput = val;
						obj = (object)val;
					}
					PrepWall.FixedUpdate -= (Manipulator)obj;
				});
				Add(delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<2>__WallRefund;
					if (obj == null)
					{
						Manipulator val = WallRefund;
						<>O.<2>__WallRefund = val;
						obj = (object)val;
					}
					PrepWall.OnExit += (Manipulator)obj;
				}, delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<2>__WallRefund;
					if (obj == null)
					{
						Manipulator val = WallRefund;
						<>O.<2>__WallRefund = val;
						obj = (object)val;
					}
					PrepWall.OnExit -= (Manipulator)obj;
				});
				Add(delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<3>__LaunchSpeed;
					if (obj == null)
					{
						Manipulator val = LaunchSpeed;
						<>O.<3>__LaunchSpeed = val;
						obj = (object)val;
					}
					FlyUpState.HandleMovements += (Manipulator)obj;
				}, delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<3>__LaunchSpeed;
					if (obj == null)
					{
						Manipulator val = LaunchSpeed;
						<>O.<3>__LaunchSpeed = val;
						obj = (object)val;
					}
					FlyUpState.HandleMovements -= (Manipulator)obj;
				});
				Add(delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<4>__LaunchSource;
					if (obj == null)
					{
						Manipulator val = LaunchSource;
						<>O.<4>__LaunchSource = val;
						obj = (object)val;
					}
					FlyUpState.OnEnter += (Manipulator)obj;
				}, delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<4>__LaunchSource;
					if (obj == null)
					{
						Manipulator val = LaunchSource;
						<>O.<4>__LaunchSource = val;
						obj = (object)val;
					}
					FlyUpState.OnEnter -= (Manipulator)obj;
				});
				Add(delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<5>__FlameVisuals;
					if (obj == null)
					{
						Manipulator val = FlameVisuals;
						<>O.<5>__FlameVisuals = val;
						obj = (object)val;
					}
					Flamethrower.FixedUpdate += (Manipulator)obj;
				}, delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<5>__FlameVisuals;
					if (obj == null)
					{
						Manipulator val = FlameVisuals;
						<>O.<5>__FlameVisuals = val;
						obj = (object)val;
					}
					Flamethrower.FixedUpdate -= (Manipulator)obj;
				});
				Add(delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<6>__FlameEnter;
					if (obj == null)
					{
						hook_OnEnter val = FlameEnter;
						<>O.<6>__FlameEnter = val;
						obj = (object)val;
					}
					Flamethrower.OnEnter += (hook_OnEnter)obj;
				}, delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<6>__FlameEnter;
					if (obj == null)
					{
						hook_OnEnter val = FlameEnter;
						<>O.<6>__FlameEnter = val;
						obj = (object)val;
					}
					Flamethrower.OnEnter -= (hook_OnEnter)obj;
				});
				Add(delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<7>__Plasma;
					if (obj == null)
					{
						hook_ModifyProjectileInfo val = Plasma;
						<>O.<7>__Plasma = val;
						obj = (object)val;
					}
					FireLightningBolt.ModifyProjectileInfo += (hook_ModifyProjectileInfo)obj;
				}, delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<7>__Plasma;
					if (obj == null)
					{
						hook_ModifyProjectileInfo val = Plasma;
						<>O.<7>__Plasma = val;
						obj = (object)val;
					}
					FireLightningBolt.ModifyProjectileInfo -= (hook_ModifyProjectileInfo)obj;
				});
				Add(delegate
				{
					GlobalEventManager.onServerDamageDealt += Slow;
				}, delegate
				{
					GlobalEventManager.onServerDamageDealt -= Slow;
				});
				Add(delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_0011: Expected O, but got Unknown
					SkillCatalog.SetSkillFamilies += new hook_SetSkillFamilies(SwapSkills);
				}, delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_0011: Expected O, but got Unknown
					SkillCatalog.SetSkillFamilies -= new hook_SetSkillFamilies(SwapSkills);
				});
				Add(delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_0011: Expected O, but got Unknown
					ProjectileCatalog.SetProjectilePrefabs += new hook_SetProjectilePrefabs(WallDamageSource);
				}, delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_0011: Expected O, but got Unknown
					ProjectileCatalog.SetProjectilePrefabs -= new hook_SetProjectilePrefabs(WallDamageSource);
				});
				Add(delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<9>__Description;
					if (obj == null)
					{
						hook_GetLocalizedStringByToken val = Description;
						<>O.<9>__Description = val;
						obj = (object)val;
					}
					Language.GetLocalizedStringByToken += (hook_GetLocalizedStringByToken)obj;
				}, delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<9>__Description;
					if (obj == null)
					{
						hook_GetLocalizedStringByToken val = Description;
						<>O.<9>__Description = val;
						obj = (object)val;
					}
					Language.GetLocalizedStringByToken -= (hook_GetLocalizedStringByToken)obj;
				});
				log.LogInfo((object)"Artificer changes ENABLED: acceleration 60; Plasma Bolt 310%/30% slow for 2s, Snapfreeze Special/300% damage, Ion Surge Utility/move-speed scaling capped at 2x base distance, Flamethrower 30m, aim-scaled Tectonic Blast push, Mithrix/False Son boss freeze execution 10%.");
			}
			catch (Exception arg)
			{
				Dispose();
				log.LogError((object)$"Could not enable the full Artificer patch; removed its hooks. {arg}");
			}
		}

		private void Add(Action install, Action remove)
		{
			cleanup.Add(remove);
			install();
		}

		public void Dispose()
		{
			//IL_0088: 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)
			if (Object.op_Implicit((Object)(object)artificerBody))
			{
				artificerBody.baseAcceleration = originalAcceleration;
			}
			artificerBody = null;
			if ((Object)(object)utility != (Object)null && originalUtility != null)
			{
				utility.variants = originalUtility;
			}
			if ((Object)(object)special != (Object)null && originalSpecial != null)
			{
				special.variants = originalSpecial;
			}
			if ((Object)(object)wallDamage != (Object)null)
			{
				wallDamage.damageType = originalWallDamageType;
			}
			wallDamage = null;
			originalUtility = (originalSpecial = null);
			for (int num = cleanup.Count - 1; num >= 0; num--)
			{
				try
				{
					cleanup[num]();
				}
				catch (Exception ex)
				{
					log.LogError((object)ex);
				}
			}
			cleanup.Clear();
		}

		private static void WallInput(ILContext il)
		{
			ArtificerBalance.PatchWallInput(il.Body);
		}

		private static void WallRefund(ILContext il)
		{
			ArtificerBalance.PatchWallRefund(il.Body);
			ArtificerBalance.PatchWallDamage(il.Body);
		}

		private static void LaunchSpeed(ILContext il)
		{
			//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)
			ILCursor val = new ILCursor(il);
			val.Goto(ArtificerBalance.LaunchSpeedSite(il.Body), (MoveType)2, false);
			val.EmitDelegate<Func<float, float>>((Func<float, float>)ArtificerBalance.CappedLaunchSpeed);
		}

		private static void LaunchSource(ILContext il)
		{
			ArtificerBalance.PatchLaunchSource(il.Body);
		}

		private static void TectonicPush(ILContext il)
		{
			//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_0073: 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_007f: 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)
			FieldReference val = ((IEnumerable<Instruction>)il.Body.Instructions).Select((Instruction i) => i.Operand).OfType<FieldReference>().First((FieldReference f) => ((MemberReference)((MemberReference)f).DeclaringType).FullName == "EntityStates.Mage.Weapon.FireEarthShards" && ((MemberReference)f).Name == "aimVector");
			ILCursor val2 = new ILCursor(il);
			val2.Goto(ArtificerBalance.TectonicPushSite(il.Body), (MoveType)2, false);
			val2.Emit(OpCodes.Ldarg_0);
			val2.Emit(OpCodes.Ldfld, val);
			val2.EmitDelegate<Func<float, Vector3, float>>((Func<float, Vector3, float>)((float speed, Vector3 direction) => speed * ArtificerBalance.TectonicPushMultiplier(direction.y)));
		}

		private void Bodies(orig_SetBodyPrefabs orig, GameObject[] prefabs)
		{
			try
			{
				if (!Object.op_Implicit((Object)(object)artificerBody))
				{
					CharacterBody component = prefabs.Single((GameObject p) => ((Object)p).name == "MageBody").GetComponent<CharacterBody>();
					if (!Object.op_Implicit((Object)(object)component))
					{
						throw new InvalidOperationException("Artificer's body prefab was not found.");
					}
					originalAcceleration = component.baseAcceleration;
					artificerBody = component;
					component.baseAcceleration = 60f;
				}
			}
			catch (Exception arg)
			{
				Dispose();
				log.LogError((object)$"Artificer stat patch failed; disabled Artificer changes. {arg}");
			}
			orig.Invoke(prefabs);
		}

		private void SwapSkills(orig_SetSkillFamilies orig, SkillFamily[] families)
		{
			//IL_00ee: 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_0102: 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)
			try
			{
				if (originalUtility == null)
				{
					SkillFamily val = families.Single((SkillFamily f) => ((Object)f).name == "MageBodyUtilityFamily");
					SkillFamily val2 = families.Single((SkillFamily f) => ((Object)f).name == "MageBodySpecialFamily");
					int num = Array.FindIndex(val.variants, (Variant v) => v.skillDef.skillNameToken == "MAGE_UTILITY_ICE_NAME");
					int num2 = Array.FindIndex(val2.variants, (Variant v) => v.skillDef.skillNameToken == "MAGE_SPECIAL_LIGHTNING_NAME");
					if (num < 0 || num2 < 0)
					{
						throw new InvalidOperationException("Artificer's original skill variants were not found.");
					}
					Variant[] array = (Variant[])val.variants.Clone();
					Variant[] array2 = (Variant[])val2.variants.Clone();
					array[num] = val2.variants[num2];
					array2[num2] = val.variants[num];
					utility = val;
					special = val2;
					originalUtility = val.variants;
					originalSpecial = val2.variants;
					val.variants = array;
					val2.variants = array2;
					log.LogInfo((object)"Artificer skill slots swapped; other variants and unlock requirements preserved.");
				}
			}
			catch (Exception arg)
			{
				Dispose();
				log.LogError((object)$"Artificer skill swap failed; disabled Artificer changes. {arg}");
			}
			orig.Invoke(families);
		}

		private void WallDamageSource(orig_SetProjectilePrefabs orig, GameObject[] prefabs)
		{
			//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_0066: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)wallDamage == (Object)null)
				{
					ProjectileDamage component = prefabs.Single((GameObject p) => ((Object)p).name == "MageIcewallPillarProjectile").GetComponent<ProjectileDamage>();
					if (!Object.op_Implicit((Object)(object)component))
					{
						throw new InvalidOperationException("Snapfreeze projectile damage was not found.");
					}
					originalWallDamageType = component.damageType;
					wallDamage = component;
					component.damageType.damageSource = (DamageSource)8;
				}
			}
			catch (Exception arg)
			{
				Dispose();
				log.LogError((object)$"Artificer projectile patch failed; disabled Artificer changes. {arg}");
			}
			orig.Invoke(prefabs);
		}

		private static void Plasma(orig_ModifyProjectileInfo orig, FireLightningBolt self, ref FireProjectileInfo info)
		{
			orig.Invoke(self, ref info);
			CharacterBody component = ((Component)((EntityState)self).outer).GetComponent<CharacterBody>();
			if (Object.op_Implicit((Object)(object)component))
			{
				info.damage = component.damage * 3.1f;
			}
		}

		private static void Slow(DamageReport report)
		{
			if (!NetworkServer.active || !Object.op_Implicit((Object)(object)report.victimBody) || report.damageInfo.rejected || !Object.op_Implicit((Object)(object)report.damageInfo.inflictor))
			{
				return;
			}
			ProjectileController component = report.damageInfo.inflictor.GetComponent<ProjectileController>();
			if (Object.op_Implicit((Object)(object)component) && component.catalogIndex >= 0)
			{
				GameObject projectilePrefab = ProjectileCatalog.GetProjectilePrefab(component.catalogIndex);
				if (Object.op_Implicit((Object)(object)projectilePrefab) && ((Object)projectilePrefab).name == "MageLightningboltBasic")
				{
					report.victimBody.AddTimedBuff(Buffs.Slow30, 2f);
				}
			}
		}

		private static void FlameEnter(orig_OnEnter orig, Flamethrower self)
		{
			self.maxDistance = 30f;
			orig.Invoke(self);
		}

		private static void FlameVisuals(ILContext il)
		{
			//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)
			Instruction[] array = ((IEnumerable<Instruction>)il.Body.Instructions).Where(delegate(Instruction i)
			{
				//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)
				if (i.OpCode == OpCodes.Stfld)
				{
					object operand = i.Operand;
					FieldReference val3 = (FieldReference)((operand is FieldReference) ? operand : null);
					if (val3 != null)
					{
						if (!(((MemberReference)val3).Name == "leftFlamethrowerEffectInstance"))
						{
							return ((MemberReference)val3).Name == "rightFlamethrowerEffectInstance";
						}
						return true;
					}
				}
				return false;
			}).ToArray();
			if (array.Length != 2 || array.Any(delegate(Instruction i)
			{
				object operand = i.Previous.Operand;
				MethodReference val3 = (MethodReference)((operand is MethodReference) ? operand : null);
				return val3 == null || ((MemberReference)val3).Name != "Instantiate";
			}))
			{
				throw new InvalidOperationException("Flamethrower effect creation layout changed.");
			}
			Instruction[] array2 = array;
			foreach (Instruction val in array2)
			{
				ILCursor val2 = new ILCursor(il);
				val2.Goto(val, (MoveType)0, false);
				val2.EmitDelegate<Func<GameObject, GameObject>>((Func<GameObject, GameObject>)ExtendFlame);
			}
		}

		private static GameObject ExtendFlame(GameObject effect)
		{
			//IL_0010: 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_002c: 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)
			if (!Object.op_Implicit((Object)(object)effect))
			{
				return effect;
			}
			Vector3 localScale = effect.transform.localScale;
			localScale.z *= 1.5f;
			effect.transform.localScale = localScale;
			ParticleSystem[] componentsInChildren = effect.GetComponentsInChildren<ParticleSystem>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				MainModule main = componentsInChildren[i].main;
				((MainModule)(ref main)).scalingMode = (ParticleSystemScalingMode)0;
			}
			return effect;
		}

		private static string Description(orig_GetLocalizedStringByToken orig, Language self, string token)
		{
			return ArtificerBalance.GetDescription(token) ?? orig.Invoke(self, token);
		}
	}
	internal static class BanditBalance
	{
		internal const int BlastBaseCharges = 6;

		internal const float BlastMinimumBaseInterval = 0.3f;

		internal const float BlastSpreadMultiplier = 0.5f;

		internal const float BlastBloomMultiplier = 0.5f;

		internal const float BlastRadiusMultiplier = 1.2f;

		internal const float StockPipSpacing = 8f;

		internal static float GetStockPipX(int pipIndex, int activeStockCount)
		{
			int num = Math.Max(1, Math.Min(activeStockCount, 6));
			return ((float)pipIndex - (float)(num - 1) * 0.5f) * 8f;
		}

		internal static string? GetDescription(string token)
		{
			if (token == "BANDIT2_PRIMARY_ALT_DESCRIPTION")
			{
				return "Fire a rifle blast for <style=cIsDamage>330% damage</style>. Can hold up to <color=#C586FF><b>6 bullets</b></color>. <color=#C586FF><b>Pierces enemies, stopping at terrain. Shot radius is 20% larger. Spread and bloom are reduced by 50%. Fires at most once every 0.3 seconds, independent of attack speed, reloads and skill interrupts.</b></color>";
			}
			return null;
		}
	}
	internal sealed class BlastShotClock
	{
		private float nextShot = float.NegativeInfinity;

		internal bool CanFire(float now)
		{
			return now >= nextShot;
		}

		internal void RecordShot(float now)
		{
			nextShot = now + 0.3f;
		}
	}
	internal sealed class BanditChanges : IDisposable
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static hook_OnEnter <0>__FireInterval;

			public static hook_ModifyBullet <1>__ReduceSpread;

			public static hook_GetLocalizedStringByToken <2>__Description;
		}

		private readonly ManualLogSource log;

		private readonly List<Action> cleanup = new List<Action>();

		private readonly ConditionalWeakTable<CrosshairController, Transform[]> stockPipLayouts = new ConditionalWeakTable<CrosshairController, Transform[]>();

		private SkillDef? rifleSkill;

		private int originalMaxStock;

		private ConditionalWeakTable<CharacterBody, BlastShotClock> shotClocks = new ConditionalWeakTable<CharacterBody, BlastShotClock>();

		internal BanditChanges(ManualLogSource log)
		{
			this.log = log;
		}

		internal void Enable()
		{
			try
			{
				Add(delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_0011: Expected O, but got Unknown
					SkillCatalog.SetSkillDefs += new hook_SetSkillDefs(SkillDefs);
				}, delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_0011: Expected O, but got Unknown
					SkillCatalog.SetSkillDefs -= new hook_SetSkillDefs(SkillDefs);
				});
				Add(delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<0>__FireInterval;
					if (obj == null)
					{
						hook_OnEnter val = FireInterval;
						<>O.<0>__FireInterval = val;
						obj = (object)val;
					}
					Bandit2FirePrimaryBase.OnEnter += (hook_OnEnter)obj;
				}, delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<0>__FireInterval;
					if (obj == null)
					{
						hook_OnEnter val = FireInterval;
						<>O.<0>__FireInterval = val;
						obj = (object)val;
					}
					Bandit2FirePrimaryBase.OnEnter -= (hook_OnEnter)obj;
				});
				Add(delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_0011: Expected O, but got Unknown
					GenericSkill.CanExecute += new hook_CanExecute(CanFireBlast);
				}, delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_0011: Expected O, but got Unknown
					GenericSkill.CanExecute -= new hook_CanExecute(CanFireBlast);
				});
				Add(delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_0011: Expected O, but got Unknown
					GenericBulletBaseState.FireBullet += new hook_FireBullet(RecordBlastShot);
				}, delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_0011: Expected O, but got Unknown
					GenericBulletBaseState.FireBullet -= new hook_FireBullet(RecordBlastShot);
				});
				Add(delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<1>__ReduceSpread;
					if (obj == null)
					{
						hook_ModifyBullet val = ReduceSpread;
						<>O.<1>__ReduceSpread = val;
						obj = (object)val;
					}
					Bandit2FireRifle.ModifyBullet += (hook_ModifyBullet)obj;
				}, delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<1>__ReduceSpread;
					if (obj == null)
					{
						hook_ModifyBullet val = ReduceSpread;
						<>O.<1>__ReduceSpread = val;
						obj = (object)val;
					}
					Bandit2FireRifle.ModifyBullet -= (hook_ModifyBullet)obj;
				});
				Add(delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_0011: Expected O, but got Unknown
					CrosshairController.Awake += new hook_Awake(ExpandBanditStockDisplay);
				}, delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_0011: Expected O, but got Unknown
					CrosshairController.Awake -= new hook_Awake(ExpandBanditStockDisplay);
				});
				Add(delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_0011: Expected O, but got Unknown
					CrosshairController.LateUpdate += new hook_LateUpdate(CenterBanditStockPips);
				}, delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_0011: Expected O, but got Unknown
					CrosshairController.LateUpdate -= new hook_LateUpdate(CenterBanditStockPips);
				});
				Add(delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<2>__Description;
					if (obj == null)
					{
						hook_GetLocalizedStringByToken val = Description;
						<>O.<2>__Description = val;
						obj = (object)val;
					}
					Language.GetLocalizedStringByToken += (hook_GetLocalizedStringByToken)obj;
				}, delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<2>__Description;
					if (obj == null)
					{
						hook_GetLocalizedStringByToken val = Description;
						<>O.<2>__Description = val;
						obj = (object)val;
					}
					Language.GetLocalizedStringByToken -= (hook_GetLocalizedStringByToken)obj;
				});
				log.LogInfo((object)"Bandit changes ENABLED: Blast has 6 rounds, a 0.3s minimum firing interval, 50% lower spread and bloom, 20% larger shot radius and enemy piercing.");
			}
			catch (Exception arg)
			{
				Dispose();
				log.LogError((object)$"Could not enable the full Bandit patch; removed its hooks. {arg}");
			}
		}

		private void Add(Action install, Action remove)
		{
			cleanup.Add(remove);
			install();
		}

		public void Dispose()
		{
			if ((Object)(object)rifleSkill != (Object)null)
			{
				rifleSkill.baseMaxStock = originalMaxStock;
			}
			rifleSkill = null;
			for (int num = cleanup.Count - 1; num >= 0; num--)
			{
				try
				{
					cleanup[num]();
				}
				catch (Exception ex)
				{
					log.LogError((object)ex);
				}
			}
			cleanup.Clear();
			shotClocks = new ConditionalWeakTable<CharacterBody, BlastShotClock>();
		}

		private void SkillDefs(orig_SetSkillDefs orig, SkillDef[] skillDefs)
		{
			try
			{
				if ((Object)(object)rifleSkill == (Object)null)
				{
					SkillDef val = Array.Find(skillDefs, (SkillDef s) => s.skillNameToken == "BANDIT2_PRIMARY_ALT_NAME");
					if (!Object.op_Implicit((Object)(object)val))
					{
						throw new InvalidOperationException("Bandit Blast's rifle SkillDef was not found.");
					}
					rifleSkill = val;
					originalMaxStock = val.baseMaxStock;
					val.baseMaxStock = 6;
				}
			}
			catch (Exception arg)
			{
				Dispose();
				log.LogError((object)$"Bandit stock patch failed; disabled Bandit changes. {arg}");
			}
			orig.Invoke(skillDefs);
		}

		private static void FireInterval(orig_OnEnter orig, Bandit2FirePrimaryBase self)
		{
			if (((object)self).GetType() == typeof(Bandit2FireRifle))
			{
				((GenericBulletBaseState)self).spreadBloomValue = ((GenericBulletBaseState)self).spreadBloomValue * 0.5f;
			}
			orig.Invoke(self);
		}

		private bool CanFireBlast(orig_CanExecute orig, GenericSkill self)
		{
			CharacterBody characterBody = self.characterBody;
			if ((Object)(object)self.skillDef == (Object)(object)rifleSkill && Object.op_Implicit((Object)(object)characterBody) && shotClocks.TryGetValue(characterBody, out BlastShotClock value) && !value.CanFire(Time.fixedTime))
			{
				return false;
			}
			return orig.Invoke(self);
		}

		private void RecordBlastShot(orig_FireBullet orig, GenericBulletBaseState self, Ray ray)
		{
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			if (((object)self).GetType() == typeof(Bandit2FireRifle) && Object.op_Implicit((Object)(object)((EntityState)self).outer))
			{
				CharacterBody component = ((Component)((EntityState)self).outer).GetComponent<CharacterBody>();
				if (component != null && component.hasEffectiveAuthority)
				{
					CharacterBody component2 = ((Component)((EntityState)self).outer).GetComponent<CharacterBody>();
					if (Object.op_Implicit((Object)(object)component2))
					{
						BlastShotClock value = shotClocks.GetValue(component2, (CharacterBody _) => new BlastShotClock());
						if (!value.CanFire(Time.fixedTime))
						{
							return;
						}
						value.RecordShot(Time.fixedTime);
					}
				}
			}
			orig.Invoke(self, ray);
		}

		private static void ReduceSpread(orig_ModifyBullet orig, Bandit2FireRifle self, BulletAttack attack)
		{
			//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_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)
			orig.Invoke(self, attack);
			attack.spreadPitchScale *= 0.5f;
			attack.spreadYawScale *= 0.5f;
			attack.radius *= 1.2f;
			LayerIndex world = LayerIndex.world;
			attack.stopperMask = ((LayerIndex)(ref world)).mask;
		}

		private void ExpandBanditStockDisplay(orig_Awake orig, CrosshairController self)
		{
			//IL_00e5: 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_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: 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_0132: 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_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: 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_01b9: Unknown result type (might be due to invalid IL or missing references)
			orig.Invoke(self);
			if (!Object.op_Implicit((Object)(object)self) || !((Object)self).name.StartsWith("Bandit2Crosshair", StringComparison.Ordinal))
			{
				return;
			}
			try
			{
				SkillStockSpriteDisplay[] skillStockSpriteDisplays = self.skillStockSpriteDisplays;
				int[] array = new int[4];
				int stock;
				for (stock = 1; stock <= 4; stock++)
				{
					int num = Array.FindIndex(skillStockSpriteDisplays, (SkillStockSpriteDisplay display) => Object.op_Implicit((Object)(object)display.target) && ((Object)display.target).name == $"Stock, {stock}");
					if (num < 0)
					{
						throw new InvalidOperationException($"Reticle stock pip {stock} was not found.");
					}
					array[stock - 1] = num;
				}
				int num2 = Array.FindIndex(skillStockSpriteDisplays, (SkillStockSpriteDisplay display) => Object.op_Implicit((Object)(object)display.target) && ((Object)display.target).name == "Center, Available");
				if (num2 < 0)
				{
					throw new InvalidOperationException("Reticle center marker was not found.");
				}
				int num3 = array[3];
				for (int num4 = 0; num4 < skillStockSpriteDisplays.Length; num4++)
				{
					SkillStockSpriteDisplay val = skillStockSpriteDisplays[num4];
					if (Object.op_Implicit((Object)(object)val.target) && (Array.IndexOf(array, num4) >= 0 || num4 == num2))
					{
						val.maximumStockCountToBeValid = -1;
						skillStockSpriteDisplays[num4] = val;
					}
				}
				SkillStockSpriteDisplay val2 = skillStockSpriteDisplays[num3];
				Transform parent = val2.target.transform.parent;
				Array.Resize(ref self.skillStockSpriteDisplays, skillStockSpriteDisplays.Length + 2);
				for (int num5 = 5; num5 <= 6; num5++)
				{
					GameObject val3 = Object.Instantiate<GameObject>(val2.target, parent, false);
					((Object)val3).name = $"Stock, {num5}";
					val3.SetActive(false);
					SkillStockSpriteDisplay val4 = val2;
					val4.target = val3;
					val4.minimumStockCountToBeValid = num5;
					val4.maximumStockCountToBeValid = -1;
					self.skillStockSpriteDisplays[skillStockSpriteDisplays.Length + num5 - 5] = val4;
				}
				Transform[] array2 = (Transform[])(object)new Transform[6];
				for (int num6 = 0; num6 < array.Length; num6++)
				{
					array2[num6] = skillStockSpriteDisplays[array[num6]].target.transform;
				}
				for (int num7 = 5; num7 <= 6; num7++)
				{
					array2[num7 - 1] = self.skillStockSpriteDisplays[skillStockSpriteDisplays.Length + num7 - 5].target.transform;
				}
				stockPipLayouts.Add(self, array2);
			}
			catch (Exception arg)
			{
				log.LogError((object)$"Could not extend Bandit's Blast reticle to six stock pips. {arg}");
			}
		}

		private void CenterBanditStockPips(orig_LateUpdate orig, CrosshairController self)
		{
			//IL_007f: 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_009a: Unknown result type (might be due to invalid IL or missing references)
			orig.Invoke(self);
			if (!Object.op_Implicit((Object)(object)self) || !stockPipLayouts.TryGetValue(self, out Transform[] value) || !Object.op_Implicit((Object)(object)self.hudElement))
			{
				return;
			}
			CharacterBody targetCharacterBody = self.hudElement.targetCharacterBody;
			if (!Object.op_Implicit((Object)(object)targetCharacterBody))
			{
				return;
			}
			SkillLocator skillLocator = targetCharacterBody.skillLocator;
			if (!Object.op_Implicit((Object)(object)skillLocator))
			{
				return;
			}
			GenericSkill primary = skillLocator.primary;
			if (!Object.op_Implicit((Object)(object)primary))
			{
				return;
			}
			int maxStock = primary.maxStock;
			for (int i = 0; i < value.Length; i++)
			{
				if (Object.op_Implicit((Object)(object)value[i]))
				{
					Vector3 localPosition = value[i].localPosition;
					localPosition.x = BanditBalance.GetStockPipX(i, maxStock);
					value[i].localPosition = localPosition;
				}
			}
		}

		private static string Description(orig_GetLocalizedStringByToken orig, Language self, string token)
		{
			return BanditBalance.GetDescription(token) ?? orig.Invoke(self, token);
		}
	}
	internal static class CaptainBalance
	{
		internal const float HealingBeaconBarrierFraction = 0.2f;

		internal const float TaserSlowDuration = 5f;

		internal static bool IsHealingWardName(string name)
		{
			if (!(name == "CaptainHealingWard"))
			{
				return name == "CaptainHealingWard(Clone)";
			}
			return true;
		}

		internal static float GetBarrierGrant(float currentBarrier, float fullHealth, float healingTick)
		{
			float val = Math.Max(0f, fullHealth * 0.2f - currentBarrier);
			return Math.Min(Math.Max(0f, healingTick), val);
		}

		internal static string? GetDescription(string token)
		{
			return token switch
			{
				"CAPTAIN_SECONDARY_DESCRIPTION" => "<style=cIsDamage>Shocking</style>. Fire a fast tazer that deals <style=cIsDamage>100% damage</style>. Travels farther if bounced. <color=#C586FF><b>Enemies that cannot be shocked are slowed by 50% for 5 seconds instead.</b></color>", 
				"CAPTAIN_SUPPLY_HEAL_DESCRIPTION" => "<style=cIsHealing>Heal</style> all nearby allies for <style=cIsHealing>10%</style> of their <style=cIsHealing>maximum health</style> every second. <color=#C586FF><b>Allies already at full combined health instead gain each healing tick as barrier, up to 20% maximum health. Existing barrier is never removed.</b></color>", 
				"CAPTAIN_UTILITY_DESCRIPTION" => "<style=cIsDamage>Stunning</style>. Request up to <style=cIsDamage>3</style> Orbital Probes from the <style=cIsDamage>UES Safe Travels</style>. Each probe deals <style=cIsDamage>1000% damage</style>. <color=#C586FF><b>Available in hidden realms.</b></color>", 
				"CAPTAIN_UTILITY_ALT1_DESCRIPTION" => "<style=cIsDamage>Stunning</style>. Request a <style=cIsDamage>kinetic strike</style> from the <style=cIsDamage>UES Safe Travels</style>. After <style=cIsUtility>20 seconds</style>, it deals <style=cIsDamage>40,000% damage</style> to ALL characters. <color=#C586FF><b>Available in hidden realms.</b></color>", 
				"CAPTAIN_SPECIAL_DESCRIPTION" => "Request a <style=cIsUtility>permanent</style> Supply Beacon. Can only be requested <style=cIsUtility>twice per stage</style>. <color=#C586FF><b>Available in hidden realms.</b></color>", 
				_ => null, 
			};
		}
	}
	internal sealed class CaptainChanges : IDisposable
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static Action<DamageReport> <0>__TaserSlow;

			public static hook_GetCurrentIcon <1>__OrbitalIcon;

			public static hook_GetCurrentNameToken <2>__OrbitalName;

			public static hook_GetCurrentDescriptionToken <3>__OrbitalDescription;

			public static hook_CanExecute <4>__OrbitalCanExecute;

			public static hook_IsReady <5>__OrbitalIsReady;

			public static hook_HealOccupants <6>__HealingBeacon;

			public static hook_GetLocalizedStringByToken <7>__Description;
		}

		private readonly ManualLogSource log;

		private readonly List<Action> cleanup = new List<Action>();

		internal CaptainChanges(ManualLogSource log)
		{
			this.log = log;
		}

		internal void Enable()
		{
			try
			{
				Add(delegate
				{
					GlobalEventManager.onServerDamageDealt += TaserSlow;
				}, delegate
				{
					GlobalEventManager.onServerDamageDealt -= TaserSlow;
				});
				Add(delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<1>__OrbitalIcon;
					if (obj == null)
					{
						hook_GetCurrentIcon val = OrbitalIcon;
						<>O.<1>__OrbitalIcon = val;
						obj = (object)val;
					}
					CaptainOrbitalSkillDef.GetCurrentIcon += (hook_GetCurrentIcon)obj;
				}, delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<1>__OrbitalIcon;
					if (obj == null)
					{
						hook_GetCurrentIcon val = OrbitalIcon;
						<>O.<1>__OrbitalIcon = val;
						obj = (object)val;
					}
					CaptainOrbitalSkillDef.GetCurrentIcon -= (hook_GetCurrentIcon)obj;
				});
				Add(delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<2>__OrbitalName;
					if (obj == null)
					{
						hook_GetCurrentNameToken val = OrbitalName;
						<>O.<2>__OrbitalName = val;
						obj = (object)val;
					}
					CaptainOrbitalSkillDef.GetCurrentNameToken += (hook_GetCurrentNameToken)obj;
				}, delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<2>__OrbitalName;
					if (obj == null)
					{
						hook_GetCurrentNameToken val = OrbitalName;
						<>O.<2>__OrbitalName = val;
						obj = (object)val;
					}
					CaptainOrbitalSkillDef.GetCurrentNameToken -= (hook_GetCurrentNameToken)obj;
				});
				Add(delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<3>__OrbitalDescription;
					if (obj == null)
					{
						hook_GetCurrentDescriptionToken val = OrbitalDescription;
						<>O.<3>__OrbitalDescription = val;
						obj = (object)val;
					}
					CaptainOrbitalSkillDef.GetCurrentDescriptionToken += (hook_GetCurrentDescriptionToken)obj;
				}, delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<3>__OrbitalDescription;
					if (obj == null)
					{
						hook_GetCurrentDescriptionToken val = OrbitalDescription;
						<>O.<3>__OrbitalDescription = val;
						obj = (object)val;
					}
					CaptainOrbitalSkillDef.GetCurrentDescriptionToken -= (hook_GetCurrentDescriptionToken)obj;
				});
				Add(delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<4>__OrbitalCanExecute;
					if (obj == null)
					{
						hook_CanExecute val = OrbitalCanExecute;
						<>O.<4>__OrbitalCanExecute = val;
						obj = (object)val;
					}
					CaptainOrbitalSkillDef.CanExecute += (hook_CanExecute)obj;
				}, delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<4>__OrbitalCanExecute;
					if (obj == null)
					{
						hook_CanExecute val = OrbitalCanExecute;
						<>O.<4>__OrbitalCanExecute = val;
						obj = (object)val;
					}
					CaptainOrbitalSkillDef.CanExecute -= (hook_CanExecute)obj;
				});
				Add(delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<5>__OrbitalIsReady;
					if (obj == null)
					{
						hook_IsReady val = OrbitalIsReady;
						<>O.<5>__OrbitalIsReady = val;
						obj = (object)val;
					}
					CaptainOrbitalSkillDef.IsReady += (hook_IsReady)obj;
				}, delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<5>__OrbitalIsReady;
					if (obj == null)
					{
						hook_IsReady val = OrbitalIsReady;
						<>O.<5>__OrbitalIsReady = val;
						obj = (object)val;
					}
					CaptainOrbitalSkillDef.IsReady -= (hook_IsReady)obj;
				});
				Add(delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<6>__HealingBeacon;
					if (obj == null)
					{
						hook_HealOccupants val = HealingBeacon;
						<>O.<6>__HealingBeacon = val;
						obj = (object)val;
					}
					HealingWard.HealOccupants += (hook_HealOccupants)obj;
				}, delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<6>__HealingBeacon;
					if (obj == null)
					{
						hook_HealOccupants val = HealingBeacon;
						<>O.<6>__HealingBeacon = val;
						obj = (object)val;
					}
					HealingWard.HealOccupants -= (hook_HealOccupants)obj;
				});
				Add(delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<7>__Description;
					if (obj == null)
					{
						hook_GetLocalizedStringByToken val = Description;
						<>O.<7>__Description = val;
						obj = (object)val;
					}
					Language.GetLocalizedStringByToken += (hook_GetLocalizedStringByToken)obj;
				}, delegate
				{
					//IL_0010: 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_001b: Expected O, but got Unknown
					object obj = <>O.<7>__Description;
					if (obj == null)
					{
						hook_GetLocalizedStringByToken val = Description;
						<>O.<7>__Description = val;
						obj = (object)val;
					}
					Language.GetLocalizedStringByToken -= (hook_GetLocalizedStringByToken)obj;
				});
				log.LogInfo((object)"Captain changes ENABLED: taser slows shock-immune enemies by 50% for 5s; orbital Utility/Special available in hidden realms; Healing Beacon converts full-health ticks into barrier up to 20% maximum health.");
			}
			catch (Exception arg)
			{
				Dispose();
				log.LogError((object)$"Could not enable the full Captain patch; removed its hooks. {arg}");
			}
		}

		private void Add(Action install, Action remove)
		{
			cleanup.Add(remove);
			install();
		}

		public void Dispose()
		{
			for (int num = cleanup.Count - 1; num >= 0; num--)
			{
				try
				{
					cleanup[num]();
				}
				catch (Exception arg)
				{
					log.LogError((object)$"Captain hook cleanup failed: {arg}");
				}
			}
			cleanup.Clear();
		}

		private static T WithoutOrbitalBlock<T>(Func<T> action)
		{
			SceneDef mostRecentSceneDef = SceneCatalog.mostRecentSceneDef;
			if (!Object.op_Implicit((Object)(object)mostRecentSceneDef) || !mostRecentSceneDef.blockOrbitalSkills)
			{
				return action();
			}
			mostRecentSceneDef.blockOrbitalSkills = false;
			try
			{
				return action();
			}
			finally
			{
				mostRecentSceneDef.blockOrbitalSkills = true;
			}
		}

		private static Sprite OrbitalIcon(orig_GetCurrentIcon orig, CaptainOrbitalSkillDef self, GenericSkill slot)
		{
			return WithoutOrbitalBlock(() => orig.Invoke(self, slot));
		}

		private static string OrbitalName(orig_GetCurrentNameToken orig, CaptainOrbitalSkillDef self, GenericSkill slot)
		{
			return WithoutOrbitalBlock(() => orig.Invoke(self, slot));
		}

		private static string OrbitalDescription(orig_GetCurrentDescriptionToken orig, CaptainOrbitalSkillDef self, GenericSkill slot)
		{
			return WithoutOrbitalBlock(() => orig.Invoke(self, slot));
		}

		private static bool OrbitalCanExecute(orig_CanExecute orig, CaptainOrbitalSkillDef self, GenericSkill slot)
		{
			return WithoutOrbitalBlock(() => orig.Invoke(self, slot));
		}

		private static bool OrbitalIsReady(orig_IsReady orig, CaptainOrbitalSkillDef self, GenericSkill slot)
		{
			return WithoutOrbitalBlock(() => orig.Invoke(self, slot));
		}

		private static bool IsCaptainHealingBeacon(HealingWard ward)
		{
			return CaptainBalance.IsHealingWardName(((Object)((Component)ward).gameObject).name);
		}

		private static void TaserSlow(DamageReport report)
		{
			//IL_003c: 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_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Invalid comparison between Unknown and I4
			//IL_007c: 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_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Invalid comparison between Unknown and I4
			//IL_00a7: 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)
			if (!NetworkServer.active || !Object.op_Implicit((Object)(object)report.attackerBody) || !Object.op_Implicit((Object)(object)report.victimBody) || !report.victim.alive || report.damageInfo.rejected || report.attackerTeamIndex == report.victimTeamIndex)
			{
				return;
			}
			DamageInfo damageInfo = report.damageInfo;
			if (!(report.attackerBody.baseNameToken != "CAPTAIN_BODY_NAME") && (int)damageInfo.damageType.damageSource == 2 && (damageInfo.damageType.damageType & 0x1000000) != 0 && (int)damageInfo.dotIndex == -1 && !(damageInfo.procCoefficient <= 0f) && ((ProcChainMask)(ref damageInfo.procChainMask)).Equals(default(ProcChainMask)))
			{
				SetStateOnHurt component = ((Component)report.victimBody).GetComponent<SetStateOnHurt>();
				if (!Object.op_Implicit((Object)(object)component) || !component.canBeStunned || !Object.op_Implicit((Object)(object)component.targetStateMachine))
				{
					report.victimBody.AddTimedBuff(Buffs.Slow50, 5f);
				}
			}
		}

		private static void HealingBeacon(orig_HealOccupants orig, HealingWard self)
		{
			//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_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: 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_009a: 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)
			if (!NetworkServer.active || !IsCaptainHealingBeacon(self))
			{
				orig.Invoke(self);
				return;
			}
			List<HealthComponent> list = new List<HealthComponent>();
			TeamFilter component = ((Component)self).GetComponent<TeamFilter>();
			if (Object.op_Implicit((Object)(object)component))
			{
				float num = self.radius * self.radius;
				Vector3 position = ((Component)self).transform.position;
				foreach (TeamComponent teamMember in TeamComponent.GetTeamMembers(component.teamIndex))
				{
					HealthComponent val = (Object.op_Implicit((Object)(object)teamMember) ? ((Component)teamMember).GetComponent<HealthComponent>() : null);
					if (Object.op_Implicit((Object)(object)val) && val.alive)
					{
						Vector3 val2 = ((Component)teamMember).transform.position - position;
						if (!(((Vector3)(ref val2)).sqrMagnitude > num) && val.combinedHealth >= val.fullCombinedHealth)
						{
							list.Add(val);
						}
					}
				}
			}
			orig.Invoke(self);
			foreach (HealthComponent item in list)
			{
				if (Object.op_Implicit((Object)(object)item) && item.alive)
				{
					float healingTick = self.healPoints + item.fullHealth * self.healFraction;
					float barrierGrant = CaptainBalance.GetBarrierGrant(item.barrier, item.fullHealth, healingTick);
					if (barrierGrant > 0f)
					{
						item.AddBarrier(barrierGrant);
					}
				}
			}
		}

		private static string Description(orig_GetLocalizedStringByToken orig, Language self, string token)
		{
			return CaptainBalance.GetDescription(token) ?? orig.Invoke(self, token);
		}
	}
	internal static class ChefBalance
	{
		internal const float IceCubeSpreadDegrees = 2.5f;

		internal const float RollSlopeLimit = 60f;

		internal const float BoostedIceDamage = 10f;

		internal static bool CancelCrestLift(bool wasGrounded, bool grounded, bool forcedUnground)
		{
			if (wasGrounded && !grounded)
			{
				return !forcedUnground;
			}
			return false;
		}

		internal static float CollisionUpSpeed(float before, float after)
		{
			return Math.Min(after, Math.Max(0f, before));
		}

		internal static string? GetDescription(string token)
		{
			return token switch
			{
				"CHEF_SECONDARY_ALT_DESCRIPTION" => "<style=cIsUtility>Frost</style>. Launch ice cubes for <style=cIsDamage>3x150% damage</style>. <color=#C586FF><b>One randomly selected cube flies straight; the other two each have independent random spread within a 2.5-degree cone.</b></color>", 
				"CHEF_SECONDARY_ALT_BOOST_DESCRIPTION" => "<style=cKeywordName>Boost</style><style=cSub><style=cIsUtility>Freezing</style>. Boosting Ice Box launches 1 large ice cube for <style=cIsDamage><color=#C586FF><b>1000%</b></color> damage</style>.</style>", 
				"CHEF_SECONDARY_ALT_BOOST_DESCRIPTION_SKILL" => "<style=cSub><style=cIsUtility>Freezing</style>. Launches 1 large ice cube for <style=cIsDamage><color=#C586FF><b>1000%</b></color> damage</style>.</style>", 
				"CHEF_UTILITY_DESCRIPTION" => "<style=cIsDamage>Stunning</style>. Charge the rolling pin to <style=cIsUtility>speed</style> forward, dealing <style=cIsDamage>300%-600% damage</style>. <color=#C586FF><b>Automatic step climbing is disabled with a 60-degree walkable slope limit (or the original motor limit if lower) while rolling. Steep collisions and ramp crests cannot create upward launch speed; deliberate jumps remain available.</b></color>", 
				"CHEF_SPECIAL_ALT1_DESCRIPTION" => "Emit a blast attack dealing <style=cIsDamage>400%</style> damage, inflicting <style=cIsDamage>Ignite</style> or <style=cIsUtility>Frost</style>. <style=cIsUtility>Boosts</style> the next Skill used. <color=#C586FF><b>Can be used during Roll without ending it.</b></color>", 
				_ => null, 
			};
		}
	}
	internal sealed class IceBoxVolley
	{
		private readonly (float pitch, float yaw)[] offsets = new(float, float)[3];

		internal IceBoxVolley(Random random)
		{
			int num = random.Next(3);
			for (int i = 0; i < offsets.Length; i++)
			{
				if (i != num)
				{
					double num2 = random.NextDouble() * Math.PI * 2.0;
					double num3 = 0.5 + random.NextDouble() * 2.0;
					offsets[i] = (pitch: (float)(Math.Sin(num2) * num3), yaw: (float)(Math.Cos(num2) * num3));
				}
			}
		}

		internal (float pitch, float yaw) Offset(int firedCount)
		{
			return offsets[Math.Clamp(firedCount - 1, 0, 2)];
		}
	}
	internal sealed class ChefChanges : IDisposable
	{
		private delegate Vector3 ObstructionOrig(KinematicCharacterMotor self, Vector3 normal, bool stable);

		private delegate Vector3 ObstructionHook(ObstructionOrig orig, KinematicCharacterMotor self, Vector3 normal, bool stable);

		private delegate void ProjectionOrig(KinematicCharacterMotor self, ref Vector3 velocity, Vector3 normal, bool stable);

		private delegate void ProjectionHook(ProjectionOrig orig, KinematicCharacterMotor self, ref Vector3 velocity, Vector3 normal, bool stable);

		[CompilerGenerated]
		private static class <>O
		{
			public static Manipulator <0>__BoostedDamage;

			public static Manipulator <1>__PreserveRoll;

			public static hook_HandleMovements <2>__YesChefMovement;

			public static hook_PerformInputs <3>__YesChefInputs;

			public static hook_GetLocalizedStringByToken <4>__Description;

			public static ObstructionHook <5>__RollObstruction;

			public static ProjectionHook <6>__RollProjection;
		}

		private readonly ManualLogSource log;

		private readonly List<Action> cleanup = new List<Action>();

		private ConditionalWeakTable<IceBox, IceBoxVolley> iceVolleys = new ConditionalWeakTable<IceBox, IceBoxVolley>();

		private readonly Random spreadRandom = new Random();

		private readonly Dictionary<KinematicCharacterMotor, (StepHandlingMethod step, float slope)> rollMotors = new Dictionary<KinematicCharacterMotor, (StepHandlingMethod, float)>();

		internal ChefChanges(ManualLogSource log)
		{
			this.log = log;
		}

		internal void Enable()
		{
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Expected O, but got Unknown
			//IL_028c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0292: Expected O, but got Unknown
			try
			{
				Add(delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_0011: Expected O, but got Unknown
					RolyPoly.StartRolyPoly += new hook_StartRolyPoly(RollStarted);
				}, delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_0011: Expected O, but got Unknown
					RolyPoly.StartRolyPoly -= new hook_StartRolyPoly(RollStarted);
				});
				Add(delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_0011: Expected O, but got Unknown
					RolyPoly.OnExit += new hook_OnExit(RollExited);
				}, delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_0011: Expected O, but got Unknown
					RolyPoly.OnExit -= new hook_OnExit(RollExited);
				});
				Add(delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_0011: Expected O, but got Unknown
					CharacterMotor.AfterCharacterUpdate += new hook_AfterCharacterUpdate(RollAfterMovement);
				}, delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_0011: Expected O