Decompiled source of DirectorReworkPlus v1.3.1

DirectorRework.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using DirectorRework.Cruelty;
using DirectorRework.Modules;
using EntityStates;
using HG;
using HarmonyLib;
using IL.EntityStates.VoidInfestor;
using IL.RoR2;
using JetBrains.Annotations;
using Microsoft.CodeAnalysis;
using Mono.Cecil.Cil;
using MonoMod.Cil;
using On.RoR2;
using RiskOfOptions;
using RiskOfOptions.OptionConfigs;
using RiskOfOptions.Options;
using RoR2;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Networking;

[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("DirectorRework")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+a4186c85d74895c5d15461025937609e8590e581")]
[assembly: AssemblyProduct("DirectorRework")]
[assembly: AssemblyTitle("DirectorRework")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 DirectorRework
{
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("com.score.DirectorReworkPlus", "DirectorReworkPlus", "1.3.1")]
	public class DirectorReworkPlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "com.score.DirectorReworkPlus";

		public const string PluginAuthor = "score";

		public const string PluginName = "DirectorReworkPlus";

		public const string PluginVersion = "1.3.1";

		public static DirectorReworkPlugin Instance { get; private set; }

		public static bool RooInstalled => Chainloader.PluginInfos.ContainsKey("com.rune580.riskofoptions");

		public void Awake()
		{
			Instance = this;
			Log.Init(((BaseUnityPlugin)this).Logger);
			PluginConfig.Init(((BaseUnityPlugin)this).Config);
			CombatCruelty.Init();
			ScriptedCruelty.Init();
			CrueltyManager.Init();
			DirectorMain.Init();
			DirectorTweaks.Init();
			ScalingTweaks.Init();
		}
	}
	public static class Log
	{
		private static ManualLogSource _logSource;

		internal static void Init(ManualLogSource logSource)
		{
			_logSource = logSource;
		}

		public static void Debug(string data)
		{
			if (PluginConfig.enableDebugLogs.Value)
			{
				_logSource.LogDebug((object)data);
			}
		}

		public static void Info(string data)
		{
			if (PluginConfig.enableDebugLogs.Value)
			{
				_logSource.LogInfo((object)data);
			}
		}

		public static void Error(string data)
		{
			_logSource.LogError((object)data);
		}

		public static void Fatal(string data)
		{
			_logSource.LogFatal((object)data);
		}

		public static void Message(string data)
		{
			_logSource.LogMessage((object)data);
		}

		public static void Warning(string data)
		{
			_logSource.LogWarning((object)data);
		}
	}
	public static class PluginConfig
	{
		public static ConfigFile MainConfig;

		public static ConfigEntry<bool> enableCruelty;

		public static ConfigEntry<bool> enableDirectorMain;

		public static ConfigEntry<bool> enableDirectorTweaks;

		public static ConfigEntry<bool> enableScalingTweaks;

		public static ConfigEntry<bool> enableDebugLogs;

		public static ConfigEntry<bool> enableMoreDebugLogs;

		public static ConfigEntry<int> maxAffixes;

		public static ConfigEntry<int> maxScriptedAffixes;

		public static ConfigEntry<bool> guaranteeSpecialBoss;

		public static ConfigEntry<bool> allowBosses;

		public static ConfigEntry<bool> onlyApplyToElites;

		public static ConfigEntry<bool> bossesAreElite;

		public static ConfigEntry<bool> bossesGetStats;

		public static ConfigEntry<int> triggerChance;

		public static ConfigEntry<int> successChance;

		public static ConfigEntry<string> blacklistedElites;

		public static ConfigEntry<bool> enableBossDiversity;

		public static ConfigEntry<bool> enableSpawnDiversity;

		public static ConfigEntry<bool> enableVieldsDiversity;

		public static ConfigEntry<bool> enableCreditRefund;

		public static ConfigEntry<int> creditRefundMultiplier;

		public static ConfigEntry<int> hordeOfManyChance;

		public static ConfigEntry<int> maxBossSpawns;

		public static ConfigEntry<bool> useRecommendedValues;

		public static ConfigEntry<float> creditMultiplier;

		public static ConfigEntry<float> spawnDistanceMultiplier;

		public static ConfigEntry<bool> useSlowDirector;

		public static ConfigEntry<float> fastSpawnInterval;

		public static ConfigEntry<float> slowSpawnInterval;

		public static ConfigEntry<float> spawnIntervalVariance;

		public static ConfigEntry<int> maximumNumberToSpawnBeforeSkipping;

		public static ConfigEntry<int> maxConsecutiveCheapSkips;

		public static ConfigEntry<bool> rampTyphoonCredits;

		public static ConfigEntry<bool> enableLinearScaling;

		public static ConfigEntry<float> linearScalingMultiplier;

		public static T GetValueOrDefault<T>(this ConfigEntry<T> entry)
		{
			if (useRecommendedValues.Value)
			{
				return (T)((ConfigEntryBase)entry).DefaultValue;
			}
			return entry.Value;
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static void Init(ConfigFile cfg)
		{
			MainConfig = cfg;
			if (DirectorReworkPlugin.RooInstalled)
			{
				InitRoO();
			}
			BindModules(cfg, "1. Modules");
			BindCruelty(cfg, "2. Affixes/Cruelty");
			BindMain(cfg, "3. Director Main");
			BindDirectorTweaks(cfg, "4. Director Tweaks");
			BindScalingTweaks(cfg, "5. Scaling Tweaks");
		}

		private static void BindModules(ConfigFile cfg, string section)
		{
			enableCruelty = cfg.BindOption(section, "Enable Affix Stacking", defaultValue: false, "Enables Affix Stacking (highly inspired by Artifact of Cruelty in RiskyArtifacts). Disable to prevent all modifications in 'Affixes/Cruelty' from loading.");
			enableDirectorMain = cfg.BindOption(section, "Enable Director Changes", defaultValue: true, "Enables Enemy Variety and all 'Director Main' config options. Disable to prevent all modifications in 'Director Main' from loading.");
			enableDirectorTweaks = cfg.BindOption(section, "Enable Combat Director Tweaks", defaultValue: true, "Enables a variety of configurable Combat Director options. Intended for fine tuning the pacing of spawns. Disable to prevent all modifications in 'Director Tweaks' from loading.");
			enableScalingTweaks = cfg.BindOption(section, "Enable Scaling Tweaks", defaultValue: true, "Enables run scaling tweaks. Disable to prevent all modifications in 'Scaling Tweaks' from loading.");
			enableDebugLogs = cfg.BindOption(section, "Enable Debug Logs", defaultValue: false, "Prints some stuff that might be useful. turn this on before reporting a problem :)");
			enableMoreDebugLogs = cfg.BindOption(section, "Enable Even More Debug Logs", defaultValue: false, "Nerd.");
		}

		private static void BindCruelty(ConfigFile cfg, string section)
		{
			maxAffixes = cfg.BindOptionSlider(section, "Max Additional Affixes", 3, "Maximum Affixes that an enemy can have. Combat Director will still need to afford the combined credit cost of the new enemy.", 0f, 10f);
			maxScriptedAffixes = cfg.BindOptionSlider(section, "Max Scripted Event Affixes", 2, "Maximum Affixes that an enemy from a scripted event (Mithrix, void cradle) can have.", 0f, 10f);
			guaranteeSpecialBoss = cfg.BindOption(section, "Guarantee Special Boss", defaultValue: true, "Always apply additional affixes to special bosses in scripted events. Applies to void cradles, Mithrix, Alloy Worship Unit, etc");
			allowBosses = cfg.BindOption(section, "Allow Boss Affix Stacking", defaultValue: true, "Allows any bosses to recieve additional affixes. This setting is ignored during scripted combat events if Guarantee Special Boss is true.");
			onlyApplyToElites = cfg.BindOption(section, "Only Apply to Elites", defaultValue: true, "Only applies additional affixes to enemies that are already elite. Setting this to false will increase the occurrance of elites as a whole.");
			bossesAreElite = cfg.BindOption(section, "Bosses Ignore Elite Setting", defaultValue: true, "When enabled, bosses do not have to be elite to receive affixes.");
			bossesGetStats = cfg.BindOption(section, "Bosses Get Stats", defaultValue: false, "When enabled, bosses recieve bonus health and damage buffs.");
			triggerChance = cfg.BindOptionSlider(section, "Trigger Chance", 20, "Chance to apply the first additional affix to an enemy. Set to 100 to make it always apply.", 0f, 100f);
			successChance = cfg.BindOptionSlider(section, "Additional Affix Chance", 10, "Chance to add an additional affix after the first. Set to 100 to make it always attempt to add as many affixes as possible.", 0f, 100f);
			blacklistedElites = cfg.BindOption(section, "Blacklisted Elites", "EliteLunarEquipment, AffixBlightedMoffein", "Blacklisted elite equipment names. Use internal names, like EliteLunarEquipment");
		}

		private static void BindMain(ConfigFile cfg, string section)
		{
			enableBossDiversity = cfg.BindOption(section, "Enable Boss Diversity", defaultValue: true, "Spawns multiple boss types during teleporter events.");
			enableSpawnDiversity = cfg.BindOption(section, "Enable Spawn Diversity", defaultValue: true, "Spawns multiple enemy types per wave.");
			enableVieldsDiversity = cfg.BindOption(section, "Enable Void Fields Spawn Diversity", defaultValue: true, "Spawns multiple enemy types in void fields. Selection is limited to the enemy types that can spawn on the final wave.");
			enableCreditRefund = cfg.BindOption(section, "Enable Credit Refund", defaultValue: false, "Gives combat director back a percent of credits spent on spawns when they are killed.");
			creditRefundMultiplier = cfg.BindOptionSlider(section, "Percent Refund", 15, "Amount to refund the combat director when an enemy is killed, in percent. 100 is a bad idea, but its technically possible.", 0f, 100f);
			hordeOfManyChance = cfg.BindOptionSlider(section, "Horde of Many Chance", 5, "Chance to replace the teleporter event with a Horde of Many. Vanilla is 0 (only used when it can't spawn normal bosses)", 0f, 100f);
			maxBossSpawns = cfg.BindOptionSlider(section, "Max Boss/Horde Spawns", 12, "Maximum number of enemies that can be spawned as the teleporter boss, scaled with playercount. Affects normal bosses and horde of many. Vanilla is 6.", 0f, 100f);
		}

		private static void BindDirectorTweaks(ConfigFile cfg, string section)
		{
			useRecommendedValues = cfg.BindOption(section, "Use Recommended Values", defaultValue: true, "If enabled, then the recommended values for this section will be used instead of the ones set in the config. Disable this setting if you want to change this section. Set any value to -1 to retain the default vanilla value.");
			creditMultiplier = cfg.BindOptionSlider(section, "Credit Multiplier", 1f, "Multiplies the monster credit accumulation rate.", -1f, 5f);
			spawnDistanceMultiplier = cfg.BindOptionSlider(section, "Spawn Distance Multiplier", 1.2f, "Multiplier to the max spawn range from the desired target.", -1f, 5f);
			spawnIntervalVariance = cfg.BindOptionSlider(section, "Spawn Interval Multiplier", 1.4f, "Adds a degree of randomness to the spawn timings, max delay determined by the interval times this value.", 1f, 5f);
			fastSpawnInterval = cfg.BindOptionSlider(section, "Fast Spawn Interval", 5f, "Minimum delay before attempting to spawn a new wave.", -1f);
			useSlowDirector = cfg.BindOption(section, "Use Slow Director", defaultValue: true, "Disable to make all stage spawning directors use the fast spawn intervals.");
			slowSpawnInterval = cfg.BindOptionSlider(section, "Slow Spawn Interval", 12f, "Minimum delay before attempting to spawn a new expensive wave. Requires Use Slow Director to be enabled, and should be larger than the fast interval.", -1f, 30f);
			maximumNumberToSpawnBeforeSkipping = cfg.BindOptionSlider(section, "Maximum Number To Spawn Before Skipping", 5, "Maximum number of enemies in a single wave. If the director can afford more than this, it'll reroll the spawncard and try again later.", -1f);
			maxConsecutiveCheapSkips = cfg.BindOptionSlider(section, "Max Consecutive Cheap Skips", 4, "If skipSpawnIfTooCheap is true, we'll behave as though it's not set after this many consecutive skips.", -1f);
		}

		private static void BindScalingTweaks(ConfigFile cfg, string section)
		{
			rampTyphoonCredits = cfg.BindOption(section, "Ramp Director Credit Scaling", defaultValue: true, "When other mods add credit scaling, it generally is unintentionally difficult on early stages. Enable this option to start stage 1 with 50% of the multipler and ramp up to the full credit multiplier on stage 3");
			enableLinearScaling = cfg.BindOption(section, "Enable Linear Stage Scaling", defaultValue: false, "Enables linear scaling for the stages cleared coefficient. Doesn't affect stage 1 or time scaling. Swaps back when exponential scaling is greater.");
			linearScalingMultiplier = cfg.BindOptionSlider(section, "Linear Scaling Per Stage", 0.2f, "Will be applied to the formula (1 + {VALUE} * StagesCleared). A value of 0.2 will make stages 2-5 a bit harder. A value of 0.25 will make stages 2-7 significantly harder.", 0.15f, 0.5f);
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static void InitRoO()
		{
			//IL_0042: 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_004e: Expected O, but got Unknown
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected O, but got Unknown
			try
			{
				ModSettingsManager.SetModDescription("Combat Director Tweaks and Elite Stacking", "com.score.DirectorReworkPlus", "DirectorReworkPlus");
				byte[] array = File.ReadAllBytes(Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)DirectorReworkPlugin.Instance).Info.Location), "icon.png"));
				Texture2D val = new Texture2D(256, 256);
				ImageConversion.LoadImage(val, array);
				ModSettingsManager.SetModIcon(Sprite.Create(val, new Rect(0f, 0f, 256f, 256f), new Vector2(0.5f, 0.5f)));
			}
			catch (Exception ex)
			{
				Log.Info(ex.ToString());
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static ConfigEntry<T> BindOption<T>(this ConfigFile myConfig, string section, string name, T defaultValue, string description = "", bool restartRequired = false)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			if ((defaultValue is int || defaultValue is float) ? true : false)
			{
				return myConfig.BindOptionSlider(section, name, defaultValue, description, 0f, 20f, restartRequired);
			}
			if (string.IsNullOrEmpty(description))
			{
				description = name;
			}
			if (restartRequired)
			{
				description += " (restart required)";
			}
			ConfigEntry<T> val = myConfig.Bind<T>(section, name, defaultValue, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()));
			if (DirectorReworkPlugin.RooInstalled)
			{
				TryRegisterOption<T>(val, restartRequired);
			}
			return val;
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static ConfigEntry<T> BindOptionSlider<T>(this ConfigFile myConfig, string section, string name, T defaultValue, string description = "", float min = 0f, float max = 20f, bool restartRequired = false)
		{
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Expected O, but got Unknown
			if ((!(defaultValue is int) && !(defaultValue is float)) || 1 == 0)
			{
				return myConfig.BindOption(section, name, defaultValue, description, restartRequired);
			}
			if (string.IsNullOrEmpty(description))
			{
				description = name;
			}
			string text = description;
			T val = defaultValue;
			description = text + " (Default: " + val?.ToString() + ")";
			if (restartRequired)
			{
				description += " (restart required)";
			}
			AcceptableValueBase val2 = (AcceptableValueBase)((typeof(T) == typeof(int)) ? ((object)new AcceptableValueRange<int>((int)min, (int)max)) : ((object)new AcceptableValueRange<float>(min, max)));
			ConfigEntry<T> val3 = myConfig.Bind<T>(section, name, defaultValue, new ConfigDescription(description, val2, Array.Empty<object>()));
			if (DirectorReworkPlugin.RooInstalled)
			{
				TryRegisterOptionSlider<T>(val3, min, max, restartRequired);
			}
			return val3;
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static ConfigEntry<T> BindOptionSteppedSlider<T>(this ConfigFile myConfig, string section, string name, T defaultValue, float increment = 1f, string description = "", float min = 0f, float max = 20f, bool restartRequired = false)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			if (string.IsNullOrEmpty(description))
			{
				description = name;
			}
			string text = description;
			T val = defaultValue;
			description = text + " (Default: " + val?.ToString() + ")";
			if (restartRequired)
			{
				description += " (restart required)";
			}
			ConfigEntry<T> val2 = myConfig.Bind<T>(section, name, defaultValue, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(min, max), Array.Empty<object>()));
			if (DirectorReworkPlugin.RooInstalled)
			{
				TryRegisterOptionSteppedSlider<T>(val2, increment, min, max, restartRequired);
			}
			return val2;
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static void TryRegisterOption<T>(ConfigEntry<T> entry, bool restartRequired)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			if (entry is ConfigEntry<string> val)
			{
				ModSettingsManager.AddOption((BaseOption)new StringInputFieldOption(val, new InputFieldConfig
				{
					submitOn = (SubmitEnum)6,
					restartRequired = restartRequired
				}));
			}
			else if (entry is ConfigEntry<bool> val2)
			{
				ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(val2, restartRequired));
			}
			else if (entry is ConfigEntry<KeyboardShortcut> val3)
			{
				ModSettingsManager.AddOption((BaseOption)new KeyBindOption(val3, restartRequired));
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static void TryRegisterOptionSlider<T>(ConfigEntry<T> entry, float min, float max, bool restartRequired)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Expected O, but got Unknown
			if (entry is ConfigEntry<int> val)
			{
				ModSettingsManager.AddOption((BaseOption)new IntSliderOption(val, new IntSliderConfig
				{
					min = (int)min,
					max = (int)max,
					formatString = "{0:0.00}",
					restartRequired = restartRequired
				}));
			}
			else if (entry is ConfigEntry<float> val2)
			{
				ModSettingsManager.AddOption((BaseOption)new SliderOption(val2, new SliderConfig
				{
					min = min,
					max = max,
					FormatString = "{0:0.00}",
					restartRequired = restartRequired
				}));
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static void TryRegisterOptionSteppedSlider<T>(ConfigEntry<T> entry, float increment, float min, float max, bool restartRequired)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			if (entry is ConfigEntry<float> val)
			{
				ModSettingsManager.AddOption((BaseOption)new StepSliderOption(val, new StepSliderConfig
				{
					increment = increment,
					min = min,
					max = max,
					FormatString = "{0:0.00}",
					restartRequired = restartRequired
				}));
			}
		}
	}
}
namespace DirectorRework.Modules
{
	public class CrueltyManager
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static Manipulator <0>__Infest_FixedUpdate;

			public static Manipulator <1>__GlobalEventManager_OnCharacterDeath;
		}

		private readonly HashSet<EquipmentIndex> _blacklistedElites = new HashSet<EquipmentIndex>();

		public bool ModuleEnabled { get; private set; }

		public static CrueltyManager Instance { get; private set; }

		public static void Init()
		{
			if (Instance == null)
			{
				Instance = new CrueltyManager();
			}
		}

		public CrueltyManager()
		{
			((ResourceAvailability)(ref EquipmentCatalog.availability)).CallWhenAvailable((Action)OnLoad);
			OnSettingChanged();
			PluginConfig.enableCruelty.SettingChanged += OnSettingChanged;
		}

		public void OnSettingChanged(object _ = null, EventArgs __ = null)
		{
			if (PluginConfig.enableCruelty.Value)
			{
				SetHooks();
			}
			else
			{
				UnsetHooks();
			}
		}

		public void SetHooks()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Expected O, but got Unknown
			if (!ModuleEnabled)
			{
				ModuleEnabled = true;
				GlobalEventManager.onCharacterDeathGlobal += GlobalEventManager_onCharacterDeathGlobal;
				CombatDirector.Awake += new hook_Awake(CombatCruelty.Instance.CombatDirector_Awake);
				ScriptedCombatEncounter.Awake += new hook_Awake(ScriptedCruelty.Instance.ScriptedCombatEncounter_Awake);
				object obj = <>O.<0>__Infest_FixedUpdate;
				if (obj == null)
				{
					Manipulator val = Infest_FixedUpdate;
					<>O.<0>__Infest_FixedUpdate = val;
					obj = (object)val;
				}
				Infest.FixedUpdate += (Manipulator)obj;
				object obj2 = <>O.<1>__GlobalEventManager_OnCharacterDeath;
				if (obj2 == null)
				{
					Manipulator val2 = GlobalEventManager_OnCharacterDeath;
					<>O.<1>__GlobalEventManager_OnCharacterDeath = val2;
					obj2 = (object)val2;
				}
				GlobalEventManager.OnCharacterDeath += (Manipulator)obj2;
			}
		}

		public void UnsetHooks()
		{
			//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
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			object obj = <>O.<1>__GlobalEventManager_OnCharacterDeath;
			if (obj == null)
			{
				Manipulator val = GlobalEventManager_OnCharacterDeath;
				<>O.<1>__GlobalEventManager_OnCharacterDeath = val;
				obj = (object)val;
			}
			GlobalEventManager.OnCharacterDeath -= (Manipulator)obj;
			object obj2 = <>O.<0>__Infest_FixedUpdate;
			if (obj2 == null)
			{
				Manipulator val2 = Infest_FixedUpdate;
				<>O.<0>__Infest_FixedUpdate = val2;
				obj2 = (object)val2;
			}
			Infest.FixedUpdate -= (Manipulator)obj2;
			ScriptedCombatEncounter.Awake -= new hook_Awake(ScriptedCruelty.Instance.ScriptedCombatEncounter_Awake);
			CombatDirector.Awake -= new hook_Awake(CombatCruelty.Instance.CombatDirector_Awake);
			GlobalEventManager.onCharacterDeathGlobal -= GlobalEventManager_onCharacterDeathGlobal;
			ModuleEnabled = false;
		}

		private void OnLoad()
		{
			BlacklistEquipment("AffixBlightedMoffein");
			BlacklistEquipment("EliteLunarEquipment");
		}

		private void BlacklistEquipment(string name)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Invalid comparison between Unknown and I4
			//IL_000b: 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_004a: Invalid comparison between Unknown and I4
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			EquipmentIndex val = EquipmentCatalog.FindEquipmentIndex(name);
			if ((int)val != -1)
			{
				EquipmentDef equipmentDef = EquipmentCatalog.GetEquipmentDef(val);
				if (equipmentDef != null)
				{
					BuffDef passiveBuffDef = equipmentDef.passiveBuffDef;
					if (((passiveBuffDef != null) ? new bool?(passiveBuffDef.isElite) : null).GetValueOrDefault() && (int)equipmentDef.passiveBuffDef.buffIndex != -1)
					{
						Log.Info("Blacklisting " + name);
						_blacklistedElites.Add(val);
						return;
					}
				}
			}
			Log.Info("Failed to blacklist " + name);
		}

		private void GlobalEventManager_onCharacterDeathGlobal(DamageReport report)
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Invalid comparison between Unknown and I4
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active || !report.victimIsElite || !Object.op_Implicit((Object)(object)report.victimBody))
			{
				return;
			}
			Inventory val = (Object.op_Implicit((Object)(object)report.victimMaster) ? report.victimMaster.inventory : null);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			float num = (Object.op_Implicit((Object)(object)report.attackerMaster) ? report.attackerMaster.luck : 0f);
			EquipmentIndex currentEquipmentIndex = val.currentEquipmentIndex;
			for (uint num2 = 0u; num2 < val.GetEquipmentSlotCount(); num2++)
			{
				EquipmentDef equipmentDef = val.GetEquipment(num2, 0u).equipmentDef;
				if ((equipmentDef == null || equipmentDef.dropOnDeathChance != 0f) && (int)equipmentDef.equipmentIndex != -1 && equipmentDef.equipmentIndex != currentEquipmentIndex && Util.CheckRoll(equipmentDef.dropOnDeathChance * 100f, num + (float)num2, report.attackerMaster))
				{
					Ray val2 = (Ray)(Object.op_Implicit((Object)(object)report.victimBody.inputBank) ? report.victimBody.inputBank.GetAimRay() : new Ray(report.victimBody.corePosition, report.victimBody.transform.rotation * Vector3.forward));
					((Ray)(ref val2)).origin = ((Ray)(ref val2)).origin + Vector3.up * 1.5f;
					((Ray)(ref val2)).direction = ((Ray)(ref val2)).direction * 2f + Vector3.up * 20f;
					if (PluginConfig.enableMoreDebugLogs.Value)
					{
						Log.Debug("dropping affix " + equipmentDef.nameToken + " woo " + num2 + "x luck!");
					}
					PickupDropletController.CreatePickupDroplet(new UniquePickup(PickupCatalog.FindPickupIndex(equipmentDef.equipmentIndex)), ((Ray)(ref val2)).origin, ((Ray)(ref val2)).direction, false);
				}
			}
		}

		private static void GlobalEventManager_OnCharacterDeath(ILContext il)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Expected O, but got Unknown
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			ILCursor val = new ILCursor(il);
			int victimBodyLoc = 0;
			int infestorMasterLoc = 0;
			if (val.TryGotoNext(new Func<Instruction, bool>[3]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, ref victimBodyLoc),
				(Instruction x) => ILPatternMatchingExt.MatchLdsfld(x, AccessTools.Field(typeof(Buffs), "EliteVoid")),
				(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)AccessTools.Method(typeof(CharacterBody), "HasBuff", new Type[1] { typeof(BuffDef) }, (Type[])null))
			}) && val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[2]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, ref infestorMasterLoc),
				(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt<CharacterMaster>(x, "SpawnBodyHere")
			}))
			{
				val.Emit(OpCodes.Ldloc, victimBodyLoc);
				val.Emit(OpCodes.Ldloc, infestorMasterLoc);
				val.Emit(OpCodes.Call, (MethodBase)AccessTools.Method(typeof(CrueltyManager), "TransferAffixes", new Type[2]
				{
					typeof(CharacterBody),
					typeof(CharacterMaster)
				}, (Type[])null));
			}
			else
			{
				Log.Error("Director Rework: GlobalEventManager_OnCharacterDeath IL Hook failed");
			}
		}

		private static void Infest_FixedUpdate(ILContext il)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Expected O, but got Unknown
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			ILCursor val = new ILCursor(il);
			int loc = 0;
			if (val.TryGotoNext(new Func<Instruction, bool>[2]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, ref loc),
				(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)AccessTools.PropertyGetter(typeof(CharacterBody), "inventory"))
			}) && val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
			{
				(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt<Inventory>(x, "SetEquipmentIndex")
			}))
			{
				val.Emit(OpCodes.Ldarg_0);
				val.Emit(OpCodes.Call, (MethodBase)AccessTools.PropertyGetter(typeof(EntityState), "characterBody"));
				val.Emit(OpCodes.Ldloc, loc);
				val.Emit(OpCodes.Call, (MethodBase)AccessTools.Method(typeof(CrueltyManager), "TransferAffixes", new Type[2]
				{
					typeof(CharacterBody),
					typeof(CharacterBody)
				}, (Type[])null));
			}
			else
			{
				Log.Error("Director Rework: Infest_FixedUpdate IL Hook failed");
			}
		}

		internal static void TransferAffixes(CharacterBody sourceBody, CharacterMaster targetMaster)
		{
			TransferAffixes(Object.op_Implicit((Object)(object)sourceBody) ? sourceBody.inventory : null, Object.op_Implicit((Object)(object)targetMaster) ? targetMaster.GetBody() : null);
		}

		internal static void TransferAffixes(CharacterBody sourceBody, CharacterBody targetBody)
		{
			TransferAffixes(Object.op_Implicit((Object)(object)sourceBody) ? sourceBody.inventory : null, targetBody);
		}

		internal static void TransferAffixes(Inventory sourceInventory, CharacterBody targetBody)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Invalid comparison between Unknown and I4
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Invalid comparison between Unknown and I4
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Invalid comparison between Unknown and I4
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)sourceInventory))
			{
				return;
			}
			Inventory val = (Object.op_Implicit((Object)(object)targetBody) ? targetBody.inventory : null);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			uint num = 0u;
			for (uint num2 = 0u; num2 <= val.GetEquipmentSlotCount(); num2++)
			{
				if ((int)val.GetEquipment(num2, 0u).equipmentIndex == -1)
				{
					num = num2;
					break;
				}
			}
			for (uint num3 = 0u; num3 < sourceInventory.GetEquipmentSlotCount(); num3++)
			{
				EquipmentDef equipmentDef = sourceInventory.GetEquipment(num3, 0u).equipmentDef;
				if (equipmentDef?.passiveBuffDef != null && (int)equipmentDef.equipmentIndex != -1 && (int)equipmentDef.passiveBuffDef.buffIndex != -1 && equipmentDef.passiveBuffDef.isElite && !targetBody.HasBuff(equipmentDef.passiveBuffDef.buffIndex))
				{
					val.SetEquipmentIndexForSlot(equipmentDef.equipmentIndex, num, 0u);
					targetBody.AddBuff(equipmentDef.passiveBuffDef);
					num++;
				}
			}
		}

		internal void GiveAffix(CharacterBody body, Inventory inventory, EquipmentDef equipment)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Invalid comparison between Unknown and I4
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			for (uint num = 0u; num <= inventory.GetEquipmentSlotCount(); num++)
			{
				EquipmentIndex equipmentIndex = inventory.GetEquipment(num, 0u).equipmentIndex;
				if ((int)equipmentIndex == -1 || equipmentIndex == equipment.equipmentIndex)
				{
					inventory.SetEquipmentIndexForSlot(equipment.equipmentIndex, num, 0u);
					break;
				}
			}
			body.SetBuffCount(equipment.passiveBuffDef.buffIndex, 1);
		}

		internal void GiveItemBoosts(Inventory inventory, EliteDef def, int affixes)
		{
			inventory.GiveItemPermanent(Items.BoostHp, Mathf.RoundToInt(def.healthBoostCoefficient * 10f / (float)(affixes + 2)));
			inventory.GiveItemPermanent(Items.BoostDamage, Mathf.RoundToInt((def.damageBoostCoefficient - 1f) * 10f / (float)(affixes + 1)));
		}

		internal void GiveItemBoostsVerbose(Inventory inventory, EliteDef def, int affixes)
		{
			int num = Mathf.RoundToInt(def.healthBoostCoefficient * 10f / (float)(affixes + 2));
			Log.Debug("hp " + num);
			inventory.GiveItemPermanent(Items.BoostHp, num);
			num = Mathf.RoundToInt((def.damageBoostCoefficient - 1f) * 10f / (float)(affixes + 1));
			Log.Debug("dmg " + num);
			inventory.GiveItemPermanent(Items.BoostDamage, num);
		}

		internal void GiveDeathReward(DeathRewards deathReward, uint xp, uint gold, int affixes)
		{
			if (Object.op_Implicit((Object)(object)deathReward))
			{
				if (xp != 0)
				{
					deathReward.expReward += Convert.ToUInt32(xp / affixes);
				}
				if (gold != 0)
				{
					deathReward.goldReward += Convert.ToUInt32(gold / affixes);
				}
			}
		}

		internal bool IsEliteDefValid(EliteDef ed, List<BuffIndex> currentBuffs)
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Invalid comparison between Unknown and I4
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Invalid comparison between Unknown and I4
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)ed) && ed.IsAvailable())
			{
				EquipmentDef eliteEquipmentDef = ed.eliteEquipmentDef;
				bool? obj;
				if (eliteEquipmentDef == null)
				{
					obj = null;
				}
				else
				{
					BuffDef passiveBuffDef = eliteEquipmentDef.passiveBuffDef;
					obj = ((passiveBuffDef != null) ? new bool?(passiveBuffDef.isElite) : null);
				}
				bool? flag = obj;
				if (flag.HasValue && flag.GetValueOrDefault() && (int)ed.eliteEquipmentDef.equipmentIndex != -1 && (int)ed.eliteEquipmentDef.passiveBuffDef.buffIndex != -1 && !_blacklistedElites.Contains(ed.eliteEquipmentDef.equipmentIndex))
				{
					return !currentBuffs.Contains(ed.eliteEquipmentDef.passiveBuffDef.buffIndex);
				}
			}
			return false;
		}

		internal bool IsTierAvailable(EliteTierDef etd)
		{
			if (etd == null)
			{
				return false;
			}
			return !etd.canSelectWithoutAvailableEliteDef;
		}

		internal bool IsTierAffordable([NotNull] EliteTierDef etd, DirectorCard card, int cardCost, float availableCredits)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)((card != null) ? card.GetSpawnCard() : null)) && etd.CanSelect(card.GetSpawnCard().eliteRules))
			{
				return availableCredits >= (float)cardCost * etd.costMultiplier;
			}
			return false;
		}
	}
	public class DirectorMain
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static hook_Awake <0>__CombatDirector_Awake;

			public static hook_SetNextSpawnAsBoss <1>__CombatDirector_SetNextSpawnAsBoss;

			public static Manipulator <2>__IL_CombatDirector_SetNextSpawnAsBoss;

			public static Manipulator <3>__CombatDirector_AttemptSpawnOnTarget;

			public static hook_SendBroadcastChat_ChatMessageBase <4>__SendBroadcastChat_ChatMessageBase;

			public static hook_UpdateBossMemories <5>__UpdateBossMemories;

			public static UnityAction<GameObject, CombatDirector> <6>__OnSpawnedServer;
		}

		private const string SUBTITLE_FORMAT = "<sprite name=\"CloudLeft\" tint=1> {0} <sprite name=\"CloudRight\" tint=1>";

		[CompilerGenerated]
		private bool <RefundEnabled>k__BackingField;

		[CompilerGenerated]
		private bool <VarietyEnabled>k__BackingField;

		private CombatDirector self;

		public bool ConfigVarietyEnabled
		{
			get
			{
				if (!PluginConfig.enableBossDiversity.Value && !PluginConfig.enableSpawnDiversity.Value)
				{
					return PluginConfig.enableVieldsDiversity.Value;
				}
				return true;
			}
		}

		public bool RefundEnabled
		{
			[CompilerGenerated]
			get
			{
				return <RefundEnabled>k__BackingField;
			}
			set
			{
				//IL_004a: Unknown result type (might be due to invalid IL or missing references)
				//IL_004f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0055: Expected O, but got Unknown
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0034: Expected O, but got Unknown
				if (<RefundEnabled>k__BackingField == value)
				{
					return;
				}
				<RefundEnabled>k__BackingField = value;
				if (<RefundEnabled>k__BackingField)
				{
					object obj = <>O.<0>__CombatDirector_Awake;
					if (obj == null)
					{
						hook_Awake val = CombatDirector_Awake;
						<>O.<0>__CombatDirector_Awake = val;
						obj = (object)val;
					}
					CombatDirector.Awake += (hook_Awake)obj;
				}
				else
				{
					object obj2 = <>O.<0>__CombatDirector_Awake;
					if (obj2 == null)
					{
						hook_Awake val2 = CombatDirector_Awake;
						<>O.<0>__CombatDirector_Awake = val2;
						obj2 = (object)val2;
					}
					CombatDirector.Awake -= (hook_Awake)obj2;
				}
			}
		}

		public bool VarietyEnabled
		{
			[CompilerGenerated]
			get
			{
				return <VarietyEnabled>k__BackingField;
			}
			set
			{
				//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d8: Expected O, but got Unknown
				//IL_002c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0031: Unknown result type (might be due to invalid IL or missing references)
				//IL_0037: Expected O, but got Unknown
				//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f8: Expected O, but got Unknown
				//IL_004c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0051: Unknown result type (might be due to invalid IL or missing references)
				//IL_0057: Expected O, but got Unknown
				//IL_010d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0112: Unknown result type (might be due to invalid IL or missing references)
				//IL_0118: Expected O, but got Unknown
				//IL_006c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0071: Unknown result type (might be due to invalid IL or missing references)
				//IL_0077: Expected O, but got Unknown
				//IL_012d: 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_0138: Expected O, but got Unknown
				//IL_008c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0091: Unknown result type (might be due to invalid IL or missing references)
				//IL_0097: Expected O, but got Unknown
				//IL_014d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0152: Unknown result type (might be due to invalid IL or missing references)
				//IL_0158: Expected O, but got Unknown
				//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b7: Expected O, but got Unknown
				if (<VarietyEnabled>k__BackingField == value)
				{
					return;
				}
				<VarietyEnabled>k__BackingField = value;
				if (<VarietyEnabled>k__BackingField)
				{
					object obj = <>O.<1>__CombatDirector_SetNextSpawnAsBoss;
					if (obj == null)
					{
						hook_SetNextSpawnAsBoss val = CombatDirector_SetNextSpawnAsBoss;
						<>O.<1>__CombatDirector_SetNextSpawnAsBoss = val;
						obj = (object)val;
					}
					CombatDirector.SetNextSpawnAsBoss += (hook_SetNextSpawnAsBoss)obj;
					object obj2 = <>O.<2>__IL_CombatDirector_SetNextSpawnAsBoss;
					if (obj2 == null)
					{
						Manipulator val2 = IL_CombatDirector_SetNextSpawnAsBoss;
						<>O.<2>__IL_CombatDirector_SetNextSpawnAsBoss = val2;
						obj2 = (object)val2;
					}
					CombatDirector.SetNextSpawnAsBoss += (Manipulator)obj2;
					object obj3 = <>O.<3>__CombatDirector_AttemptSpawnOnTarget;
					if (obj3 == null)
					{
						Manipulator val3 = CombatDirector_AttemptSpawnOnTarget;
						<>O.<3>__CombatDirector_AttemptSpawnOnTarget = val3;
						obj3 = (object)val3;
					}
					CombatDirector.AttemptSpawnOnTarget += (Manipulator)obj3;
					object obj4 = <>O.<4>__SendBroadcastChat_ChatMessageBase;
					if (obj4 == null)
					{
						hook_SendBroadcastChat_ChatMessageBase val4 = SendBroadcastChat_ChatMessageBase;
						<>O.<4>__SendBroadcastChat_ChatMessageBase = val4;
						obj4 = (object)val4;
					}
					Chat.SendBroadcastChat_ChatMessageBase += (hook_SendBroadcastChat_ChatMessageBase)obj4;
					object obj5 = <>O.<5>__UpdateBossMemories;
					if (obj5 == null)
					{
						hook_UpdateBossMemories val5 = UpdateBossMemories;
						<>O.<5>__UpdateBossMemories = val5;
						obj5 = (object)val5;
					}
					BossGroup.UpdateBossMemories += (hook_UpdateBossMemories)obj5;
				}
				else
				{
					object obj6 = <>O.<5>__UpdateBossMemories;
					if (obj6 == null)
					{
						hook_UpdateBossMemories val6 = UpdateBossMemories;
						<>O.<5>__UpdateBossMemories = val6;
						obj6 = (object)val6;
					}
					BossGroup.UpdateBossMemories -= (hook_UpdateBossMemories)obj6;
					object obj7 = <>O.<4>__SendBroadcastChat_ChatMessageBase;
					if (obj7 == null)
					{
						hook_SendBroadcastChat_ChatMessageBase val7 = SendBroadcastChat_ChatMessageBase;
						<>O.<4>__SendBroadcastChat_ChatMessageBase = val7;
						obj7 = (object)val7;
					}
					Chat.SendBroadcastChat_ChatMessageBase -= (hook_SendBroadcastChat_ChatMessageBase)obj7;
					object obj8 = <>O.<3>__CombatDirector_AttemptSpawnOnTarget;
					if (obj8 == null)
					{
						Manipulator val8 = CombatDirector_AttemptSpawnOnTarget;
						<>O.<3>__CombatDirector_AttemptSpawnOnTarget = val8;
						obj8 = (object)val8;
					}
					CombatDirector.AttemptSpawnOnTarget -= (Manipulator)obj8;
					object obj9 = <>O.<2>__IL_CombatDirector_SetNextSpawnAsBoss;
					if (obj9 == null)
					{
						Manipulator val9 = IL_CombatDirector_SetNextSpawnAsBoss;
						<>O.<2>__IL_CombatDirector_SetNextSpawnAsBoss = val9;
						obj9 = (object)val9;
					}
					CombatDirector.SetNextSpawnAsBoss -= (Manipulator)obj9;
					object obj10 = <>O.<1>__CombatDirector_SetNextSpawnAsBoss;
					if (obj10 == null)
					{
						hook_SetNextSpawnAsBoss val10 = CombatDirector_SetNextSpawnAsBoss;
						<>O.<1>__CombatDirector_SetNextSpawnAsBoss = val10;
						obj10 = (object)val10;
					}
					CombatDirector.SetNextSpawnAsBoss -= (hook_SetNextSpawnAsBoss)obj10;
				}
			}
		}

		public static DirectorMain Instance { get; private set; }

		internal static void Init()
		{
			if (Instance == null)
			{
				Instance = new DirectorMain();
			}
		}

		public DirectorMain()
		{
			OnSettingChanged(null, null);
			PluginConfig.enableDirectorMain.SettingChanged += OnSettingChanged;
			PluginConfig.enableCreditRefund.SettingChanged += OnSettingChanged;
			PluginConfig.enableSpawnDiversity.SettingChanged += OnSettingChanged;
			PluginConfig.enableBossDiversity.SettingChanged += OnSettingChanged;
			PluginConfig.enableVieldsDiversity.SettingChanged += OnSettingChanged;
		}

		private void OnSettingChanged(object _, EventArgs __)
		{
			RefundEnabled = PluginConfig.enableDirectorMain.Value && PluginConfig.enableCreditRefund.Value;
			VarietyEnabled = PluginConfig.enableDirectorMain.Value && ConfigVarietyEnabled;
		}

		private static void SendBroadcastChat_ChatMessageBase(orig_SendBroadcastChat_ChatMessageBase orig, ChatMessageBase message)
		{
			if (PluginConfig.enableSpawnDiversity.Value)
			{
				SubjectFormatChatMessage val = (SubjectFormatChatMessage)(object)((message is SubjectFormatChatMessage) ? message : null);
				if (val != null && ((SubjectChatMessage)val).baseToken == "SHRINE_COMBAT_USE_MESSAGE")
				{
					string[] paramTokens = val.paramTokens;
					if (paramTokens != null && paramTokens.Length != 0)
					{
						val.paramTokens[0] = Language.GetString("LOGBOOK_CATEGORY_MONSTER").ToLower();
					}
				}
			}
			orig.Invoke(message);
		}

		private static void UpdateBossMemories(orig_UpdateBossMemories orig, BossGroup self)
		{
			orig.Invoke(self);
			if (!PluginConfig.enableBossDiversity.Value)
			{
				return;
			}
			float num = float.MinValue;
			CharacterBody val = null;
			for (int i = 0; i < self.bossMemoryCount; i++)
			{
				ref BossMemory reference = ref self.bossMemories[i];
				if (Object.op_Implicit((Object)(object)reference.cachedBody) && !(reference.lastObservedHealth <= 0f))
				{
					float num2 = reference.maxObservedMaxHealth + 2f * Mathf.Max(0f, reference.maxObservedMaxHealth - reference.lastObservedHealth);
					if (num2 > num)
					{
						num = num2;
						val = reference.cachedBody;
					}
				}
			}
			if (Object.op_Implicit((Object)(object)val))
			{
				string text = val.GetSubtitle();
				if (string.IsNullOrEmpty(text))
				{
					text = Language.GetString("NULL_SUBTITLE");
				}
				self.bestObservedName = Util.GetBestBodyName(((Component)val).gameObject);
				self.bestObservedSubtitle = $"<sprite name=\"CloudLeft\" tint=1> {text} <sprite name=\"CloudRight\" tint=1>";
			}
		}

		private static void CombatDirector_Awake(orig_Awake orig, CombatDirector self)
		{
			orig.Invoke(self);
			if (NetworkServer.active && !((Object)(object)self == (Object)(object)TeleporterInteraction.instance?.bossDirector))
			{
				((UnityEvent<GameObject, CombatDirector>)(object)self.onSpawnedWithDirectorServer).AddListener((UnityAction<GameObject, CombatDirector>)OnSpawnedServer);
			}
		}

		private static void OnSpawnedServer(GameObject masterObject, CombatDirector self)
		{
			CharacterMaster val = (Object.op_Implicit((Object)(object)masterObject) ? masterObject.GetComponent<CharacterMaster>() : null);
			if (!Object.op_Implicit((Object)(object)val) || PluginConfig.creditRefundMultiplier.Value <= 0)
			{
				return;
			}
			val.onBodyDestroyed += delegate(CharacterBody body)
			{
				if (PluginConfig.creditRefundMultiplier.Value > 0 && Object.op_Implicit((Object)(object)self) && ((Behaviour)self).isActiveAndEnabled && self.monsterCredit > 0f)
				{
					float num = body?.cost ?? 0f;
					if (num > 0f)
					{
						CombatDirector obj = self;
						obj.monsterCredit += num * (float)PluginConfig.creditRefundMultiplier.Value * 0.01f;
					}
				}
			};
		}

		private static void CombatDirector_SetNextSpawnAsBoss(orig_SetNextSpawnAsBoss orig, CombatDirector self)
		{
			Run instance = Run.instance;
			int num = ((instance != null) ? instance.participatingPlayerCount : 0);
			if (num > 0)
			{
				num--;
			}
			self.maximumNumberToSpawnBeforeSkipping = PluginConfig.maxBossSpawns.Value + num * (PluginConfig.maxBossSpawns.Value / 4);
			self.skipSpawnIfTooCheap = false;
			orig.Invoke(self);
		}

		private static void IL_CombatDirector_SetNextSpawnAsBoss(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)
			//IL_001a: Expected O, but got Unknown
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			ILCursor val = new ILCursor(il)
			{
				Index = il.Instrs.Count - 1
			};
			if (val.TryGotoPrev((MoveType)0, new Func<Instruction, bool>[1]
			{
				(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt<CombatDirector>(x, "PrepareNewMonsterWave")
			}))
			{
				val.Emit(OpCodes.Ldarg_0);
				val.Emit(OpCodes.Call, (MethodBase)AccessTools.DeclaredMethod(typeof(DirectorMain), "RollForHorde", (Type[])null, (Type[])null));
			}
			else
			{
				Log.Error("IL Hook failed for CombatDirector.SetNextSpawnAsBoss");
			}
		}

		private static void CombatDirector_AttemptSpawnOnTarget(ILContext il)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			ILCursor val = new ILCursor(il);
			if (val.TryGotoNext(new Func<Instruction, bool>[1]
			{
				(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt<CombatDirector>(x, "Spawn")
			}) && val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
			{
				(Instruction x) => ILPatternMatchingExt.MatchStfld<CombatDirector>(x, "consecutiveCheapSkips")
			}))
			{
				val.Emit(OpCodes.Ldarg_0);
				val.Emit(OpCodes.Call, (MethodBase)AccessTools.DeclaredMethod(typeof(DirectorMain), "AttemptSpawnOnTarget", (Type[])null, (Type[])null));
			}
			else
			{
				Log.Error("IL Hook failed for CombatDirector.Simulate");
			}
		}

		public static DirectorCard RollForHorde(DirectorCard selection, CombatDirector self)
		{
			Instance.self = self;
			if (self.rng.RangeInt(0, 100) < PluginConfig.hordeOfManyChance.Value)
			{
				selection = Instance.GetNextSpawnCard(isTeleporterEvent: true, spawnChampion: false) ?? selection;
			}
			Instance.self = null;
			return selection;
		}

		public static void AttemptSpawnOnTarget(CombatDirector self)
		{
			if (Instance.ConfigVarietyEnabled)
			{
				Instance.self = self;
				ArenaMissionController instance = ArenaMissionController.instance;
				if (instance != null && (instance.activeMonsterCards?.Any()).GetValueOrDefault())
				{
					if (PluginConfig.enableVieldsDiversity.Value)
					{
						self.PrepareNewMonsterWave(self.rng.NextElementUniform<DirectorCard>(ArenaMissionController.instance.activeMonsterCards));
					}
				}
				else
				{
					WeightedSelection<DirectorCard> finalMonsterCardsSelection = self.finalMonsterCardsSelection;
					if (finalMonsterCardsSelection != null && finalMonsterCardsSelection.Count > 0 && self.spawnCountInCurrentWave < self.maximumNumberToSpawnBeforeSkipping)
					{
						if ((Object)(object)self == (Object)(object)TeleporterInteraction.instance?.bossDirector)
						{
							if (PluginConfig.enableBossDiversity.Value)
							{
								Instance.SetNextSpawn(isTeleporterEvent: true, IsMonsterChampion(self.currentMonsterCard));
							}
						}
						else if (PluginConfig.enableSpawnDiversity.Value)
						{
							Instance.SetNextSpawn(isTeleporterEvent: false, spawnChampion: false);
						}
					}
				}
			}
			Instance.self = null;
		}

		private static bool IsMonsterChampion(DirectorCard currentMonsterCard)
		{
			bool? obj;
			if (currentMonsterCard == null)
			{
				obj = null;
			}
			else
			{
				SpawnCard spawnCard = currentMonsterCard.GetSpawnCard();
				obj = ((spawnCard != null) ? new bool?(spawnCard.prefab.GetComponent<CharacterMaster>().bodyPrefab.GetComponent<CharacterBody>().isChampion) : null);
			}
			bool? flag = obj;
			return flag.GetValueOrDefault();
		}

		private void SetNextSpawn(bool isTeleporterEvent, bool spawnChampion)
		{
			DirectorCard nextSpawnCard = GetNextSpawnCard(isTeleporterEvent, spawnChampion);
			if (!Object.op_Implicit((Object)(object)((nextSpawnCard != null) ? nextSpawnCard.GetSpawnCard() : null)))
			{
				return;
			}
			EliteTierDef bestEliteTier = GetBestEliteTier(nextSpawnCard);
			EliteDef randomAvailableEliteDef = bestEliteTier.GetRandomAvailableEliteDef(self.rng);
			if (PluginConfig.enableMoreDebugLogs.Value)
			{
				object[] obj = new object[5]
				{
					((Object)self).name,
					null,
					null,
					null,
					null
				};
				DirectorCard currentMonsterCard = self.currentMonsterCard;
				object obj2;
				if (currentMonsterCard == null)
				{
					obj2 = null;
				}
				else
				{
					SpawnCard spawnCard = currentMonsterCard.GetSpawnCard();
					obj2 = ((spawnCard != null) ? ((Object)spawnCard.prefab).name : null);
				}
				if (obj2 == null)
				{
					obj2 = "null";
				}
				obj[1] = obj2;
				obj[2] = self.currentActiveEliteDef?.modifierToken;
				DirectorCard currentMonsterCard2 = self.currentMonsterCard;
				obj[3] = ((currentMonsterCard2 != null) ? new int?(currentMonsterCard2.cost) : null);
				obj[4] = self.currentActiveEliteTier.costMultiplier;
				Log.Debug(string.Format("{0} overriding {1} {2} | {3} * {4}", obj) + $"\r\n\twith {((Object)nextSpawnCard.GetSpawnCard().prefab).name} {randomAvailableEliteDef?.modifierToken} | {nextSpawnCard.cost} * {bestEliteTier.costMultiplier}");
			}
			self.currentMonsterCard = nextSpawnCard;
			self.lastAttemptedMonsterCard = nextSpawnCard;
			self.currentActiveEliteTier = bestEliteTier;
			self.currentActiveEliteDef = randomAvailableEliteDef;
		}

		private DirectorCard GetNextSpawnCard(bool isTeleporterEvent, bool spawnChampion)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			WeightedSelection<DirectorCard> finalMonsterCardsSelection = self.finalMonsterCardsSelection;
			if (finalMonsterCardsSelection != null && finalMonsterCardsSelection.Count == 0)
			{
				return null;
			}
			if (self.HasOverrideBoss() || self.monsterCredit <= 0f)
			{
				return null;
			}
			WeightedSelection<DirectorCard> val = new WeightedSelection<DirectorCard>(8);
			WeightedSelection<DirectorCard> val2 = new WeightedSelection<DirectorCard>(8);
			for (int i = 0; i < self.finalMonsterCardsSelection.Count; i++)
			{
				ChoiceInfo<DirectorCard> choice = self.finalMonsterCardsSelection.GetChoice(i);
				DirectorCard value = choice.value;
				if (value == null || !value.IsAvailable() || !((float)choice.value.cost <= self.monsterCredit))
				{
					continue;
				}
				if (isTeleporterEvent)
				{
					SpawnCard spawnCard = choice.value.GetSpawnCard();
					SpawnCard obj = ((spawnCard is CharacterSpawnCard) ? spawnCard : null);
					if (obj == null || ((CharacterSpawnCard)obj).forbiddenAsBoss || spawnChampion != IsMonsterChampion(choice.value))
					{
						continue;
					}
				}
				EliteTierDef bestEliteTier = GetBestEliteTier(choice.value);
				if (self.skipSpawnIfTooCheap && self.consecutiveCheapSkips < self.maxConsecutiveCheapSkips)
				{
					float num = bestEliteTier.costMultiplier * (float)choice.value.cost;
					if (num * (float)self.maximumNumberToSpawnBeforeSkipping < self.monsterCredit && num < (float)self.mostExpensiveMonsterCostInDeck)
					{
						continue;
					}
				}
				val.AddChoice(choice);
				if (self.currentActiveEliteTier == CombatDirector.eliteTiers[0] || bestEliteTier != CombatDirector.eliteTiers[0])
				{
					val2.AddChoice(choice);
				}
			}
			if (val2.Count > 0)
			{
				return val2.Evaluate(self.rng.nextNormalizedFloat);
			}
			if (val.Count > 0)
			{
				return val.Evaluate(self.rng.nextNormalizedFloat);
			}
			return null;
		}

		private EliteTierDef GetBestEliteTier(DirectorCard nextMonsterCard)
		{
			//IL_0019: 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)
			EliteTierDef result = CombatDirector.eliteTiers[0];
			for (int i = 0; i < CombatDirector.eliteTiers.Length; i++)
			{
				if (CombatDirector.eliteTiers[i].CanSelect(nextMonsterCard.GetSpawnCard().eliteRules))
				{
					result = CombatDirector.eliteTiers[i];
					break;
				}
			}
			SpawnCard spawnCard = nextMonsterCard.GetSpawnCard();
			if (!((CharacterSpawnCard)((spawnCard is CharacterSpawnCard) ? spawnCard : null)).noElites)
			{
				for (int j = 1; j < CombatDirector.eliteTiers.Length; j++)
				{
					EliteTierDef val = CombatDirector.eliteTiers[j];
					if (val.CanSelect(nextMonsterCard.GetSpawnCard().eliteRules) && (float)nextMonsterCard.cost * val.costMultiplier <= self.monsterCredit)
					{
						result = val;
					}
				}
			}
			return result;
		}
	}
	public class DirectorTweaks : MonoBehaviour
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static hook_Awake <0>__CombatDirector_Awake;
		}

		private static bool _enabled;

		private CombatDirector _director;

		private bool eventHandlersSet;

		private bool isFastDirector;

		private int _vanillaMaxSpawns;

		private int _vanillaMaxCheapSkips;

		private float _vanillaMinSpawnInterval;

		private float _vanillaMaxSpawnInterval;

		private float _internalCreditMult;

		private float _internalSpawnDistMult;

		public static bool ModuleEnabled
		{
			get
			{
				return _enabled;
			}
			set
			{
				if (value != _enabled)
				{
					_enabled = value;
					DirectorTweaks.onEnabledChanged?.Invoke(_enabled);
				}
			}
		}

		private static event Action<bool> onEnabledChanged;

		public static void Init()
		{
			//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>__CombatDirector_Awake;
			if (obj == null)
			{
				hook_Awake val = CombatDirector_Awake;
				<>O.<0>__CombatDirector_Awake = val;
				obj = (object)val;
			}
			CombatDirector.Awake += (hook_Awake)obj;
			_enabled = PluginConfig.enableDirectorTweaks.Value;
			PluginConfig.enableDirectorTweaks.SettingChanged += delegate
			{
				ModuleEnabled = PluginConfig.enableDirectorTweaks.Value;
			};
		}

		private static void CombatDirector_Awake(orig_Awake orig, CombatDirector self)
		{
			if (NetworkServer.active)
			{
				((Component)self).gameObject.AddComponent<DirectorTweaks>().SetDirector(self);
			}
			orig.Invoke(self);
		}

		private void SetDirector(CombatDirector director)
		{
			if (PluginConfig.enableDebugLogs.Value)
			{
				CombatDirector.cvDirectorCombatEnableInternalLogs.SetBool(true);
			}
			_director = director;
			_vanillaMaxSpawns = _director.maximumNumberToSpawnBeforeSkipping;
			_vanillaMaxCheapSkips = _director.maxConsecutiveCheapSkips;
			_vanillaMinSpawnInterval = _director.minRerollSpawnInterval;
			_vanillaMaxSpawnInterval = _director.maxRerollSpawnInterval;
			isFastDirector = true;
			if (_vanillaMinSpawnInterval != _vanillaMaxSpawnInterval && _vanillaMinSpawnInterval > 5f)
			{
				DirectorTweaks[] components = ((Component)this).GetComponents<DirectorTweaks>();
				foreach (DirectorTweaks directorTweaks in components)
				{
					if ((Object)(object)directorTweaks == (Object)(object)this || !Object.op_Implicit((Object)(object)directorTweaks._director))
					{
						continue;
					}
					if (directorTweaks._vanillaMinSpawnInterval >= _vanillaMinSpawnInterval)
					{
						isFastDirector = true;
						break;
					}
					if (directorTweaks._vanillaMinSpawnInterval < _vanillaMinSpawnInterval)
					{
						isFastDirector = false;
						if (!directorTweaks.isFastDirector)
						{
							Log.Info("Resetting sibling from " + ((Object)((Component)this).gameObject).name);
							directorTweaks.isFastDirector = true;
							directorTweaks.OverwriteSpawnInterval_SettingChanged();
						}
					}
				}
			}
			SetEventHandlers(ModuleEnabled);
			onEnabledChanged += SetEventHandlers;
		}

		private void SetEventHandlers(bool newEnabled)
		{
			if (newEnabled != eventHandlersSet)
			{
				eventHandlersSet = newEnabled;
				if (eventHandlersSet)
				{
					PluginConfig.useRecommendedValues.SettingChanged += OnSettingValuesChanged;
					PluginConfig.creditMultiplier.SettingChanged += CreditMultiplier_SettingChanged;
					PluginConfig.spawnDistanceMultiplier.SettingChanged += SpawnDistanceMultiplier_SettingChanged;
					PluginConfig.useSlowDirector.SettingChanged += OverwriteSpawnInterval_SettingChanged;
					PluginConfig.spawnIntervalVariance.SettingChanged += OverwriteSpawnInterval_SettingChanged;
					PluginConfig.fastSpawnInterval.SettingChanged += OverwriteSpawnInterval_SettingChanged;
					PluginConfig.slowSpawnInterval.SettingChanged += OverwriteSpawnInterval_SettingChanged;
					PluginConfig.maximumNumberToSpawnBeforeSkipping.SettingChanged += MaximumNumberToSpawnBeforeSkipping_SettingChanged;
					PluginConfig.maxConsecutiveCheapSkips.SettingChanged += MaxConsecutiveCheapSkips_SettingChanged;
				}
				else
				{
					PluginConfig.useRecommendedValues.SettingChanged -= OnSettingValuesChanged;
					PluginConfig.creditMultiplier.SettingChanged -= CreditMultiplier_SettingChanged;
					PluginConfig.spawnDistanceMultiplier.SettingChanged -= SpawnDistanceMultiplier_SettingChanged;
					PluginConfig.useSlowDirector.SettingChanged -= OverwriteSpawnInterval_SettingChanged;
					PluginConfig.spawnIntervalVariance.SettingChanged -= OverwriteSpawnInterval_SettingChanged;
					PluginConfig.fastSpawnInterval.SettingChanged -= OverwriteSpawnInterval_SettingChanged;
					PluginConfig.slowSpawnInterval.SettingChanged -= OverwriteSpawnInterval_SettingChanged;
					PluginConfig.maximumNumberToSpawnBeforeSkipping.SettingChanged -= MaximumNumberToSpawnBeforeSkipping_SettingChanged;
					PluginConfig.maxConsecutiveCheapSkips.SettingChanged -= MaxConsecutiveCheapSkips_SettingChanged;
				}
				OnSettingValuesChanged();
			}
		}

		private void OnSettingValuesChanged(object _ = null, EventArgs __ = null)
		{
			CreditMultiplier_SettingChanged();
			SpawnDistanceMultiplier_SettingChanged();
			OverwriteSpawnInterval_SettingChanged();
			MaximumNumberToSpawnBeforeSkipping_SettingChanged();
			MaxConsecutiveCheapSkips_SettingChanged();
		}

		private void CreditMultiplier_SettingChanged(object _ = null, EventArgs __ = null)
		{
			float valueOrDefault = PluginConfig.creditMultiplier.GetValueOrDefault<float>();
			float creditMultiplier = _director.creditMultiplier;
			if (valueOrDefault != _internalCreditMult)
			{
				if (_internalCreditMult > 0f)
				{
					CombatDirector director = _director;
					director.creditMultiplier /= _internalCreditMult;
				}
				_internalCreditMult = valueOrDefault;
				if (_internalCreditMult > 0f)
				{
					CombatDirector director2 = _director;
					director2.creditMultiplier *= _internalCreditMult;
				}
			}
			if (PluginConfig.enableMoreDebugLogs.Value && creditMultiplier != _director.creditMultiplier)
			{
				Log.Debug(((Object)((Component)this).gameObject).name + " | creditMult\r\n\tprv: " + creditMultiplier + "\r\n\tnew: " + _director.creditMultiplier);
			}
		}

		private void SpawnDistanceMultiplier_SettingChanged(object _ = null, EventArgs __ = null)
		{
			float valueOrDefault = PluginConfig.spawnDistanceMultiplier.GetValueOrDefault<float>();
			float spawnDistanceMultiplier = _director.spawnDistanceMultiplier;
			if (valueOrDefault != _internalSpawnDistMult)
			{
				if (_internalSpawnDistMult > 0f)
				{
					CombatDirector director = _director;
					director.spawnDistanceMultiplier /= _internalSpawnDistMult;
				}
				_internalSpawnDistMult = valueOrDefault;
				if (_internalSpawnDistMult > 0f)
				{
					CombatDirector director2 = _director;
					director2.spawnDistanceMultiplier *= _internalSpawnDistMult;
				}
			}
			if (PluginConfig.enableMoreDebugLogs.Value && spawnDistanceMultiplier != _director.spawnDistanceMultiplier)
			{
				Log.Debug(((Object)((Component)this).gameObject).name + " | spawnMult\r\n\tprv: " + spawnDistanceMultiplier + "\r\n\tnew: " + _director.spawnDistanceMultiplier);
			}
		}

		private void OverwriteSpawnInterval_SettingChanged(object _ = null, EventArgs __ = null)
		{
			if (_vanillaMinSpawnInterval == _vanillaMaxSpawnInterval)
			{
				Log.Info(((Object)((Component)this).gameObject).name + " Intervals " + _vanillaMaxSpawnInterval + " are equal, skipping special director.");
				return;
			}
			float num = _vanillaMinSpawnInterval;
			float num2 = _vanillaMaxSpawnInterval;
			float valueOrDefault = PluginConfig.fastSpawnInterval.GetValueOrDefault<float>();
			float valueOrDefault2 = PluginConfig.slowSpawnInterval.GetValueOrDefault<float>();
			float valueOrDefault3 = PluginConfig.spawnIntervalVariance.GetValueOrDefault<float>();
			if (valueOrDefault < 0f || valueOrDefault2 < 0f || valueOrDefault3 < 1f)
			{
				Log.Info(((Object)((Component)this).gameObject).name + " resetting to vanilla spawn timers due to invalid config value");
			}
			else
			{
				num = ((!isFastDirector && PluginConfig.useSlowDirector.GetValueOrDefault<bool>()) ? valueOrDefault2 : valueOrDefault);
				num2 = num * valueOrDefault3;
			}
			if (_director.minRerollSpawnInterval != num || _director.maxRerollSpawnInterval != num2)
			{
				if (PluginConfig.enableMoreDebugLogs.Value)
				{
					Log.Debug(((Object)((Component)this).gameObject).name + " | spawnInterval\r\n\tprv: " + _director.minRerollSpawnInterval + " and " + _director.maxRerollSpawnInterval + "\r\n\tnew: " + num + " and " + num2);
				}
				_director.minRerollSpawnInterval = num;
				_director.maxRerollSpawnInterval = num2;
			}
		}

		private void MaximumNumberToSpawnBeforeSkipping_SettingChanged(object _ = null, EventArgs __ = null)
		{
			int num = PluginConfig.maximumNumberToSpawnBeforeSkipping.GetValueOrDefault<int>();
			if (num <= 0)
			{
				num = _vanillaMaxSpawns;
			}
			if (_director.maximumNumberToSpawnBeforeSkipping != num)
			{
				if (PluginConfig.enableMoreDebugLogs.Value)
				{
					Log.Debug(((Object)((Component)this).gameObject).name + " | maxBeforeSkip\r\n\tprv: " + _director.maximumNumberToSpawnBeforeSkipping + "\r\n\tnew: " + num);
				}
				_director.maximumNumberToSpawnBeforeSkipping = num;
			}
		}

		private void MaxConsecutiveCheapSkips_SettingChanged(object _ = null, EventArgs __ = null)
		{
			int num = PluginConfig.maxConsecutiveCheapSkips.GetValueOrDefault<int>();
			if (num <= 0)
			{
				num = _vanillaMaxCheapSkips;
			}
			if (_director.maxConsecutiveCheapSkips != num)
			{
				if (PluginConfig.enableMoreDebugLogs.Value)
				{
					Log.Debug(((Object)((Component)this).gameObject).name + " | maxConsecutiveSkips\r\n\tprv: " + _director.maxConsecutiveCheapSkips + "\r\n\tnew: " + num);
				}
				_director.maxConsecutiveCheapSkips = num;
			}
		}
	}
	public class ScalingTweaks
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static Manipulator <0>__Run_RecalculateDifficultyCoefficentInternal;

			public static Func<int, float, float> <1>__GetStageMultiplier;
		}

		private bool linearScaling;

		private bool rampTyphoonCredits;

		public static ScalingTweaks Instance { get; private set; }

		public static void Init()
		{
			if (Instance == null)
			{
				Instance = new ScalingTweaks();
			}
		}

		public ScalingTweaks()
		{
			OnSettingChanged(null, null);
			PluginConfig.enableScalingTweaks.SettingChanged += OnSettingChanged;
			PluginConfig.enableLinearScaling.SettingChanged += OnSettingChanged;
			PluginConfig.rampTyphoonCredits.SettingChanged += OnSettingChanged;
		}

		public void OnSettingChanged(object sender, EventArgs a)
		{
			bool value = PluginConfig.enableScalingTweaks.Value;
			ApplyLinearScaling(value && PluginConfig.enableLinearScaling.Value);
			ApplyTyphoonRamp(value && PluginConfig.rampTyphoonCredits.Value);
		}

		private void ApplyLinearScaling(bool enabled)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			//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)
			//IL_002e: Expected O, but got Unknown
			if (linearScaling == enabled)
			{
				return;
			}
			linearScaling = enabled;
			if (enabled)
			{
				object obj = <>O.<0>__Run_RecalculateDifficultyCoefficentInternal;
				if (obj == null)
				{
					Manipulator val = Run_RecalculateDifficultyCoefficentInternal;
					<>O.<0>__Run_RecalculateDifficultyCoefficentInternal = val;
					obj = (object)val;
				}
				Run.RecalculateDifficultyCoefficentInternal += (Manipulator)obj;
			}
			else
			{
				object obj2 = <>O.<0>__Run_RecalculateDifficultyCoefficentInternal;
				if (obj2 == null)
				{
					Manipulator val2 = Run_RecalculateDifficultyCoefficentInternal;
					<>O.<0>__Run_RecalculateDifficultyCoefficentInternal = val2;
					obj2 = (object)val2;
				}
				Run.RecalculateDifficultyCoefficentInternal -= (Manipulator)obj2;
			}
		}

		private void ApplyTyphoonRamp(bool enabled)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			if (rampTyphoonCredits != enabled)
			{
				rampTyphoonCredits = enabled;
				if (enabled)
				{
					CombatDirector.OnEnable += new hook_OnEnable(CombatDirector_OnEnable);
				}
				else
				{
					CombatDirector.OnEnable -= new hook_OnEnable(CombatDirector_OnEnable);
				}
			}
		}

		private void CombatDirector_OnEnable(orig_OnEnable orig, CombatDirector self)
		{
			orig.Invoke(self);
			if (NetworkServer.active && Object.op_Implicit((Object)(object)Run.instance))
			{
				self.creditMultiplier = GetNewCreditMultiplier(self.creditMultiplier);
				for (int i = 0; i < self.moneyWaves.Length; i++)
				{
					self.moneyWaves[i].multiplier = GetNewCreditMultiplier(self.moneyWaves[i].multiplier);
				}
			}
		}

		private float GetNewCreditMultiplier(float creditMultiplier)
		{
			if ((creditMultiplier < 1.3f || creditMultiplier > 2f) ? true : false)
			{
				return creditMultiplier;
			}
			float num = (creditMultiplier - 1f) / 2f;
			float num2 = (float)Run.instance.stageClearCount * num / 3f;
			float num3 = Mathf.Clamp(1f + num + num2, 1f, creditMultiplier);
			Log.Info($"Reducing credit multiplier from {creditMultiplier} to {num3}");
			return num3;
		}

		private static void Run_RecalculateDifficultyCoefficentInternal(ILContext il)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Expected O, but got Unknown
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			ILCursor val = new ILCursor(il);
			int stageMultLoc = 0;
			if (val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[4]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 0),
				(Instruction x) => ILPatternMatchingExt.MatchLdfld<Run>(x, "stageClearCount"),
				(Instruction x) => ILPatternMatchingExt.MatchConvR4(x),
				(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt<Mathf>(x, "Pow")
			}) && val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
			{
				(Instruction x) => ILPatternMatchingExt.MatchStloc(x, ref stageMultLoc)
			}))
			{
				val.Emit(OpCodes.Ldarg_0);
				val.Emit<Run>(OpCodes.Ldfld, "stageClearCount");
				val.Emit(OpCodes.Ldloc, stageMultLoc);
				val.EmitDelegate<Func<int, float, float>>((Func<int, float, float>)GetStageMultiplier);
				val.Emit(OpCodes.Stloc, stageMultLoc);
			}
			else
			{
				Log.Error("IL Hook failed for Run.RecalculateDifficultyCoefficentInternal");
			}
		}

		public static float GetStageMultiplier(int stageClearCount, float currentScaling)
		{
			float num = 1f + PluginConfig.linearScalingMultiplier.Value * (float)stageClearCount;
			return Mathf.Max(currentScaling, num);
		}
	}
}
namespace DirectorRework.Cruelty
{
	public class CombatCruelty
	{
		public static CombatCruelty Instance { get; private set; }

		public static void Init()
		{
			if (Instance == null)
			{
				Instance = new CombatCruelty();
			}
		}

		public void CombatDirector_Awake(orig_Awake orig, CombatDirector self)
		{
			orig.Invoke(self);
			if (NetworkServer.active)
			{
				((UnityEvent<GameObject, CombatDirector>)(object)self.onSpawnedWithDirectorServer).AddListener((UnityAction<GameObject, CombatDirector>)OnSpawnedServer);
			}
		}

		private void OnSpawnedServer(GameObject masterObject, CombatDirector self)
		{
			CharacterMaster val = default(CharacterMaster);
			if (!PluginConfig.enableCruelty.Value || !Util.CheckRoll((float)PluginConfig.triggerChance.Value, 0f, (CharacterMaster)null) || !Object.op_Implicit((Object)(object)self) || self.currentMonsterCard == null || self.rng == null || !Object.op_Implicit((Object)(object)masterObject) || !masterObject.TryGetComponent<CharacterMaster>(ref val) || !Object.op_Implicit((Object)(object)val.inventory) || val.inventory.GetItemCountEffective(Items.HealthDecay) != 0)
			{
				return;
			}
			CharacterBody body = val.GetBody();
			if (Object.op_Implicit((Object)(object)body) && (PluginConfig.allowBosses.Value || (!val.isBoss && !body.isChampion)))
			{
				bool flag = body.eliteBuffCount > 0 || (PluginConfig.bossesAreElite.Value && (val.isBoss || body.isChampion));
				if (!PluginConfig.onlyApplyToElites.Value || flag)
				{
					AddEliteBuffs(self, body, val.inventory);
				}
			}
		}

		private void AddEliteBuffs(CombatDirector director, CharacterBody body, Inventory inventory)
		{
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			List<BuffIndex> list = CollectionPool<BuffIndex, List<BuffIndex>>.RentCollection();
			if (body.eliteBuffCount > 0)
			{
				for (int i = 0; i < body.activeBuffsListCount; i++)
				{
					BuffDef buffDef = BuffCatalog.GetBuffDef(body.activeBuffsList[i]);
					if (((buffDef != null) ? new bool?(buffDef.isElite) : null) ?? false)
					{
						list.Add(body.activeBuffsList[i]);
					}
				}
			}
			uint xp = 0u;
			uint gold = 0u;
			DeathRewards component = ((Component)body).GetComponent<DeathRewards>();
			if (Object.op_Implicit((Object)(object)component))
			{
				xp = component.expReward;
				gold = component.goldReward;
			}
			EliteDef result;
			float cost;
			while (director.monsterCredit > 0f && list.Count < PluginConfig.maxAffixes.Value && GetRandom(director, list, out result, out cost))
			{
				list.Add(result.eliteEquipmentDef.passiveBuffDef.buffIndex);
				director.monsterCredit -= cost;
				body.cost += cost;
				if (PluginConfig.enableMoreDebugLogs.Value)
				{
					Log.Debug($"NORMAL {body}  |  isBoss? {body.isBoss} isChamp? {body.isChampion}  |   affix #{list.Count} - {result.modifierToken}");
				}
				CrueltyManager.Instance.GiveAffix(body, inventory, result.eliteEquipmentDef);
				if (PluginConfig.bossesGetStats.Value || (!body.isChampion && !body.isBoss))
				{
					if (PluginConfig.enableMoreDebugLogs.Value)
					{
						CrueltyManager.Instance.GiveItemBoostsVerbose(inventory, result, list.Count);
					}
					else
					{
						CrueltyManager.Instance.GiveItemBoosts(inventory, result, list.Count);
					}
				}
				CrueltyManager.Instance.GiveDeathReward(component, xp, gold, list.Count);
				if (!Util.CheckRoll((float)PluginConfig.successChance.Value, 0f, (CharacterMaster)null))
				{
					break;
				}
			}
			CollectionPool<BuffIndex, List<BuffIndex>>.ReturnCollection(list);
		}

		private bool GetRandom(CombatDirector director, List<BuffIndex> currentBuffs, out EliteDef result, out float cost)
		{
			result = null;
			cost = 0f;
			int num = director.currentMonsterCard.cost / (currentBuffs.Count + 1);
			List<EliteDef> list = CollectionPool<EliteDef, List<EliteDef>>.RentCollection();
			List<float> list2 = CollectionPool<float, List<float>>.RentCollection();
			for (int i = 0; i < CombatDirector.eliteTiers.Length; i++)
			{
				EliteTierDef val = CombatDirector.eliteTiers[i];
				if (!CrueltyManager.Instance.IsTierAvailable(val) || !CrueltyManager.Instance.IsTierAffordable(val, director.currentMonsterCard, num, director.monsterCredit))
				{
					continue;
				}
				for (int j = 0; j < val.eliteTypes.Length; j++)
				{
					EliteDef val2 = val.eliteTypes[j];
					if (CrueltyManager.Instance.IsEliteDefValid(val2, currentBuffs))
					{
						list.Add(val2);
						list2.Add(val.costMultiplier);
					}
				}
			}
			if (list.Count > 0)
			{
				int index = director.rng.RangeInt(0, list.Count);
				result = list[index];
				cost = list2[index] * (float)num;
			}
			CollectionPool<EliteDef, List<EliteDef>>.ReturnCollection(list);
			CollectionPool<float, List<float>>.ReturnCollection(list2);
			return result != null;
		}
	}
	public class ScriptedCruelty
	{
		public static ScriptedCruelty Instance { get; private set; }

		public static void Init()
		{
			if (Instance == null)
			{
				Instance = new ScriptedCruelty();
			}
		}

		public void ScriptedCombatEncounter_Awake(orig_Awake orig, ScriptedCombatEncounter self)
		{
			orig.Invoke(self);
			Xoroshiro128Plus rng;
			if (NetworkServer.active && Object.op_Implicit((Object)(object)self.combatSquad))
			{
				rng = self.rng;
				self.combatSquad.onMemberAddedServer += OnMemberAddedServer;
			}
			void OnMemberAddedServer(CharacterMaster master)
			{
				if (PluginConfig.enableCruelty.Value)
				{
					CharacterBody val = (Object.op_Implicit((Object)(object)master) ? master.GetBody() : null);
					if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)master.inventory) && master.inventory.GetItemCountEffective(Items.HealthDecay) <= 0 && (PluginConfig.guaranteeSpecialBoss.Value || (Util.CheckRoll((float)PluginConfig.triggerChance.Value, 0f, (CharacterMaster)null) && (PluginConfig.allowBosses.Value || (!master.isBoss && !val.isChampion)))))
					{
						AddEliteBuffs(val, master.inventory, rng);
					}
				}
			}
		}

		private void AddEliteBuffs(CharacterBody body, Inventory inventory, Xoroshiro128Plus rng)
		{
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			List<BuffIndex> list = CollectionPool<BuffIndex, List<BuffIndex>>.RentCollection();
			if (body.eliteBuffCount > 0)
			{
				for (int i = 0; i < body.activeBuffsListCount; i++)
				{
					BuffDef buffDef = BuffCatalog.GetBuffDef(body.activeBuffsList[i]);
					if (((buffDef != null) ? new bool?(buffDef.isElite) : null) ?? false)
					{
						list.Add(body.activeBuffsList[i]);
					}
				}
			}
			uint xp = 0u;
			uint gold = 0u;
			DeathRewards component = ((Component)body).GetComponent<DeathRewards>();
			if (Object.op_Implicit((Object)(object)component))
			{
				xp = component.expReward;
				gold = component.goldReward;
			}
			EliteDef result;
			while (list.Count < PluginConfig.maxScriptedAffixes.Value && GetScriptedRandom(rng, list, out result))
			{
				list.Add(result.eliteEquipmentDef.passiveBuffDef.buffIndex);
				if (PluginConfig.enableMoreDebugLogs.Value)
				{
					Log.Debug($"SCRIPTED {body}  |  isBoss? {body.isBoss} isChamp? {body.isChampion}  |   affix #{list.Count} - {result.modifierToken}");
				}
				CrueltyManager.Instance.GiveAffix(body, inventory, result.eliteEquipmentDef);
				if (PluginConfig.bossesGetStats.Value)
				{
					if (PluginConfig.enableMoreDebugLogs.Value)
					{
						CrueltyManager.Instance.GiveItemBoostsVerbose(inventory, result, list.Count);
					}
					else
					{
						CrueltyManager.Instance.GiveItemBoosts(inventory, result, list.Count);
					}
				}
				CrueltyManager.Instance.GiveDeathReward(component, xp, gold, list.Count);
				if (!Util.CheckRoll((float)PluginConfig.successChance.Value, 0f, (CharacterMaster)null))
				{
					break;
				}
			}
			CollectionPool<BuffIndex, List<BuffIndex>>.ReturnCollection(list);
		}

		private bool GetScriptedRandom(Xoroshiro128Plus rng, List<BuffIndex> currentBuffs, out EliteDef result)
		{
			result = null;
			List<EliteDef> list = CollectionPool<EliteDef, List<EliteDef>>.RentCollection();
			for (int i = 0; i < CombatDirector.eliteTiers.Length; i++)
			{
				EliteTierDef val = CombatDirector.eliteTiers[i];
				if (!CrueltyManager.Instance.IsTierAvailable(val))
				{
					continue;
				}
				for (int j = 0; j < val.eliteTypes.Length; j++)
				{
					EliteDef val2 = val.eliteTypes[j];
					if (CrueltyManager.Instance.IsEliteDefValid(val2, currentBuffs))
					{
						list.Add(val2);
					}
				}
			}
			if (list.Count > 0)
			{
				result = rng.NextElementUniform<EliteDef>(list);
			}
			CollectionPool<EliteDef, List<EliteDef>>.ReturnCollection(list);
			return result != null;
		}
	}
}