Decompiled source of DirectorReworkPlus v1.1.3

DirectorRework.dll

Decompiled 2 weeks 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.Config;
using DirectorRework.Cruelty;
using DirectorRework.Hooks;
using EntityStates;
using HG;
using HarmonyLib;
using IL.EntityStates.VoidInfestor;
using IL.RoR2;
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+acb3c0d519c760ccde2939b37c4d4ce9b6d469dd")]
[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.1.3")]
	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.1.3";

		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);
			CrueltyManager.Init();
			DirectorMain.Init();
			DirectorTweaks.Init();
		}
	}
	public static class Log
	{
		private static ManualLogSource _logSource;

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

		public static void Debug(string data)
		{
		}

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

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

		public static void Info(string data)
		{
			_logSource.LogInfo((object)data);
		}

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

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

		public static ConfigEntry<bool> info;

		public static ConfigEntry<bool> enableCruelty;

		public static ConfigEntry<bool> enableDirectorMain;

		public static ConfigEntry<bool> enableDirectorTweaks;

		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<int> triggerChance;

		public static ConfigEntry<int> successChance;

		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<bool> useRecommendedValues;

		public static ConfigEntry<float> minRerollSpawnInterval;

		public static ConfigEntry<float> maxRerollSpawnInterval;

		public static ConfigEntry<float> creditMultiplier;

		public static ConfigEntry<float> eliteBias;

		public static ConfigEntry<float> creditMultiplierForEachMountainShrine;

		public static ConfigEntry<float> goldAndExperienceMultiplierForEachMountainShrine;

		public static ConfigEntry<int> maximumNumberToSpawnBeforeSkipping;

		public static ConfigEntry<int> maxConsecutiveCheapSkips;

		public static T GetValue<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();
			}
			string section = "1. Modules";
			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, "!!! Highly recommend to disable/zero out other mods that modify the combat director. Some options will stack exponentially !!!\r\n\r\nEnables 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.");
			section = "2. Affixes/Cruelty";
			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: false, "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: false, "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.");
			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", 20, "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);
			section = "3. Director Main";
			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: false, "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", 10, "Amount to refund the combat director when an enemy is killed, in percent. 100 is a bad idea, but its technically possible.", 0f, 100f);
			section = "Director Tweaks";
			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.");
			creditMultiplier = cfg.BindOptionSlider(section, "Credit Multiplier", 1f, "How much to multiply money wave yield by. Vanilla is 1. \r\n\r\n!!! ITS RECOMMENDED TO SET ALL OTHER MODS TO 1 !!!", 0.1f, 5f);
			eliteBias = cfg.BindOptionSlider(section, "Elite Bias Cost Multiplier", 1f, "Multiplies the elite selection cost. Higher numbers result in higher cost and therefore less elites. Vanilla is 1", 0.1f, 5f);
			minRerollSpawnInterval = cfg.BindOptionSlider(section, "Minimum Reroll Spawn Interval", 4.3333335f, "Used when a spawn is rejected and the director needs to wait to build more credits. Vanilla is 2.33333", 0.1f);
			maxRerollSpawnInterval = cfg.BindOptionSlider(section, "Maximum Reroll Spawn Interval", 6.3333335f, "Used when a spawn is rejected and the director needs to wait to build more credits. Vanilla is 4.33333", 0.1f);
			creditMultiplierForEachMountainShrine = cfg.BindOptionSlider(section, "Credit Multiplier For Each Mountain Shrine", 1f, "Credit multiplier for the teleporter director for each mountain shrine", 0.1f, 5f);
			goldAndExperienceMultiplierForEachMountainShrine = cfg.BindOptionSlider(section, "Gold And Experience Multiplier For Each Mountain Shrine", 1f, "Gold and Exp multiplier for the teleporter director for each mountain shrine. Vanilla is 1", 0.1f, 5f);
			maximumNumberToSpawnBeforeSkipping = cfg.BindOptionSlider(section, "Maximum Number To Spawn Before Skipping", 6, "Maximum number of enemies in a single wave. If the director can afford more than this, it'll reroll the spawncard. Vanilla is 6", 1f);
			maxConsecutiveCheapSkips = cfg.BindOptionSlider(section, "Max Consecutive Cheap Skips", 10, "If skipSpawnIfTooCheap is true, we'll behave as though it's not set after this many consecutive skips. Vanilla is -1", -1f);
		}

		[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.Debug(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_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Expected O, but got Unknown
			bool flag = ((defaultValue is int || defaultValue is float) ? true : false);
			if (flag && !typeof(T).IsEnum)
			{
				return myConfig.BindOptionSlider(section, name, defaultValue, description, 0f, 20f, restartRequired);
			}
			if (string.IsNullOrEmpty(description))
			{
				description = name;
			}
			if (restartRequired)
			{
				description += " (restart required)";
			}
			AcceptableValueBase val = null;
			if (typeof(T).IsEnum)
			{
				val = (AcceptableValueBase)(object)new AcceptableValueList<string>(Enum.GetNames(typeof(T)));
			}
			ConfigEntry<T> val2 = myConfig.Bind<T>(section, name, defaultValue, new ConfigDescription(description, val, Array.Empty<object>()));
			if (DirectorReworkPlugin.RooInstalled)
			{
				TryRegisterOption<T>(val2, restartRequired);
			}
			return val2;
		}

		[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_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Expected O, but got Unknown
			bool flag = ((defaultValue is int || defaultValue is float) ? true : false);
			if (!flag || typeof(T).IsEnum)
			{
				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
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: 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));
			}
			else if (typeof(T).IsEnum)
			{
				ModSettingsManager.AddOption((BaseOption)new ChoiceOption((ConfigEntryBase)(object)entry, 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.Hooks
{
	public class CrueltyManager
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static hook_Awake <0>__CombatDirector_Awake;

			public static hook_Awake <1>__ScriptedCombatEncounter_Awake;

			public static Manipulator <2>__Infest_FixedUpdate;

			public static Manipulator <3>__GlobalEventManager_OnCharacterDeath;
		}

		private HashSet<EquipmentIndex> BlacklistedElites { get; set; } = new HashSet<EquipmentIndex>();


		public static CrueltyManager Instance { get; private set; }

		public bool HooksEnabled { get; set; }

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

		private CrueltyManager()
		{
			RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(OnLoad));
			PluginConfig.enableCruelty.SettingChanged += OnSettingChanged;
			OnSettingChanged(null, null);
		}

		public void OnSettingChanged(object sender, EventArgs args)
		{
			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_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: 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_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_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
			if (!HooksEnabled)
			{
				GlobalEventManager.onCharacterDeathGlobal += GlobalEventManager_onCharacterDeathGlobal;
				object obj = <>O.<0>__CombatDirector_Awake;
				if (obj == null)
				{
					hook_Awake val = CombatCruelty.CombatDirector_Awake;
					<>O.<0>__CombatDirector_Awake = val;
					obj = (object)val;
				}
				CombatDirector.Awake += (hook_Awake)obj;
				object obj2 = <>O.<1>__ScriptedCombatEncounter_Awake;
				if (obj2 == null)
				{
					hook_Awake val2 = ScriptedCruelty.ScriptedCombatEncounter_Awake;
					<>O.<1>__ScriptedCombatEncounter_Awake = val2;
					obj2 = (object)val2;
				}
				ScriptedCombatEncounter.Awake += (hook_Awake)obj2;
				object obj3 = <>O.<2>__Infest_FixedUpdate;
				if (obj3 == null)
				{
					Manipulator val3 = Infest_FixedUpdate;
					<>O.<2>__Infest_FixedUpdate = val3;
					obj3 = (object)val3;
				}
				Infest.FixedUpdate += (Manipulator)obj3;
				object obj4 = <>O.<3>__GlobalEventManager_OnCharacterDeath;
				if (obj4 == null)
				{
					Manipulator val4 = GlobalEventManager_OnCharacterDeath;
					<>O.<3>__GlobalEventManager_OnCharacterDeath = val4;
					obj4 = (object)val4;
				}
				GlobalEventManager.OnCharacterDeath += (Manipulator)obj4;
				HooksEnabled = true;
			}
		}

		public void UnsetHooks()
		{
			//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_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_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_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
			if (HooksEnabled)
			{
				GlobalEventManager.onCharacterDeathGlobal -= GlobalEventManager_onCharacterDeathGlobal;
				object obj = <>O.<0>__CombatDirector_Awake;
				if (obj == null)
				{
					hook_Awake val = CombatCruelty.CombatDirector_Awake;
					<>O.<0>__CombatDirector_Awake = val;
					obj = (object)val;
				}
				CombatDirector.Awake -= (hook_Awake)obj;
				object obj2 = <>O.<1>__ScriptedCombatEncounter_Awake;
				if (obj2 == null)
				{
					hook_Awake val2 = ScriptedCruelty.ScriptedCombatEncounter_Awake;
					<>O.<1>__ScriptedCombatEncounter_Awake = val2;
					obj2 = (object)val2;
				}
				ScriptedCombatEncounter.Awake -= (hook_Awake)obj2;
				object obj3 = <>O.<2>__Infest_FixedUpdate;
				if (obj3 == null)
				{
					Manipulator val3 = Infest_FixedUpdate;
					<>O.<2>__Infest_FixedUpdate = val3;
					obj3 = (object)val3;
				}
				Infest.FixedUpdate -= (Manipulator)obj3;
				object obj4 = <>O.<3>__GlobalEventManager_OnCharacterDeath;
				if (obj4 == null)
				{
					Manipulator val4 = GlobalEventManager_OnCharacterDeath;
					<>O.<3>__GlobalEventManager_OnCharacterDeath = val4;
					obj4 = (object)val4;
				}
				GlobalEventManager.OnCharacterDeath -= (Manipulator)obj4;
				HooksEnabled = false;
			}
		}

		private void OnLoad()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Invalid comparison between Unknown and I4
			//IL_004f: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Invalid comparison between Unknown and I4
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: 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)
			EquipmentIndex val = EquipmentCatalog.FindEquipmentIndex("AffixBlightedMoffein");
			if ((int)val != -1)
			{
				EquipmentDef equipmentDef = EquipmentCatalog.GetEquipmentDef(val);
				if (Object.op_Implicit((Object)(object)equipmentDef) && Object.op_Implicit((Object)(object)equipmentDef.passiveBuffDef) && Object.op_Implicit((Object)(object)equipmentDef.passiveBuffDef.eliteDef))
				{
					BlacklistedElites.Add(val);
				}
			}
			EquipmentIndex val2 = EquipmentCatalog.FindEquipmentIndex("EliteLunarEquipment");
			if ((int)val2 != -1)
			{
				EquipmentDef equipmentDef2 = EquipmentCatalog.GetEquipmentDef(val2);
				if (Object.op_Implicit((Object)(object)equipmentDef2) && Object.op_Implicit((Object)(object)equipmentDef2.passiveBuffDef) && Object.op_Implicit((Object)(object)equipmentDef2.passiveBuffDef.eliteDef))
				{
					BlacklistedElites.Add(val2);
				}
			}
		}

		private void GlobalEventManager_onCharacterDeathGlobal(DamageReport report)
		{
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: 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_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: 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_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			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) || val.GetEquipmentSlotCount() <= 1)
			{
				return;
			}
			float num = (Object.op_Implicit((Object)(object)report.attackerMaster) ? report.attackerMaster.luck : 0f);
			for (uint num2 = 1u; num2 < val.GetEquipmentSlotCount(); num2++)
			{
				EquipmentDef equipmentDef = val.GetEquipment(num2).equipmentDef;
				if (Object.op_Implicit((Object)(object)equipmentDef) && 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;
					PickupDropletController.CreatePickupDroplet(PickupCatalog.FindPickupIndex(equipmentDef.equipmentIndex), ((Ray)(ref val2)).origin, ((Ray)(ref val2)).direction);
				}
			}
		}

		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 source, CharacterBody targetBody)
		{
			//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: Invalid comparison between Unknown and I4
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Invalid comparison between Unknown and I4
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			Inventory val = (Object.op_Implicit((Object)(object)targetBody) ? targetBody.inventory : null);
			if (!Object.op_Implicit((Object)(object)source) || !Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			uint num = 0u;
			for (uint num2 = 0u; num2 <= val.GetEquipmentSlotCount(); num2++)
			{
				if ((int)val.GetEquipment(num2).equipmentIndex == -1)
				{
					num = num2;
					break;
				}
			}
			for (uint num3 = 0u; num3 < source.GetEquipmentSlotCount(); num3++)
			{
				EquipmentDef equipmentDef = source.GetEquipment(num3).equipmentDef;
				if (Object.op_Implicit((Object)(object)equipmentDef) && (int)equipmentDef.equipmentIndex != -1 && Object.op_Implicit((Object)(object)equipmentDef.passiveBuffDef) && equipmentDef.passiveBuffDef.isElite)
				{
					val.SetEquipmentIndexForSlot(equipmentDef.equipmentIndex, num);
					targetBody.AddBuff(equipmentDef.passiveBuffDef);
					num++;
				}
			}
		}

		internal static void GiveAffix(CharacterBody body, Inventory inventory, EquipmentDef equipment)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Invalid comparison between Unknown and I4
			//IL_0038: 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)
			for (uint num = 0u; num <= inventory.GetEquipmentSlotCount(); num++)
			{
				if ((int)inventory.GetEquipment(num).equipmentIndex == -1)
				{
					inventory.SetEquipmentIndexForSlot(equipment.equipmentIndex, num);
					break;
				}
			}
			body.SetBuffCount(equipment.passiveBuffDef.buffIndex, 1);
		}

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

		internal static 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 static bool IsValid(EliteDef ed, List<BuffIndex> currentBuffs)
		{
			//IL_0051: 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)
			if (Object.op_Implicit((Object)(object)ed) && ed.IsAvailable() && Object.op_Implicit((Object)(object)ed.eliteEquipmentDef) && Object.op_Implicit((Object)(object)ed.eliteEquipmentDef.passiveBuffDef) && ed.eliteEquipmentDef.passiveBuffDef.isElite && !Instance.BlacklistedElites.Contains(ed.eliteEquipmentDef.equipmentIndex))
			{
				return !currentBuffs.Contains(ed.eliteEquipmentDef.passiveBuffDef.buffIndex);
			}
			return false;
		}
	}
	internal class DirectorMain
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static Manipulator <0>__CombatDirector_AttemptSpawnOnTarget;

			public static Action<CombatDirector> <1>__Simulate;
		}

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

		public bool HooksEnabled { get; set; }

		public bool RefundEnabled { get; set; }

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

		public static DirectorMain Instance { get; private set; }

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

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

		public void OnSettingChanged(object sender, EventArgs a)
		{
			if (PluginConfig.enableDirectorMain.Value)
			{
				SetHooks();
			}
			else
			{
				UnsetHooks();
			}
		}

		public void SetHooks()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Expected O, but got Unknown
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Expected O, but got Unknown
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Expected O, but got Unknown
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Expected O, but got Unknown
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Expected O, but got Unknown
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Expected O, but got Unknown
			if (!RefundEnabled && PluginConfig.enableCreditRefund.Value)
			{
				CombatDirector.Awake += new hook_Awake(CombatDirector_Awake);
				RefundEnabled = true;
			}
			else if (RefundEnabled && !PluginConfig.enableCreditRefund.Value)
			{
				CombatDirector.Awake -= new hook_Awake(CombatDirector_Awake);
				RefundEnabled = false;
			}
			if (!HooksEnabled && VarietyEnabled)
			{
				object obj = <>O.<0>__CombatDirector_AttemptSpawnOnTarget;
				if (obj == null)
				{
					Manipulator val = CombatDirector_AttemptSpawnOnTarget;
					<>O.<0>__CombatDirector_AttemptSpawnOnTarget = val;
					obj = (object)val;
				}
				CombatDirector.AttemptSpawnOnTarget += (Manipulator)obj;
				Chat.SendBroadcastChat_ChatMessageBase += new hook_SendBroadcastChat_ChatMessageBase(ChangeMessage);
				BossGroup.UpdateBossMemories += new hook_UpdateBossMemories(UpdateTitle);
				HooksEnabled = true;
			}
			else if (HooksEnabled && !VarietyEnabled)
			{
				object obj2 = <>O.<0>__CombatDirector_AttemptSpawnOnTarget;
				if (obj2 == null)
				{
					Manipulator val2 = CombatDirector_AttemptSpawnOnTarget;
					<>O.<0>__CombatDirector_AttemptSpawnOnTarget = val2;
					obj2 = (object)val2;
				}
				CombatDirector.Simulate -= (Manipulator)obj2;
				Chat.SendBroadcastChat_ChatMessageBase -= new hook_SendBroadcastChat_ChatMessageBase(ChangeMessage);
				BossGroup.UpdateBossMemories -= new hook_UpdateBossMemories(UpdateTitle);
				HooksEnabled = false;
			}
		}

		public void UnsetHooks()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: 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_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			if (RefundEnabled)
			{
				CombatDirector.Awake -= new hook_Awake(CombatDirector_Awake);
				RefundEnabled = false;
			}
			if (HooksEnabled)
			{
				object obj = <>O.<0>__CombatDirector_AttemptSpawnOnTarget;
				if (obj == null)
				{
					Manipulator val = CombatDirector_AttemptSpawnOnTarget;
					<>O.<0>__CombatDirector_AttemptSpawnOnTarget = val;
					obj = (object)val;
				}
				CombatDirector.AttemptSpawnOnTarget -= (Manipulator)obj;
				Chat.SendBroadcastChat_ChatMessageBase -= new hook_SendBroadcastChat_ChatMessageBase(ChangeMessage);
				BossGroup.UpdateBossMemories -= new hook_UpdateBossMemories(UpdateTitle);
				HooksEnabled = false;
			}
		}

		private static void CombatDirector_AttemptSpawnOnTarget(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_006d: 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(new Func<Instruction, bool>[2]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdcI4(x, 1),
				(Instruction x) => ILPatternMatchingExt.MatchRet(x)
			}))
			{
				val.Emit(OpCodes.Ldarg_0);
				val.EmitDelegate<Action<CombatDirector>>((Action<CombatDirector>)Simulate);
			}
			else
			{
				Log.Error("IL Hook failed for CombatDirector.Simulate");
			}
		}

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

		private static void SetNextSpawn(CombatDirector self, bool isBoss)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: 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_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			int mostExpensiveMonsterCostInDeck = self.mostExpensiveMonsterCostInDeck;
			bool flag = isBoss && self.currentMonsterCard.spawnCard.prefab.GetComponent<CharacterMaster>().bodyPrefab.GetComponent<CharacterBody>().isChampion;
			WeightedSelection<DirectorCard> val = new WeightedSelection<DirectorCard>(8);
			int i = 0;
			for (int count = self.finalMonsterCardsSelection.Count; i < count; i++)
			{
				ChoiceInfo<DirectorCard> choice = self.finalMonsterCardsSelection.GetChoice(i);
				if (!choice.value.IsAvailable() || !((float)choice.value.cost <= self.monsterCredit))
				{
					continue;
				}
				if (isBoss)
				{
					SpawnCard spawnCard = choice.value.spawnCard;
					bool isChampion = spawnCard.prefab.GetComponent<CharacterMaster>().bodyPrefab.GetComponent<CharacterBody>().isChampion;
					bool flag2 = ((CharacterSpawnCard)(((spawnCard is CharacterSpawnCard) ? spawnCard : null)?)).forbiddenAsBoss ?? false;
					if (isChampion == flag && !flag2 && ValidateBossCard(self, choice.value, mostExpensiveMonsterCostInDeck))
					{
						val.AddChoice(choice);
					}
				}
				else
				{
					val.AddChoice(choice);
				}
			}
			if (val.Count > 0)
			{
				self.currentMonsterCard = val.Evaluate(self.rng.nextNormalizedFloat);
				self.currentActiveEliteTier = GetBestEliteTier(self, self.currentMonsterCard);
				self.currentActiveEliteDef = self.currentActiveEliteTier.GetRandomAvailableEliteDef(self.rng);
				self.lastAttemptedMonsterCard = self.currentMonsterCard;
			}
		}

		private static bool ValidateBossCard(CombatDirector self, DirectorCard spawnCard, int mostExpensive)
		{
			float costMultiplier = GetBestEliteTier(self, spawnCard).costMultiplier;
			int num = spawnCard.cost;
			int num2 = (int)((float)num * costMultiplier);
			if ((float)num2 <= self.monsterCredit)
			{
				num = num2;
			}
			if (self.skipSpawnIfTooCheap && (float)(num * self.maximumNumberToSpawnBeforeSkipping) < self.monsterCredit && mostExpensive > num)
			{
				return false;
			}
			return true;
		}

		private static EliteTierDef GetBestEliteTier(CombatDirector self, DirectorCard currentMonsterCard)
		{
			//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(currentMonsterCard.spawnCard.eliteRules))
				{
					result = CombatDirector.eliteTiers[i];
					break;
				}
			}
			SpawnCard spawnCard = currentMonsterCard.spawnCard;
			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(currentMonsterCard.spawnCard.eliteRules) && (float)currentMonsterCard.cost * val.costMultiplier * self.eliteBias <= self.monsterCredit)
					{
						result = val;
					}
				}
			}
			return result;
		}

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

		private void UpdateTitle(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 + 4f * Mathf.Max(0f, reference.maxObservedMaxHealth - reference.lastObservedHealth);
					if (num2 > num)
					{
						num = num2;
						val = reference.cachedBody;
					}
				}
			}
			if (Object.op_Implicit((Object)(object)val))
			{
				self.bestObservedName = Util.GetBestBodyName(((Component)val).gameObject);
				string text = val.GetSubtitle();
				if (string.IsNullOrEmpty(text))
				{
					text = Language.GetString("NULL_SUBTITLE");
				}
				self.bestObservedSubtitle = $"<sprite name=\"CloudLeft\" tint=1> {text} <sprite name=\"CloudRight\" tint=1>";
			}
		}

		private void CombatDirector_Awake(orig_Awake orig, CombatDirector self)
		{
			orig.Invoke(self);
			if (NetworkServer.active && !((Object)(object)self == (Object)(object)TeleporterInteraction.instance?.bossDirector))
			{
				((UnityEvent<GameObject>)(object)self.onSpawnedServer).AddListener((UnityAction<GameObject>)OnSpawnedServer);
			}
			void OnBodyDestroyed(CharacterBody body)
			{
				if (PluginConfig.creditRefundMultiplier.Value > 0 && Object.op_Implicit((Object)(object)self) && ((Behaviour)self).isActiveAndEnabled && self.monsterCredit > 0f)
				{
					float? num = body?.cost * (float)PluginConfig.creditRefundMultiplier.Value * 0.01f;
					if (num.HasValue)
					{
						CombatDirector obj = self;
						obj.monsterCredit += num.Value;
					}
				}
			}
			void OnSpawnedServer(GameObject masterObject)
			{
				//IL_004d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0053: Invalid comparison between Unknown and I4
				CharacterMaster val = (Object.op_Implicit((Object)(object)masterObject) ? masterObject.GetComponent<CharacterMaster>() : null);
				if (Object.op_Implicit((Object)(object)val))
				{
					CharacterBody body2 = val.GetBody();
					if (Object.op_Implicit((Object)(object)body2) && !body2.isBoss && !body2.isChampion && body2.cost > 0f && (int)body2.teamComponent.teamIndex == 2)
					{
						val.onBodyDestroyed += OnBodyDestroyed;
					}
				}
			}
		}
	}
	internal class DirectorTweaks
	{
		private float prevCreditMult = PluginConfig.creditMultiplier.GetValue<float>();

		private float prevEliteBias = PluginConfig.eliteBias.GetValue<float>();

		public static DirectorTweaks instance;

		public bool HooksEnabled { get; set; }

		public static void Init()
		{
			if (instance == null)
			{
				instance = new DirectorTweaks();
			}
		}

		private DirectorTweaks()
		{
			OnSettingChanged(null, null);
			PluginConfig.enableDirectorTweaks.SettingChanged += OnSettingChanged;
			PluginConfig.useRecommendedValues.SettingChanged += OnSettingValuesChanged;
			PluginConfig.minRerollSpawnInterval.SettingChanged += OnSettingValuesChanged;
			PluginConfig.maxRerollSpawnInterval.SettingChanged += OnSettingValuesChanged;
			PluginConfig.maxConsecutiveCheapSkips.SettingChanged += OnSettingValuesChanged;
			PluginConfig.maximumNumberToSpawnBeforeSkipping.SettingChanged += OnSettingValuesChanged;
			PluginConfig.creditMultiplierForEachMountainShrine.SettingChanged += OnSettingValuesChanged;
			PluginConfig.goldAndExperienceMultiplierForEachMountainShrine.SettingChanged += OnSettingValuesChanged;
			PluginConfig.creditMultiplier.SettingChanged += OnSettingValuesChanged;
			PluginConfig.eliteBias.SettingChanged += OnSettingValuesChanged;
		}

		public void OnSettingChanged(object sender, EventArgs args)
		{
			if (PluginConfig.enableDirectorTweaks.Value)
			{
				SetHooks();
			}
			else
			{
				UnsetHooks();
			}
		}

		public void SetHooks()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			if (!HooksEnabled)
			{
				CombatDirector.Awake += new hook_Awake(CombatDirector_Awake);
				ChargingState.OnEnter += new hook_OnEnter(ChargingState_OnEnter);
				HooksEnabled = true;
			}
		}

		public void UnsetHooks()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			if (HooksEnabled)
			{
				CombatDirector.Awake -= new hook_Awake(CombatDirector_Awake);
				ChargingState.OnEnter -= new hook_OnEnter(ChargingState_OnEnter);
				HooksEnabled = false;
			}
		}

		public void OnSettingValuesChanged(object sender, EventArgs args)
		{
			if (!HooksEnabled)
			{
				return;
			}
			foreach (CombatDirector instances in CombatDirector.instancesList)
			{
				instances.maxConsecutiveCheapSkips = ((PluginConfig.maxConsecutiveCheapSkips.GetValue<int>() <= 0) ? int.MaxValue : PluginConfig.maxConsecutiveCheapSkips.GetValue<int>());
				instances.maximumNumberToSpawnBeforeSkipping = PluginConfig.maximumNumberToSpawnBeforeSkipping.GetValue<int>();
				instances.minRerollSpawnInterval = PluginConfig.minRerollSpawnInterval.GetValue<float>();
				instances.maxRerollSpawnInterval = PluginConfig.maxRerollSpawnInterval.GetValue<float>();
				instances.creditMultiplier /= prevCreditMult;
				instances.creditMultiplier *= PluginConfig.creditMultiplier.GetValue<float>();
				prevCreditMult = PluginConfig.creditMultiplier.GetValue<float>();
				instances.eliteBias /= prevEliteBias;
				instances.eliteBias *= PluginConfig.eliteBias.GetValue<float>();
				prevEliteBias = PluginConfig.eliteBias.GetValue<float>();
			}
		}

		private void CombatDirector_Awake(orig_Awake orig, CombatDirector self)
		{
			self.creditMultiplier *= PluginConfig.creditMultiplier.GetValue<float>();
			self.eliteBias *= PluginConfig.eliteBias.GetValue<float>();
			self.maxConsecutiveCheapSkips = ((PluginConfig.maxConsecutiveCheapSkips.GetValue<int>() <= 0) ? int.MaxValue : PluginConfig.maxConsecutiveCheapSkips.GetValue<int>());
			self.maximumNumberToSpawnBeforeSkipping = PluginConfig.maximumNumberToSpawnBeforeSkipping.GetValue<int>();
			self.minRerollSpawnInterval = PluginConfig.minRerollSpawnInterval.GetValue<float>();
			self.maxRerollSpawnInterval = PluginConfig.maxRerollSpawnInterval.GetValue<float>();
			orig.Invoke(self);
		}

		private void ChargingState_OnEnter(orig_OnEnter orig, BaseState self)
		{
			ChargingState val = (ChargingState)(object)((self is ChargingState) ? self : null);
			if (val != null && Object.op_Implicit((Object)(object)((BaseTeleporterState)val).teleporterInteraction))
			{
				int shrineBonusStacks = ((BaseTeleporterState)val).teleporterInteraction.shrineBonusStacks;
				if (shrineBonusStacks > 0)
				{
					CombatDirector bossDirector = val.bossDirector;
					if (Object.op_Implicit((Object)(object)bossDirector))
					{
						CombatDirector obj = bossDirector;
						obj.creditMultiplier += bossDirector.creditMultiplier * (1f - (float)shrineBonusStacks * PluginConfig.creditMultiplierForEachMountainShrine.GetValue<float>());
						CombatDirector obj2 = bossDirector;
						obj2.expRewardCoefficient += bossDirector.expRewardCoefficient * (1f - (float)shrineBonusStacks * PluginConfig.goldAndExperienceMultiplierForEachMountainShrine.GetValue<float>());
						CombatDirector obj3 = bossDirector;
						obj3.goldRewardCoefficient += bossDirector.goldRewardCoefficient * (1f - (float)shrineBonusStacks * PluginConfig.goldAndExperienceMultiplierForEachMountainShrine.GetValue<float>());
					}
					bossDirector = val.bonusDirector;
					if (Object.op_Implicit((Object)(object)bossDirector))
					{
						CombatDirector obj4 = bossDirector;
						obj4.creditMultiplier += bossDirector.creditMultiplier * (1f - (float)shrineBonusStacks * PluginConfig.creditMultiplierForEachMountainShrine.GetValue<float>());
						CombatDirector obj5 = bossDirector;
						obj5.expRewardCoefficient += bossDirector.expRewardCoefficient * (1f - (float)shrineBonusStacks * PluginConfig.goldAndExperienceMultiplierForEachMountainShrine.GetValue<float>());
						CombatDirector obj6 = bossDirector;
						obj6.goldRewardCoefficient += bossDirector.goldRewardCoefficient * (1f - (float)shrineBonusStacks * PluginConfig.goldAndExperienceMultiplierForEachMountainShrine.GetValue<float>());
					}
				}
			}
			orig.Invoke(self);
		}
	}
}
namespace DirectorRework.Cruelty
{
	public static class CombatCruelty
	{
		public readonly struct EliteWithCost
		{
			public readonly EliteDef eliteDef;

			public readonly float cost;

			public EliteWithCost(EliteDef def, float cost)
			{
				eliteDef = def;
				this.cost = cost;
			}
		}

		public static void CombatDirector_Awake(orig_Awake orig, CombatDirector self)
		{
			orig.Invoke(self);
			if (!NetworkServer.active)
			{
				return;
			}
			((UnityEvent<GameObject>)(object)self.onSpawnedServer).AddListener((UnityAction<GameObject>)delegate(GameObject masterObject)
			{
				if (PluginConfig.enableCruelty.Value && Util.CheckRoll((float)PluginConfig.triggerChance.Value, 0f, (CharacterMaster)null))
				{
					CharacterMaster val = (Object.op_Implicit((Object)(object)masterObject) ? masterObject.GetComponent<CharacterMaster>() : null);
					if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.inventory) && val.inventory.GetItemCount(Items.HealthDecay) <= 0)
					{
						CharacterBody body = val.GetBody();
						if (Object.op_Implicit((Object)(object)body))
						{
							bool flag = val.isBoss || body.isChampion;
							if (!(!PluginConfig.allowBosses.Value && flag))
							{
								bool flag2 = body.eliteBuffCount > 0 || (PluginConfig.bossesAreElite.Value && flag);
								if (!PluginConfig.onlyApplyToElites.Value || flag2)
								{
									OnSpawnedServer(self, body, val.inventory);
								}
							}
						}
					}
				}
			});
		}

		private static void OnSpawnedServer(CombatDirector director, CharacterBody body, Inventory inventory)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: 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_00c8: Unknown result type (might be due to invalid IL or missing references)
			List<BuffIndex> list = CollectionPool<BuffIndex, List<BuffIndex>>.RentCollection();
			BuffIndex[] eliteBuffIndices = BuffCatalog.eliteBuffIndices;
			foreach (BuffIndex val in eliteBuffIndices)
			{
				if (body.HasBuff(val) && !list.Contains(val))
				{
					list.Add(val);
				}
			}
			uint xp = 0u;
			uint gold = 0u;
			DeathRewards val2 = default(DeathRewards);
			if (((Component)body).TryGetComponent<DeathRewards>(ref val2))
			{
				xp = val2.expReward;
				gold = val2.goldReward;
			}
			EliteWithCost result;
			while (director.monsterCredit > 0f && list.Count < PluginConfig.maxAffixes.Value && GetRandom(director.monsterCredit, director.currentMonsterCard, director.rng, list, out result))
			{
				CrueltyManager.GiveAffix(body, inventory, result.eliteDef.eliteEquipmentDef);
				list.Add(result.eliteDef.eliteEquipmentDef.passiveBuffDef.buffIndex);
				int count = list.Count;
				director.monsterCredit -= result.cost;
				body.cost += result.cost;
				CrueltyManager.GiveItemBoosts(inventory, result.eliteDef, count);
				CrueltyManager.GiveDeathReward(val2, xp, gold, count);
				if (!Util.CheckRoll((float)PluginConfig.successChance.Value, 0f, (CharacterMaster)null))
				{
					break;
				}
			}
			CollectionPool<BuffIndex, List<BuffIndex>>.ReturnCollection(list);
		}

		private static bool GetRandom(float availableCredits, DirectorCard card, Xoroshiro128Plus rng, List<BuffIndex> currentBuffs, out EliteWithCost result)
		{
			result = default(EliteWithCost);
			EliteTierDef[] eliteTiers = CombatDirector.eliteTiers;
			if (eliteTiers == null || eliteTiers.Length == 0)
			{
				return false;
			}
			DirectorCard obj = card;
			int cost = ((obj != null) ? obj.cost : 0) / (currentBuffs.Count + 1);
			IEnumerable<EliteWithCost> source = from etd in eliteTiers
				where IsValid(etd, card, cost, availableCredits)
				from ed in etd.eliteTypes
				where CrueltyManager.IsValid(ed, currentBuffs)
				select new EliteWithCost(ed, etd.costMultiplier * (float)cost);
			if (source.Any())
			{
				int index = rng.RangeInt(0, source.Count());
				result = source.ElementAt(index);
				return true;
			}
			return false;
		}

		private static bool IsValid(EliteTierDef etd, DirectorCard card, int cost, float availableCredits)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			if (etd != null && !etd.canSelectWithoutAvailableEliteDef && (!Object.op_Implicit((Object)(object)card?.spawnCard) || etd.CanSelect(card.spawnCard.eliteRules)))
			{
				return availableCredits >= (float)cost * etd.costMultiplier;
			}
			return false;
		}
	}
	public static class ScriptedCruelty
	{
		public static void ScriptedCombatEncounter_Awake(orig_Awake orig, ScriptedCombatEncounter self)
		{
			orig.Invoke(self);
			if (!NetworkServer.active || !Object.op_Implicit((Object)(object)self.combatSquad))
			{
				return;
			}
			Xoroshiro128Plus rng = self.rng;
			self.combatSquad.onMemberAddedServer += delegate(CharacterMaster master)
			{
				if (PluginConfig.enableCruelty.Value && Object.op_Implicit((Object)(object)master) && Object.op_Implicit((Object)(object)master.inventory) && master.inventory.GetItemCount(Items.HealthDecay) <= 0)
				{
					CharacterBody body = master.GetBody();
					if (Object.op_Implicit((Object)(object)body))
					{
						if (!PluginConfig.guaranteeSpecialBoss.Value)
						{
							if (!Util.CheckRoll((float)PluginConfig.triggerChance.Value, 0f, (CharacterMaster)null))
							{
								return;
							}
							bool flag = master.isBoss || body.isChampion;
							if (!PluginConfig.allowBosses.Value && flag)
							{
								return;
							}
						}
						OnMemberAddedServer(body, master.inventory, rng);
					}
				}
			};
		}

		public static void OnMemberAddedServer(CharacterBody body, Inventory inventory, Xoroshiro128Plus rng)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: 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_0097: Unknown result type (might be due to invalid IL or missing references)
			List<BuffIndex> list = CollectionPool<BuffIndex, List<BuffIndex>>.RentCollection();
			BuffIndex[] eliteBuffIndices = BuffCatalog.eliteBuffIndices;
			foreach (BuffIndex val in eliteBuffIndices)
			{
				if (body.HasBuff(val) && !list.Contains(val))
				{
					list.Add(val);
				}
			}
			uint xp = 0u;
			uint gold = 0u;
			DeathRewards val2 = default(DeathRewards);
			if (((Component)body).TryGetComponent<DeathRewards>(ref val2))
			{
				xp = val2.expReward;
				gold = val2.goldReward;
			}
			EliteDef result;
			while (list.Count < PluginConfig.maxScriptedAffixes.Value && GetScriptedRandom(rng, list, out result))
			{
				CrueltyManager.GiveAffix(body, inventory, result.eliteEquipmentDef);
				list.Add(result.eliteEquipmentDef.passiveBuffDef.buffIndex);
				int count = list.Count;
				CrueltyManager.GiveItemBoosts(inventory, result, count);
				CrueltyManager.GiveDeathReward(val2, xp, gold, count);
				if (!Util.CheckRoll((float)PluginConfig.successChance.Value, 0f, (CharacterMaster)null))
				{
					break;
				}
			}
			CollectionPool<BuffIndex, List<BuffIndex>>.ReturnCollection(list);
		}

		private static bool GetScriptedRandom(Xoroshiro128Plus rng, List<BuffIndex> currentBuffs, out EliteDef result)
		{
			result = null;
			EliteTierDef[] eliteTiers = CombatDirector.eliteTiers;
			if (eliteTiers == null || eliteTiers.Length == 0)
			{
				return false;
			}
			IEnumerable<EliteDef> source = from etd in eliteTiers
				where etd != null && !etd.canSelectWithoutAvailableEliteDef
				from ed in etd.eliteTypes
				where CrueltyManager.IsValid(ed, currentBuffs)
				select ed;
			if (source.Any())
			{
				int index = rng.RangeInt(0, source.Count());
				result = source.ElementAt(index);
				return true;
			}
			return false;
		}
	}
}