Decompiled source of ExtractionTweaks v1.2.2

plugins\ExtractionTweaks\ExtractionTweaks.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using Assets.Scripts.EnemyBehaviours;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using DRS.UI;
using HarmonyLib;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("ExtractionTweaks")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.2.2.0")]
[assembly: AssemblyInformationalVersion("1.2.2")]
[assembly: AssemblyProduct("ExtractionTweaks")]
[assembly: AssemblyTitle("ExtractionTweaks")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.2.2.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ExtractionTweaks
{
	internal static class ConfigReload
	{
		private static ConfigFile config;

		private static FileSystemWatcher watcher;

		private static volatile bool pending;

		private static DateTime dueAt;

		public static void Start(ConfigFile cfg)
		{
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Expected O, but got Unknown
			config = cfg;
			try
			{
				watcher = new FileSystemWatcher(Path.GetDirectoryName(cfg.ConfigFilePath), Path.GetFileName(cfg.ConfigFilePath))
				{
					NotifyFilter = (NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite)
				};
				watcher.Changed += delegate
				{
					Queue();
				};
				watcher.Created += delegate
				{
					Queue();
				};
				watcher.Renamed += delegate
				{
					Queue();
				};
				watcher.EnableRaisingEvents = true;
				Plugin.Logger.LogInfo((object)"Watching config file for live changes.");
			}
			catch (Exception ex)
			{
				ManualLogSource logger = Plugin.Logger;
				bool flag = default(bool);
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(32, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Live config reload unavailable: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
				}
				logger.LogWarning(val);
			}
		}

		private static void Queue()
		{
			dueAt = DateTime.UtcNow.AddMilliseconds(300.0);
			pending = true;
		}

		public static void Tick()
		{
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Expected O, but got Unknown
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			if (!pending || DateTime.UtcNow < dueAt)
			{
				return;
			}
			pending = false;
			bool flag = default(bool);
			try
			{
				config.Reload();
				ManualLogSource logger = Plugin.Logger;
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(80, 4, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Config reloaded. KillAll = ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(Plugin.KillAllOnExtraction.Value);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", SpawnsInCountdown = ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(Plugin.AllowSpawnsDuringCountdown.Value);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", PodTimer = ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(Plugin.DropPodTimerSeconds.Value);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("s, PodCondition = ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<DropPodCondition>(Plugin.PodCondition.Value);
				}
				logger.LogInfo(val);
			}
			catch (Exception ex)
			{
				ManualLogSource logger2 = Plugin.Logger;
				BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(39, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Config reload failed (file mid-save?): ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.Message);
				}
				logger2.LogError(val2);
				pending = true;
				dueAt = DateTime.UtcNow.AddSeconds(1.0);
			}
		}
	}
	[BepInPlugin("tobipolar.drgs.extractiontweaks", "Extraction Tweaks", "1.2.2")]
	public class Plugin : BasePlugin
	{
		public const string Guid = "tobipolar.drgs.extractiontweaks";

		public const string Name = "Extraction Tweaks";

		public const string Version = "1.2.2";

		internal static ManualLogSource Logger;

		internal static ConfigEntry<bool> KillAllOnExtraction;

		internal static ConfigEntry<int> DropPodTimerSeconds;

		internal static ConfigEntry<bool> AllowSpawnsDuringCountdown;

		internal static ConfigEntry<DropPodCondition> PodCondition;

		internal static ConfigEntry<int> KillModeSafetySeconds;

		private void MigrateOldConfig(params string[] oldNames)
		{
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Expected O, but got Unknown
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Expected O, but got Unknown
			bool flag = default(bool);
			try
			{
				string configFilePath = ((BasePlugin)this).Config.ConfigFilePath;
				if (File.Exists(configFilePath) && new FileInfo(configFilePath).Length != 0)
				{
					return;
				}
				foreach (string text in oldNames)
				{
					string text2 = Path.Combine(Paths.ConfigPath, text);
					if (File.Exists(text2))
					{
						File.Copy(text2, configFilePath, overwrite: true);
						((BasePlugin)this).Config.Reload();
						ManualLogSource log = ((BasePlugin)this).Log;
						BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(56, 1, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Settings copied from the old ");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(text);
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral(". You can delete that file.");
						}
						log.LogInfo(val);
						break;
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = ((BasePlugin)this).Log;
				BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(28, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Couldn't copy old settings: ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.Message);
				}
				log2.LogWarning(val2);
			}
		}

		public override void Load()
		{
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Expected O, but got Unknown
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Expected O, but got Unknown
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Expected O, but got Unknown
			Logger = ((BasePlugin)this).Log;
			MigrateOldConfig("toby.drgs.extractiontweaks.cfg");
			KillAllOnExtraction = ((BasePlugin)this).Config.Bind<bool>("Extraction", "KillAllBugsWhenPodLands", false, "Kill every enemy on the level the moment the extraction countdown starts.");
			AllowSpawnsDuringCountdown = ((BasePlugin)this).Config.Bind<bool>("Extraction", "AllowSpawnsDuringCountdown", false, "false = no new bugs spawn while the extraction countdown is running. true = vanilla spawning.");
			DropPodTimerSeconds = ((BasePlugin)this).Config.Bind<int>("Extraction", "DropPodTimerSeconds", 180, new ConfigDescription("How long the extraction pod waits for you, in seconds (vanilla is 30). Set to 0 to leave the game's value alone.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 3600), Array.Empty<object>()));
			PodCondition = ((BasePlugin)this).Config.Bind<DropPodCondition>("Drop Pod Condition", "DropPodCondition", DropPodCondition.Vanilla, "When the extraction pod is called.\nVanilla = when the main objective is done.\nKillRemainingEnemies = main objective done, then spawns stop and you must kill every remaining bug (Lootbugs and cocoons don't count).\nAllObjectives = the main objective AND every secondary objective must be done (failed secondaries count as done).");
			KillModeSafetySeconds = ((BasePlugin)this).Config.Bind<int>("Drop Pod Condition", "KillModeSafetySeconds", 0, new ConfigDescription("KillRemainingEnemies only: if the bug count doesn't drop for this many seconds (e.g. a bug stuck in a wall), the pod comes anyway. 0 = never.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 600), Array.Empty<object>()));
			Harmony.CreateAndPatchAll(typeof(Patches), "tobipolar.drgs.extractiontweaks").CreateClassProcessor(typeof(PodHoldPatch)).Patch();
			ConfigReload.Start(((BasePlugin)this).Config);
			ExtractionRunner.Init();
			ManualLogSource logger = Logger;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(73, 6, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("Extraction Tweaks");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("1.2.2");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" loaded. KillAll = ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(KillAllOnExtraction.Value);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", SpawnsInCountdown = ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(AllowSpawnsDuringCountdown.Value);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", PodTimer = ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(DropPodTimerSeconds.Value);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("s, PodCondition = ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<DropPodCondition>(PodCondition.Value);
			}
			logger.LogInfo(val);
		}
	}
	public class ExtractionRunner : MonoBehaviour
	{
		public ExtractionRunner(IntPtr ptr)
			: base(ptr)
		{
		}

		public static void Init()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			//IL_0015: 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_0036: Expected O, but got Unknown
			try
			{
				ClassInjector.RegisterTypeInIl2Cpp<ExtractionRunner>();
				GameObject val = new GameObject("ExtractionTweaks.Runner");
				Object.DontDestroyOnLoad((Object)val);
				((Object)val).hideFlags = (HideFlags)61;
				val.AddComponent<ExtractionRunner>();
			}
			catch (Exception ex)
			{
				ManualLogSource logger = Plugin.Logger;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(39, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Runner setup failed (live config off): ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Exception>(ex);
				}
				logger.LogError(val2);
			}
		}

		private void Update()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			ConfigReload.Tick();
			try
			{
				PodCondition.Tick();
			}
			catch (Exception ex)
			{
				ManualLogSource logger = Plugin.Logger;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(20, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Drop pod condition: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				logger.LogError(val);
			}
		}
	}
	internal static class State
	{
		public static Player Player;

		public static EnemySpawner EnemySpawner;

		public static bool OutOfPod;

		public static bool ExtractionLanded;

		public static void ResetStage()
		{
			OutOfPod = false;
			ExtractionLanded = false;
			PodCondition.ResetStage();
		}

		public static bool Alive(Object o)
		{
			if (o != (Object)null && !((Il2CppObjectBase)o).WasCollected)
			{
				return Object.op_Implicit(o);
			}
			return false;
		}

		public static Player GetPlayer()
		{
			if (Alive((Object)(object)Player))
			{
				return Player;
			}
			try
			{
				Player = Object.FindObjectOfType<Player>();
			}
			catch
			{
				Player = null;
			}
			if (!Alive((Object)(object)Player))
			{
				return null;
			}
			return Player;
		}
	}
	internal static class Extraction
	{
		private static bool loggedOriginalTimer;

		internal static bool InternalDamage;

		public static bool BlockSpawns
		{
			get
			{
				if (!State.ExtractionLanded || Plugin.AllowSpawnsDuringCountdown.Value)
				{
					return PodCondition.BlockSpawns;
				}
				return true;
			}
		}

		public static void ApplyPodTimer(DropPod pod)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			int value = Plugin.DropPodTimerSeconds.Value;
			if (value <= 0 || !State.Alive((Object)(object)pod))
			{
				return;
			}
			if (!loggedOriginalTimer)
			{
				ManualLogSource logger = Plugin.Logger;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(35, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Drop pod timer: game default ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(pod.secondsToTimeOut);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("s -> ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(value);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("s");
				}
				logger.LogInfo(val);
				loggedOriginalTimer = true;
			}
			pod.secondsToTimeOut = value;
		}

		public static void OnCountdownStarted(string source)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			if (!State.ExtractionLanded)
			{
				State.ExtractionLanded = true;
				State.OutOfPod = true;
				ManualLogSource logger = Plugin.Logger;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(32, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Extraction countdown started (");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(source);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(").");
				}
				logger.LogInfo(val);
				if (Plugin.KillAllOnExtraction.Value)
				{
					KillAllEnemies();
				}
			}
		}

		public static EnemySpawner GetEnemySpawner()
		{
			if (State.Alive((Object)(object)State.EnemySpawner))
			{
				return State.EnemySpawner;
			}
			try
			{
				State.EnemySpawner = Object.FindObjectOfType<EnemySpawner>();
			}
			catch
			{
				State.EnemySpawner = null;
			}
			if (!State.Alive((Object)(object)State.EnemySpawner))
			{
				return null;
			}
			return State.EnemySpawner;
		}

		public static List<Enemy> LiveEnemies(out string from)
		{
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Expected O, but got Unknown
			List<Enemy> list = new List<Enemy>();
			from = "none";
			try
			{
				EnemySpawner enemySpawner = GetEnemySpawner();
				List<Enemy> val = ((enemySpawner != null) ? enemySpawner.enemies : null);
				if (val != null && val.Count > 0)
				{
					for (int i = 0; i < val.Count; i++)
					{
						list.Add(val[i]);
					}
					from = "spawner list";
				}
				else
				{
					foreach (Enemy item in Object.FindObjectsOfType<Enemy>())
					{
						list.Add(item);
					}
					from = "scene search";
				}
			}
			catch (Exception ex)
			{
				ManualLogSource logger = Plugin.Logger;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(23, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Couldn't list enemies: ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Exception>(ex);
				}
				logger.LogError(val2);
			}
			list.RemoveAll((Enemy e) => !State.Alive((Object)(object)e) || e.IsDead || !((Component)e).gameObject.activeInHierarchy);
			return list;
		}

		public static long LethalDamage(Enemy enemy)
		{
			try
			{
				double num = ((Entity)enemy).CurrentHP;
				double num2 = 1.0;
				try
				{
					num2 = enemy.DamageTakenMod.Value;
				}
				catch
				{
				}
				if (num2 < 0.2 || num2 > 5.0)
				{
					num2 = 1.0;
				}
				return (long)Math.Ceiling(num / num2 * 1.2) + 1;
			}
			catch
			{
				return 1000000L;
			}
		}

		public static bool Kill(Enemy enemy)
		{
			if (!State.Alive((Object)(object)enemy) || enemy.IsDead)
			{
				return false;
			}
			InternalDamage = true;
			try
			{
				long num = LethalDamage(enemy);
				((Entity)enemy).TakeDamage(num, false, (EDamageType)0, false, (EDamageSource)7, (Entity)null, false);
				if (!enemy.IsDead)
				{
					((Entity)enemy).Die((EDamageType)0, num, false);
				}
			}
			finally
			{
				InternalDamage = false;
			}
			return enemy.IsDead;
		}

		public static void KillAllEnemies(string reason = "extraction")
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Expected O, but got Unknown
			string from;
			List<Enemy> list = LiveEnemies(out from);
			int num = 0;
			int num2 = 0;
			bool flag = default(bool);
			foreach (Enemy item in list)
			{
				try
				{
					if (Kill(item))
					{
						num++;
					}
					else
					{
						num2++;
					}
				}
				catch (Exception ex)
				{
					if (num2++ == 0)
					{
						ManualLogSource logger = Plugin.Logger;
						BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(13, 1, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Kill failed: ");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
						}
						logger.LogError(val);
					}
				}
			}
			ManualLogSource logger2 = Plugin.Logger;
			BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(49, 5, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Kill all [");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(reason);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("] (");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(from);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("): ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(list.Count);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" found, ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(num);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" killed, ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(num2);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" survived/failed");
			}
			logger2.LogInfo(val2);
		}
	}
	[HarmonyPatch]
	internal static class PodHoldPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			MethodInfo[] methods = typeof(DropPod).GetMethods(BindingFlags.Instance | BindingFlags.Public);
			foreach (MethodInfo methodInfo in methods)
			{
				if (methodInfo.Name == "AnimateIn")
				{
					yield return methodInfo;
				}
			}
		}

		private static bool Prefix(DropPod __instance, MethodBase __originalMethod, object[] __args)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			try
			{
				return PodCondition.ShouldRun(__instance, __originalMethod, __args);
			}
			catch (Exception ex)
			{
				ManualLogSource logger = Plugin.Logger;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(20, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Drop pod condition: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				logger.LogError(val);
				return true;
			}
		}
	}
	internal static class Patches
	{
		[HarmonyPatch(typeof(DropPod), "Awake")]
		[HarmonyPrefix]
		private static void DropPodAwake(DropPod __instance)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			try
			{
				Extraction.ApplyPodTimer(__instance);
			}
			catch (Exception ex)
			{
				ManualLogSource logger = Plugin.Logger;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(18, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Pod timer failed: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				logger.LogError(val);
			}
		}

		[HarmonyPatch(typeof(CoreGameEvents), "TriggerStageBegin")]
		[HarmonyPostfix]
		private static void StageBegin()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			State.ResetStage();
			try
			{
				Extraction.ApplyPodTimer(Object.FindObjectOfType<DropPod>());
			}
			catch (Exception ex)
			{
				ManualLogSource logger = Plugin.Logger;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(18, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Pod timer failed: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				logger.LogError(val);
			}
		}

		[HarmonyPatch(typeof(Player), "OnExitDropPod")]
		[HarmonyPostfix]
		private static void PlayerExitDropPod(Player __instance)
		{
			State.Player = __instance;
			State.ResetStage();
			State.OutOfPod = true;
			Plugin.Logger.LogInfo((object)"Stage started (left landing pod).");
		}

		[HarmonyPatch(typeof(CoreGameEvents), "TriggerPlayerEnteredDropPod")]
		[HarmonyPostfix]
		private static void PlayerEnteredDropPod()
		{
			State.ResetStage();
		}

		[HarmonyPatch(typeof(CoreGameEvents), "TriggerDropPodLanded")]
		[HarmonyPostfix]
		private static void DropPodLanded()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			ManualLogSource logger = Plugin.Logger;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(31, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Drop pod landed (out of pod: ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(State.OutOfPod);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(").");
			}
			logger.LogInfo(val);
			if (State.OutOfPod)
			{
				Safe(delegate
				{
					Extraction.OnCountdownStarted("pod landed");
				});
			}
		}

		[HarmonyPatch(typeof(UIDropPodCountdown), "Show")]
		[HarmonyPostfix]
		private static void CountdownShown()
		{
			Safe(delegate
			{
				Extraction.OnCountdownStarted("countdown shown");
			});
		}

		[HarmonyPatch(typeof(EnemySpawner), "SpawnDrip")]
		[HarmonyPrefix]
		private static bool BlockDrip(EnemySpawner __instance)
		{
			State.EnemySpawner = __instance;
			return !Extraction.BlockSpawns;
		}

		[HarmonyPatch(typeof(EnemySpawner), "SpawnWave")]
		[HarmonyPrefix]
		private static bool BlockWave()
		{
			return !Extraction.BlockSpawns;
		}

		private static void Safe(Action a)
		{
			try
			{
				a();
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogError((object)ex.ToString());
			}
		}
	}
	public enum DropPodCondition
	{
		Vanilla,
		KillRemainingEnemies,
		AllObjectives
	}
	internal static class PodCondition
	{
		private static readonly List<(DropPod pod, MethodBase method, object[] args)> Held = new List<(DropPod, MethodBase, object[])>();

		private static bool releasing;

		private static DropPodCondition heldMode;

		private static int lastCount = -1;

		private static float lastProgressAt;

		private static float nextCheck;

		private static LevelObjectiveTracker tracker;

		public static bool Holding => Held.Count > 0;

		public static bool BlockSpawns
		{
			get
			{
				if (Holding)
				{
					return heldMode == DropPodCondition.KillRemainingEnemies;
				}
				return false;
			}
		}

		public static void ResetStage()
		{
			Held.Clear();
			lastCount = -1;
			tracker = null;
			KillCounter.Hide();
		}

		public static bool ShouldRun(DropPod pod, MethodBase method, object[] args)
		{
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Expected O, but got Unknown
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			if (releasing)
			{
				return true;
			}
			if (!State.OutOfPod || State.ExtractionLanded)
			{
				return true;
			}
			DropPodCondition value = Plugin.PodCondition.Value;
			if (value == DropPodCondition.Vanilla)
			{
				return true;
			}
			bool flag = default(bool);
			if (!Holding && ConditionMet(value, out var _))
			{
				ManualLogSource logger = Plugin.Logger;
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(43, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Drop pod called; ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(Describe(value));
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" already, letting it land.");
				}
				logger.LogInfo(val);
				return true;
			}
			if (!Holding)
			{
				heldMode = value;
				lastCount = -1;
				lastProgressAt = Time.time;
				ManualLogSource logger2 = Plugin.Logger;
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(29, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Drop pod called: held until ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(Describe(value));
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(".");
				}
				logger2.LogInfo(val);
			}
			Held.Add((pod, method, (args == null) ? null : ((object[])args.Clone())));
			return false;
		}

		public static void Tick()
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			if (!Holding || Time.unscaledTime < nextCheck)
			{
				return;
			}
			nextCheck = Time.unscaledTime + 0.25f;
			DropPodCondition value = Plugin.PodCondition.Value;
			if (value != heldMode)
			{
				heldMode = value;
				lastCount = -1;
				lastProgressAt = Time.time;
				ManualLogSource logger = Plugin.Logger;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(31, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Drop pod condition changed to ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<DropPodCondition>(value);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(".");
				}
				logger.LogInfo(val);
			}
			int remaining;
			if (value == DropPodCondition.Vanilla)
			{
				Release("condition set to Vanilla");
			}
			else if (ConditionMet(value, out remaining))
			{
				Release(Describe(value) + " done");
			}
			else if (value == DropPodCondition.KillRemainingEnemies)
			{
				if (remaining != lastCount)
				{
					lastCount = remaining;
					lastProgressAt = Time.time;
				}
				int value2 = Plugin.KillModeSafetySeconds.Value;
				float num = Time.time - lastProgressAt;
				if (value2 > 0 && num >= (float)value2)
				{
					Release($"no kills for {value2}s, {remaining} bugs left");
				}
				else
				{
					KillCounter.Show(remaining, (value2 > 0) ? Mathf.CeilToInt((float)value2 - num) : (-1));
				}
			}
			else
			{
				KillCounter.Hide();
			}
		}

		private static bool ConditionMet(DropPodCondition mode, out int remaining)
		{
			remaining = 0;
			switch (mode)
			{
			case DropPodCondition.KillRemainingEnemies:
				remaining = CountTargets();
				return remaining == 0;
			case DropPodCondition.AllObjectives:
				return SecondariesDone();
			default:
				return true;
			}
		}

		private static int CountTargets()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Invalid comparison between Unknown and I4
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Invalid comparison between Unknown and I4
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Invalid comparison between Unknown and I4
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Invalid comparison between Unknown and I4
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Invalid comparison between Unknown and I4
			int num = 0;
			string from;
			foreach (Enemy item in Extraction.LiveEnemies(out from))
			{
				try
				{
					EEnemyType type = item.type;
					if ((int)type != 4 && (int)type != 5)
					{
						EEnemyBehaviourType behaviourType = item.BehaviourType;
						if ((int)behaviourType != 11 && (int)behaviourType != 2 && (int)behaviourType != 10)
						{
							goto IL_004d;
						}
					}
				}
				catch
				{
					goto IL_004d;
				}
				continue;
				IL_004d:
				num++;
			}
			return num;
		}

		private static bool SecondariesDone()
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Expected O, but got Unknown
			try
			{
				if ((Object)(object)tracker == (Object)null || ((Il2CppObjectBase)tracker).WasCollected || !Object.op_Implicit((Object)(object)tracker))
				{
					tracker = Object.FindObjectOfType<LevelObjectiveTracker>();
				}
				LevelObjectiveTracker obj = tracker;
				List<ObjectiveProgress> val = ((obj != null) ? obj.SecondaryObjectives : null);
				if (val == null)
				{
					return true;
				}
				for (int i = 0; i < val.Count; i++)
				{
					ObjectiveProgress val2 = val[i];
					if (val2 != null && !val2.IsComplete && !val2.IsFailed)
					{
						return false;
					}
				}
				return true;
			}
			catch (Exception ex)
			{
				ManualLogSource logger = Plugin.Logger;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val3 = new BepInExErrorLogInterpolatedStringHandler(50, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Secondary objective check failed (releasing pod): ");
					((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<Exception>(ex);
				}
				logger.LogError(val3);
				return true;
			}
		}

		private static void Release(string why)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Expected O, but got Unknown
			KillCounter.Hide();
			List<(DropPod, MethodBase, object[])> list = new List<(DropPod, MethodBase, object[])>(Held);
			Held.Clear();
			ManualLogSource logger = Plugin.Logger;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(21, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Drop pod released (");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(why);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(").");
			}
			logger.LogInfo(val);
			releasing = true;
			try
			{
				foreach (var (val2, methodBase, parameters) in list)
				{
					try
					{
						if ((Object)(object)val2 != (Object)null && !((Il2CppObjectBase)val2).WasCollected && Object.op_Implicit((Object)(object)val2))
						{
							methodBase.Invoke(val2, parameters);
						}
					}
					catch (Exception ex)
					{
						ManualLogSource logger2 = Plugin.Logger;
						BepInExErrorLogInterpolatedStringHandler val3 = new BepInExErrorLogInterpolatedStringHandler(27, 1, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Couldn't release drop pod: ");
							((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<Exception>(ex);
						}
						logger2.LogError(val3);
					}
				}
			}
			finally
			{
				releasing = false;
			}
		}

		private static string Describe(DropPodCondition m)
		{
			return m switch
			{
				DropPodCondition.KillRemainingEnemies => "every bug is dead", 
				DropPodCondition.AllObjectives => "every secondary objective is complete", 
				_ => "vanilla", 
			};
		}
	}
	internal static class KillCounter
	{
		private static GameObject box;

		private static TMP_Text text;

		private static string lastText;

		public static void Show(int remaining, int safetySecondsLeft)
		{
			if ((Object)(object)box == (Object)null || ((Il2CppObjectBase)box).WasCollected || !Object.op_Implicit((Object)(object)box))
			{
				box = null;
				Create();
			}
			if (!((Object)(object)box == (Object)null))
			{
				if (!box.activeSelf)
				{
					box.SetActive(true);
				}
				string text = $"<size=50%>BUGS REMAINING</size>  {remaining}";
				if (safetySecondsLeft >= 0 && safetySecondsLeft <= 15)
				{
					text += $"\n<size=40%>pod arrives anyway in {safetySecondsLeft}s</size>";
				}
				if (text != lastText)
				{
					lastText = text;
					KillCounter.text.text = text;
				}
			}
		}

		public static void Hide()
		{
			if ((Object)(object)box != (Object)null && !((Il2CppObjectBase)box).WasCollected && Object.op_Implicit((Object)(object)box))
			{
				Object.Destroy((Object)(object)box);
			}
			box = null;
			text = null;
			lastText = null;
		}

		private static void Create()
		{
			//IL_03a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b0: Expected O, but got Unknown
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0303: Unknown result type (might be due to invalid IL or missing references)
			//IL_0307: Unknown result type (might be due to invalid IL or missing references)
			//IL_0314: Unknown result type (might be due to invalid IL or missing references)
			//IL_0319: Unknown result type (might be due to invalid IL or missing references)
			//IL_031d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0322: Unknown result type (might be due to invalid IL or missing references)
			//IL_0327: Unknown result type (might be due to invalid IL or missing references)
			//IL_032c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0331: Unknown result type (might be due to invalid IL or missing references)
			//IL_034e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0353: Unknown result type (might be due to invalid IL or missing references)
			//IL_0357: Unknown result type (might be due to invalid IL or missing references)
			//IL_0345: Unknown result type (might be due to invalid IL or missing references)
			//IL_035c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0360: Unknown result type (might be due to invalid IL or missing references)
			//IL_0367: Unknown result type (might be due to invalid IL or missing references)
			//IL_036f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0376: Unknown result type (might be due to invalid IL or missing references)
			//IL_037e: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				UIDropPodCountdown val = null;
				foreach (Object item in (Il2CppArrayBase<Object>)(object)Resources.FindObjectsOfTypeAll(Il2CppType.Of<UIDropPodCountdown>()))
				{
					UIDropPodCountdown val2 = ((item != null) ? ((Il2CppObjectBase)item).TryCast<UIDropPodCountdown>() : null);
					if ((Object)(object)val2 != (Object)null)
					{
						Scene scene = ((Component)val2).gameObject.scene;
						if (((Scene)(ref scene)).IsValid())
						{
							val = val2;
							break;
						}
					}
				}
				if ((Object)(object)val == (Object)null || (Object)(object)val.content == (Object)null)
				{
					return;
				}
				RectTransform content = val.content;
				Transform val3 = (((Object)(object)((Component)val).transform.parent != (Object)null) ? ((Component)val).transform.parent : ((Component)val).transform);
				GameObject val4 = Object.Instantiate<GameObject>(((Component)content).gameObject);
				((Object)val4).name = "ExtractionTweaks.KillCounter";
				val4.transform.SetParent(val3, false);
				foreach (Component componentsInChild in val4.GetComponentsInChildren<Component>(true))
				{
					if (!((Object)(object)componentsInChild == (Object)null))
					{
						string fullName = ((Object)componentsInChild).GetIl2CppType().FullName;
						if (fullName.Contains("UIDropPodCountdown") || fullName.Contains("Localize") || fullName.Contains("FontSwap"))
						{
							Object.Destroy((Object)(object)componentsInChild);
						}
					}
				}
				val4.SetActive(true);
				foreach (CanvasGroup componentsInChild2 in val4.GetComponentsInChildren<CanvasGroup>(true))
				{
					componentsInChild2.alpha = 1f;
				}
				Vector3 localScale = val4.transform.localScale;
				if (((Vector3)(ref localScale)).sqrMagnitude < 0.01f)
				{
					val4.transform.localScale = Vector3.one;
				}
				TMP_Text val5 = null;
				foreach (TMP_Text componentsInChild3 in val4.GetComponentsInChildren<TMP_Text>(true))
				{
					if ((Object)(object)val5 == (Object)null)
					{
						val5 = componentsInChild3;
					}
					else
					{
						((Component)componentsInChild3).gameObject.SetActive(false);
					}
				}
				if ((Object)(object)val5 == (Object)null)
				{
					Object.Destroy((Object)(object)val4);
					return;
				}
				RectTransform rectTransform = val5.rectTransform;
				rectTransform.anchorMin = Vector2.zero;
				rectTransform.anchorMax = Vector2.one;
				rectTransform.pivot = new Vector2(0.5f, 0.5f);
				rectTransform.offsetMin = new Vector2(12f, 6f);
				rectTransform.offsetMax = new Vector2(-12f, -6f);
				val5.fontSizeMax = val5.fontSize;
				val5.fontSizeMin = 8f;
				val5.enableAutoSizing = true;
				val5.richText = true;
				val5.alignment = (TextAlignmentOptions)514;
				RectTransform component = val4.GetComponent<RectTransform>();
				if ((Object)(object)component != (Object)null)
				{
					Vector2 anchorMin = (component.anchorMax = new Vector2(0.5f, 0.5f));
					component.anchorMin = anchorMin;
					component.pivot = new Vector2(0.5f, 0.5f);
					Rect rect = content.rect;
					component.sizeDelta = ((Rect)(ref rect)).size;
					rect = content.rect;
					Vector3 val7 = val3.InverseTransformPoint(((Transform)content).TransformPoint(Vector2.op_Implicit(((Rect)(ref rect)).center)));
					RectTransform val8 = ((Il2CppObjectBase)val3).TryCast<RectTransform>();
					Vector2 val9;
					if (!((Object)(object)val8 != (Object)null))
					{
						val9 = Vector2.zero;
					}
					else
					{
						rect = val8.rect;
						val9 = ((Rect)(ref rect)).center;
					}
					Vector2 val10 = val9;
					component.anchoredPosition = new Vector2(val7.x - val10.x, val7.y - val10.y);
				}
				box = val4;
				text = val5;
				lastText = null;
			}
			catch (Exception ex)
			{
				ManualLogSource logger = Plugin.Logger;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val11 = new BepInExErrorLogInterpolatedStringHandler(24, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val11).AppendLiteral("Kill counter UI failed: ");
					((BepInExLogInterpolatedStringHandler)val11).AppendFormatted<Exception>(ex);
				}
				logger.LogError(val11);
				box = null;
			}
		}
	}
}