Decompiled source of Hugos Cards v0.10.12

plugins/CustomCards.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using CustomCards.Cards;
using CustomCards.Effects;
using CustomCards.Patches;
using CustomCards.Testing;
using HarmonyLib;
using InControl;
using Microsoft.CodeAnalysis;
using ModdingUtils.Extensions;
using ModdingUtils.MonoBehaviours;
using ModdingUtils.Utils;
using Photon.Pun;
using Sonigon;
using Sonigon.Internal;
using TMPro;
using UnboundLib;
using UnboundLib.Cards;
using UnboundLib.Extensions;
using UnboundLib.GameModes;
using UnboundLib.Networking;
using UnboundLib.Utils;
using UnboundLib.Utils.UI;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.1", FrameworkDisplayName = ".NET Framework 4.7.1")]
[assembly: AssemblyCompany("CustomCards")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("CustomCards")]
[assembly: AssemblyTitle("CustomCards")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace CustomCards
{
	internal static class CardUtils
	{
		private static readonly FieldRef<PlayerVelocity, Vector2> PlayerVelocityField = AccessTools.FieldRefAccess<PlayerVelocity, Vector2>("velocity");

		public static int CountCard(Player player, string cardName)
		{
			if ((Object)(object)player == (Object)null || (Object)(object)player.data == (Object)null || player.data.currentCards == null)
			{
				return 0;
			}
			return player.data.currentCards.Count((CardInfo c) => (Object)(object)c != (Object)null && c.cardName == cardName);
		}

		public static bool Alive(Player p)
		{
			if ((Object)(object)p != (Object)null && (Object)(object)p.data != (Object)null && !p.data.dead)
			{
				return p.data.isPlaying;
			}
			return false;
		}

		public static IEnumerable<Player> Enemies(Player player)
		{
			return PlayerManager.instance.players.Where((Player p) => (Object)(object)p != (Object)(object)player && p.teamID != player.teamID && Alive(p));
		}

		public static Player ClosestEnemy(Player player)
		{
			return (from p in Enemies(player)
				orderby Vector2.Distance(Vector2.op_Implicit(((Component)p).transform.position), Vector2.op_Implicit(((Component)player).transform.position))
				select p).FirstOrDefault();
		}

		public static Vector2 Velocity(Player player)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)player != (Object)null) || !((Object)(object)player.data.playerVel != (Object)null))
			{
				return Vector2.zero;
			}
			return PlayerVelocityField.Invoke(player.data.playerVel);
		}

		public static T Ensure<T>(Player player) where T : Component
		{
			T component = ((Component)player).GetComponent<T>();
			if (!((Object)(object)component != (Object)null))
			{
				return ((Component)player).gameObject.AddComponent<T>();
			}
			return component;
		}
	}
	public abstract class CardBehaviour : MonoBehaviour
	{
		protected Player player;

		protected CharacterData data;

		protected abstract string CardName { get; }

		protected int Stacks => CardUtils.CountCard(player, CardName);

		protected virtual void Awake()
		{
			player = ((Component)this).GetComponent<Player>();
			data = ((Component)this).GetComponent<CharacterData>();
		}

		protected virtual void Update()
		{
			if (Stacks <= 0)
			{
				Object.Destroy((Object)(object)this);
			}
		}
	}
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("com.custom.rounds.customcards", "Hugo's Cards", "0.10.12")]
	[BepInProcess("Rounds.exe")]
	public class CustomCardsPlugin : BaseUnityPlugin
	{
		public const string ModId = "com.custom.rounds.customcards";

		public const string ModName = "Hugo's Cards";

		public const string Version = "0.10.12";

		public const string ModInitials = "HC";

		internal static ManualLogSource Log;

		internal static CustomCardsPlugin Instance;

		private void Awake()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			new Harmony("com.custom.rounds.customcards").PatchAll();
			Log.LogInfo((object)"Patches applied.");
		}

		private void Start()
		{
			CustomCard.BuildCard<DemoCard>();
			CustomCard.BuildCard<NeoCard>();
			CustomCard.BuildCard<BalloonCard>((Action<CardInfo>)delegate(CardInfo card)
			{
				BalloonCard.Card = card;
			});
			CustomCard.BuildCard<PiercerCard>();
			CustomCard.BuildCard<NormalizeCard>();
			CustomCard.BuildCard<GreedCard>();
			GreedPicks.RegisterHooks();
			CustomCard.BuildCard<TopsyTurvyCard>();
			TopsyTurvy.RegisterHooks();
			CustomCard.BuildCard<PlatingCard>();
			CustomCard.BuildCard<MossCard>();
			CustomCard.BuildCard<TreasureMapCard>();
			CustomCard.BuildCard<BloodthirstyCard>();
			CustomCard.BuildCard<FragileCard>();
			CustomCard.BuildCard<OneManArmyCard>();
			CustomCard.BuildCard<DetonaterCard>();
			CustomCard.BuildCard<RocketBootsCard>();
			CustomCard.BuildCard<TeslaCard>();
			CustomCard.BuildCard<ChickenCard>();
			CustomCard.BuildCard<WoundedCard>();
			CustomCard.BuildCard<SlipperyCard>();
			CustomCard.BuildCard<ForcePushCard>();
			CustomCard.BuildCard<FlameOnCard>();
			CustomCard.BuildCard<RouletteCard>();
			CustomCard.BuildCard<TranscendenceCard>();
			CustomCard.BuildCard<DoublingCherryCard>();
			DoublingCherry.RegisterHooks();
			TreasureMap.RegisterHooks();
			PerPointResets.RegisterHooks();
			CardManager.AddAllCardsCallback((Action<CardInfo[]>)BalloonCard.CopyGrowEffect);
			CardManager.AddAllCardsCallback((Action<CardInfo[]>)DetonaterCard.FindExplosion);
			TestMap.Init();
		}
	}
}
namespace CustomCards.Testing
{
	internal class DamageRecord
	{
		public float time = Time.time;

		public Player victim;

		public Player attacker;

		public string source;

		public readonly List<string> steps = new List<string>();

		public float current;

		public float applied = -1f;

		public float hpBefore;

		public float hpAfter;

		public float maxHp;

		public bool blocked;

		public bool refilled;

		public bool delayed;

		public bool logged;

		public void Step(string text)
		{
			steps.Add(text);
		}
	}
	internal class BulletNotes : MonoBehaviour
	{
		public float fired;

		public float finalAtFire = float.NaN;

		public readonly List<string> mods = new List<string>();
	}
	internal static class DamageLog
	{
		public struct FloatingNumber
		{
			public Vector3 pos;

			public string text;

			public Color color;

			public float born;
		}

		public const int MaxRecords = 40;

		public static readonly List<DamageRecord> Records = new List<DamageRecord>();

		public static readonly List<FloatingNumber> Numbers = new List<FloatingNumber>();

		internal static string SourceOverride;

		internal static ProjectileHit CurrentBullet;

		private static readonly Stack<DamageRecord> sending = new Stack<DamageRecord>();

		public static bool Enabled => TestMap.Active;

		internal static DamageRecord Top
		{
			get
			{
				if (sending.Count <= 0)
				{
					return null;
				}
				return sending.Peek();
			}
		}

		public static void Step(string label, float before, float after)
		{
			if (Enabled && sending.Count != 0 && !Mathf.Approximately(before, after))
			{
				DamageRecord damageRecord = sending.Peek();
				damageRecord.Step($"{label}: {before:0.#} → {after:0.#}");
				damageRecord.current = after;
			}
		}

		public static void Clear()
		{
			Records.Clear();
			Numbers.Clear();
			sending.Clear();
			SourceOverride = null;
			CurrentBullet = null;
		}

		internal static DamageRecord Begin(HealthHandler victim, Vector2 damage, Player attacker)
		{
			DamageRecord damageRecord = new DamageRecord
			{
				victim = ((Component)victim).GetComponent<Player>(),
				attacker = attacker,
				source = Classify(),
				current = ((Vector2)(ref damage)).magnitude
			};
			ProjectileHit currentBullet = CurrentBullet;
			if (SourceOverride == null && (Object)(object)currentBullet != (Object)null)
			{
				BulletNotes component = ((Component)currentBullet).GetComponent<BulletNotes>();
				if ((Object)(object)component != (Object)null)
				{
					damageRecord.Step($"Bullet fired with {component.fired:0.#} damage");
					foreach (string mod in component.mods)
					{
						damageRecord.Step(mod);
					}
				}
				float num = (((Object)(object)component != (Object)null) ? component.finalAtFire : float.NaN);
				if (!float.IsNaN(num) && Mathf.Abs(num - currentBullet.damage) > 0.05f)
				{
					damageRecord.Step($"Changed in flight (Grow/Balloon etc.): {num:0.#} → {currentBullet.damage:0.#}");
				}
				if (currentBullet.percentageDamage != 0f)
				{
					damageRecord.Step($"+{currentBullet.percentageDamage * 100f:0.#}% of max HP (vanilla percentage damage)");
				}
				if (!Mathf.Approximately(currentBullet.dealDamageMultiplierr, 1f))
				{
					damageRecord.Step($"Damage multiplier ×{currentBullet.dealDamageMultiplierr:0.##}");
				}
			}
			damageRecord.Step($"Hit for {damageRecord.current:0.#}");
			return damageRecord;
		}

		internal static void Push(DamageRecord rec)
		{
			sending.Push(rec);
		}

		internal static void Pop()
		{
			if (sending.Count > 0)
			{
				sending.Pop();
			}
		}

		internal static void Finish(DamageRecord rec, Vector3 pos)
		{
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: 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_0132: 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_0141: 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_015a: 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_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			if (!rec.logged)
			{
				rec.logged = true;
				Records.Insert(0, rec);
				if (Records.Count > 40)
				{
					Records.RemoveAt(Records.Count - 1);
				}
				string text;
				Color color = default(Color);
				if (rec.blocked)
				{
					text = "BLOCKED";
					((Color)(ref color))..ctor(0.4f, 0.8f, 1f);
				}
				else if (rec.delayed && rec.applied < 0f)
				{
					text = $"{rec.current:0.#} over time";
					((Color)(ref color))..ctor(0.7f, 1f, 0.4f);
				}
				else
				{
					text = $"-{rec.applied:0.#}" + (rec.refilled ? " (lethal)" : "");
					color = (rec.refilled ? new Color(1f, 0.85f, 0.2f) : new Color(1f, 0.35f, 0.3f));
				}
				Numbers.Add(new FloatingNumber
				{
					pos = pos + Vector3.up * 2f + Vector2.op_Implicit(Random.insideUnitCircle * 0.5f),
					text = text,
					color = color,
					born = Time.time
				});
				if (Numbers.Count > 60)
				{
					Numbers.RemoveAt(0);
				}
				TestDummy testDummy = (((Object)(object)rec.victim != (Object)null) ? ((Component)rec.victim).GetComponent<TestDummy>() : null);
				if ((Object)(object)testDummy != (Object)null && rec.applied > 0f)
				{
					testDummy.OnDamaged(rec.applied);
				}
			}
		}

		private static string Classify()
		{
			if (SourceOverride != null)
			{
				return SourceOverride;
			}
			if ((Object)(object)CurrentBullet != (Object)null)
			{
				return "Bullet";
			}
			try
			{
				StackFrame[] array = new StackTrace(2, fNeedFileInfo: false).GetFrames() ?? new StackFrame[0];
				for (int i = 0; i < array.Length; i++)
				{
					string text = FrameType(array[i]);
					if (text != null && !text.StartsWith("HealthHandler") && !text.StartsWith("Damagable") && !text.StartsWith("System") && !text.StartsWith("HarmonyLib") && !text.StartsWith("MonoMod") && !text.StartsWith("Photon") && !text.StartsWith("CustomCards.Testing") && !text.Contains("PhotonView") && !text.Contains("NetworkingPeer"))
					{
						if (text.Contains("ProjectileHit"))
						{
							return "Bullet";
						}
						if (text.Contains("Explosion"))
						{
							return "Explosion";
						}
						if (text.Contains("DamageOverTime"))
						{
							return "Damage over time";
						}
						if (text.Contains("FlameOn"))
						{
							return "Flame on! fire";
						}
						if (text.Contains("Tesla"))
						{
							return "Tesla arc";
						}
						if (text.Contains("OutOfBounds"))
						{
							return "Out of bounds";
						}
						int num = text.LastIndexOf('.');
						return (num >= 0) ? text.Substring(num + 1) : text;
					}
				}
			}
			catch (Exception)
			{
			}
			return "Unknown";
		}

		private static string FrameType(StackFrame frame)
		{
			MethodBase method = frame.GetMethod();
			if (method == null)
			{
				return null;
			}
			if (method.DeclaringType != null)
			{
				return method.DeclaringType.FullName;
			}
			string name = method.Name;
			int num = name.IndexOf('<');
			int num2 = name.IndexOf("::", StringComparison.Ordinal);
			if (num < 0 || num2 <= num)
			{
				return null;
			}
			return name.Substring(num + 1, num2 - num - 1);
		}
	}
	[HarmonyPatch(typeof(ProjectileHit), "RPCA_DoHit")]
	internal static class DamageLogBulletContext
	{
		[HarmonyPriority(800)]
		private static void Prefix(ProjectileHit __instance, out ProjectileHit __state)
		{
			__state = DamageLog.CurrentBullet;
			if (DamageLog.Enabled)
			{
				DamageLog.CurrentBullet = __instance;
			}
		}

		private static Exception Finalizer(Exception __exception, ProjectileHit __state)
		{
			DamageLog.CurrentBullet = __state;
			return __exception;
		}
	}
	[HarmonyPatch(typeof(HealthHandler), "CallTakeDamage")]
	internal static class DamageLogSendStart
	{
		[HarmonyPriority(800)]
		private static void Prefix(HealthHandler __instance, Vector2 damage, Player damagingPlayer, out DamageRecord __state)
		{
			//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_0032: Unknown result type (might be due to invalid IL or missing references)
			__state = null;
			if (DamageLog.Enabled && !(damage == Vector2.zero) && !((Object)(object)((Component)__instance).GetComponent<Player>() == (Object)null) && !DoublingCherry.SameGroup(__instance, damagingPlayer))
			{
				__state = DamageLog.Begin(__instance, damage, damagingPlayer);
				DamageLog.Push(__state);
			}
		}

		private static Exception Finalizer(Exception __exception, HealthHandler __instance, DamageRecord __state)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			if (__state != null)
			{
				DamageLog.Pop();
				if (__state.applied < 0f)
				{
					if (!__state.blocked)
					{
						__state.delayed = true;
					}
					DamageLog.Finish(__state, ((Component)__instance).transform.position);
				}
			}
			return __exception;
		}
	}
	[HarmonyPatch(typeof(HealthHandler), "CallTakeDamage")]
	internal static class DamageLogSendEnd
	{
		[HarmonyPriority(0)]
		private static void Prefix(HealthHandler __instance, Vector2 damage)
		{
			DamageRecord top = DamageLog.Top;
			if (top != null && DamageLog.Enabled)
			{
				float magnitude = ((Vector2)(ref damage)).magnitude;
				if (Mathf.Abs(magnitude - top.current) > 0.05f)
				{
					top.Step($"Other mods: {top.current:0.#} → {magnitude:0.#}");
					top.current = magnitude;
				}
				CharacterData component = ((Component)__instance).GetComponent<CharacterData>();
				if ((Object)(object)component != (Object)null && component.block.IsBlocking())
				{
					top.blocked = true;
				}
			}
		}
	}
	[HarmonyPatch(typeof(HealthHandler), "DoDamage")]
	internal static class DamageLogApply
	{
		[HarmonyPriority(800)]
		private static void Prefix(HealthHandler __instance, Vector2 damage, Player damagingPlayer, bool ignoreBlock, out DamageRecord __state)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			__state = null;
			if (!DamageLog.Enabled || damage == Vector2.zero)
			{
				return;
			}
			CharacterData component = ((Component)__instance).GetComponent<CharacterData>();
			if (!((Object)(object)component == (Object)null) && component.isPlaying && !component.dead && !__instance.isRespawning && (!component.block.IsBlocking() || ignoreBlock))
			{
				DamageRecord damageRecord = DamageLog.Top;
				if (damageRecord == null || (Object)(object)damageRecord.victim != (Object)(object)component.player || damageRecord.applied >= 0f)
				{
					damageRecord = DamageLog.Begin(__instance, damage, damagingPlayer);
				}
				else if (Mathf.Abs(((Vector2)(ref damage)).magnitude - damageRecord.current) > 0.05f)
				{
					damageRecord.Step($"Changed on arrival: {damageRecord.current:0.#} → {((Vector2)(ref damage)).magnitude:0.#}");
					damageRecord.current = ((Vector2)(ref damage)).magnitude;
				}
				damageRecord.hpBefore = component.health;
				damageRecord.maxHp = component.maxHealth;
				if (((Vector2)(ref damage)).magnitude >= component.health && TestMap.IsImmortal(component.player))
				{
					damageRecord.refilled = true;
					component.health = ((Vector2)(ref damage)).magnitude + component.maxHealth;
				}
				__state = damageRecord;
			}
		}

		private static void Postfix(HealthHandler __instance, Vector2 damage, DamageRecord __state)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			if (__state != null)
			{
				CharacterData component = ((Component)__instance).GetComponent<CharacterData>();
				__state.hpAfter = component.health;
				__state.applied = (__state.refilled ? ((Vector2)(ref damage)).magnitude : (__state.hpBefore - component.health));
				DamageLog.Finish(__state, ((Component)__instance).transform.position);
				if (__state.refilled && (Object)(object)((Component)component.player).GetComponent<TestDummy>() != (Object)null && DamageLog.SourceOverride != "Detonater explosion")
				{
					__state.Step("Counts as a kill (Detonater, Bloodthirsty)");
					Detonater.OnPlayerDied(component.player);
					Bloodthirsty.OnPlayerDied(component.player);
				}
			}
		}
	}
	public enum DummyKind
	{
		Target,
		Shooter
	}
	public class TestDummy : MonoBehaviour
	{
		public DummyKind Kind;

		public Vector3 Home;

		public bool Disabled;

		private const float DpsWindow = 3f;

		private const float AutoHealDelay = 2.5f;

		private readonly Queue<KeyValuePair<float, float>> recent = new Queue<KeyValuePair<float, float>>();

		private Player player;

		private CharacterData data;

		private float nextShot;

		public float TotalDamage { get; private set; }

		public int Hits { get; private set; }

		public float BiggestHit { get; private set; }

		public float LastDamaged { get; private set; } = -100f;

		public string Name
		{
			get
			{
				if (Kind != DummyKind.Target)
				{
					return "Shooter dummy";
				}
				return "Target dummy";
			}
		}

		public float Dps
		{
			get
			{
				while (recent.Count > 0 && Time.time - recent.Peek().Key > 3f)
				{
					recent.Dequeue();
				}
				float num = 0f;
				foreach (KeyValuePair<float, float> item in recent)
				{
					num += item.Value;
				}
				return num / 3f;
			}
		}

		private void Awake()
		{
			player = ((Component)this).GetComponent<Player>();
			data = ((Component)this).GetComponent<CharacterData>();
		}

		public void OnDamaged(float amount)
		{
			TotalDamage += amount;
			Hits++;
			BiggestHit = Mathf.Max(BiggestHit, amount);
			LastDamaged = Time.time;
			recent.Enqueue(new KeyValuePair<float, float>(Time.time, amount));
		}

		public void ResetStats()
		{
			TotalDamage = 0f;
			Hits = 0;
			BiggestHit = 0f;
			recent.Clear();
		}

		private void Update()
		{
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: 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_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			if (!TestMap.Active || (Object)(object)data == (Object)null)
			{
				return;
			}
			GeneralInput input = data.input;
			input.ResetInput();
			if (!CardUtils.Alive(player))
			{
				return;
			}
			if (TestMap.DummiesAutoHeal && Time.time - LastDamaged > 2.5f && data.health < data.maxHealth)
			{
				data.health = data.maxHealth;
			}
			if (TestMap.DummiesWalkBack && data.isGrounded)
			{
				float num = Home.x - ((Component)this).transform.position.x;
				if (Mathf.Abs(num) > 0.8f)
				{
					input.direction = new Vector3(Mathf.Sign(num), 0f, 0f);
				}
			}
			Player human = TestMap.Human;
			if (!((Object)(object)human == (Object)null) && CardUtils.Alive(human))
			{
				Vector3 val = ((Component)human).transform.position - ((Component)this).transform.position;
				val.z = 0f;
				((Vector3)(ref val)).Normalize();
				Gun val2 = (((Object)(object)data.weaponHandler != (Object)null) ? data.weaponHandler.gun : null);
				if ((Object)(object)val2 != (Object)null)
				{
					val += Vector3.up * 0.13f / Mathf.Clamp(val2.projectileSpeed, 1f, 100f);
				}
				input.aimDirection = val;
				input.lastAimDirection = val;
				if (Kind == DummyKind.Shooter && TestMap.ShooterFiring && Time.time >= nextShot)
				{
					nextShot = Time.time + TestMap.ShooterInterval;
					input.shootWasPressed = true;
					input.shootIsPressed = true;
				}
			}
		}
	}
	internal static class TestMap
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__Open;

			public static Action <1>__SpawnProps;
		}

		public const float FloorTop = -9f;

		public static readonly Vector3 PlayerSpawn = new Vector3(0f, -7f, 0f);

		public static readonly Vector3 TargetSpawn = new Vector3(14f, -7f, 0f);

		public static readonly Vector3 ShooterSpawn = new Vector3(-14f, -7f, 0f);

		private const float PropStartX = -31f;

		private const float PropSpacing = 3.2f;

		private static readonly string[] PropNames = new string[6] { "box", "box_medium", "box_destructible", "box_destructible_small", "box_big", "ball_big" };

		public static bool DummiesImmortal = true;

		public static bool DummiesAutoHeal = true;

		public static bool DummiesWalkBack = true;

		public static bool ShooterFiring = true;

		public static float ShooterInterval = 1f;

		public static bool GodMode;

		public static float TimeScale = 1f;

		private static Map map;

		private static GameObject floor;

		private static readonly List<GameObject> props = new List<GameObject>();

		private static bool dummiesRequested;

		private static float defaultBaseTimeScale = -1f;

		private static readonly Dictionary<string, bool> propEnabled = PropNames.ToDictionary((string n) => n, (string n) => true);

		private static readonly Dictionary<string, GameObject> propByName = new Dictionary<string, GameObject>();

		private static float lastJoinAt = -10f;

		private static readonly FieldRef<PlayerVelocity, Vector2> Velocity = AccessTools.FieldRefAccess<PlayerVelocity, Vector2>("velocity");

		public static bool Active { get; private set; }

		public static Player Human
		{
			get
			{
				if (!((Object)(object)PlayerManager.instance == (Object)null))
				{
					return ((IEnumerable<Player>)PlayerManager.instance.players).FirstOrDefault((Func<Player, bool>)((Player p) => (Object)(object)p != (Object)null && (Object)(object)((Component)p).GetComponent<TestDummy>() == (Object)null && !p.data.input.controlledElseWhere));
				}
				return null;
			}
		}

		public static IEnumerable<string> PropList => PropNames;

		public static Player Dummy(DummyKind kind)
		{
			if (!((Object)(object)PlayerManager.instance == (Object)null))
			{
				return ((IEnumerable<Player>)PlayerManager.instance.players).FirstOrDefault((Func<Player, bool>)delegate(Player p)
				{
					if ((Object)(object)p != (Object)null)
					{
						TestDummy component = ((Component)p).GetComponent<TestDummy>();
						if (component != null)
						{
							return component.Kind == kind;
						}
					}
					return false;
				});
			}
			return null;
		}

		public static bool IsImmortal(Player p)
		{
			if (!Active || (Object)(object)p == (Object)null)
			{
				return false;
			}
			if ((Object)(object)((Component)p).GetComponent<TestDummy>() != (Object)null)
			{
				return DummiesImmortal;
			}
			if (GodMode)
			{
				return (Object)(object)p == (Object)(object)Human;
			}
			return false;
		}

		public static void Init()
		{
			SceneManager.sceneLoaded += delegate(Scene scene, LoadSceneMode mode)
			{
				if (((Scene)(ref scene)).name == "Main")
				{
					Leave();
				}
			};
			((MonoBehaviour)CustomCardsPlugin.Instance).StartCoroutine(KeepMenuButton());
			((Component)CustomCardsPlugin.Instance).gameObject.AddComponent<TestMapUI>();
		}

		private static IEnumerator KeepMenuButton()
		{
			while (true)
			{
				yield return (object)new WaitForSecondsRealtime(1f);
				if (Active)
				{
					continue;
				}
				GameObject val = GameObject.Find("/Game/UI/UI_MainMenu/Canvas/ListSelector/LOCAL");
				Transform val2 = (((Object)(object)val != (Object)null) ? val.transform.Find("Group/Grid/Scroll View/Viewport/Content") : null);
				if ((Object)(object)val2 == (Object)null || (Object)(object)val2.Find("CC Test Map") != (Object)null)
				{
					continue;
				}
				try
				{
					object obj = <>O.<0>__Open;
					if (obj == null)
					{
						UnityAction val3 = Open;
						<>O.<0>__Open = val3;
						obj = (object)val3;
					}
					GameObject val4 = MenuHandler.CreateButton("TEST MAP", val, (UnityAction)obj, 60, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
					((Object)val4).name = "CC Test Map";
					Transform val5 = val2.Find("Test");
					if ((Object)(object)val5 != (Object)null)
					{
						val4.transform.SetSiblingIndex(val5.GetSiblingIndex() + 1);
					}
				}
				catch (Exception ex)
				{
					CustomCardsPlugin.Log.LogWarning((object)("Test map: couldn't add menu button: " + ex));
				}
			}
		}

		private static void Open()
		{
			Active = true;
			dummiesRequested = false;
			DamageLog.Clear();
			MainMenuHandler.instance.Close();
			GameModeManager.SetGameMode("Sandbox");
			GameModeManager.CurrentHandler.StartGame();
			CustomCardsPlugin.Log.LogInfo((object)"Test map: opened. Press jump/any button to join.");
		}

		private static void Leave()
		{
			if (Active)
			{
				Active = false;
				SetTimeScale(1f);
				map = null;
				floor = null;
				props.Clear();
				propByName.Clear();
				DamageLog.Clear();
				Unbound.lockInputBools.Remove("CustomCards_TestMap");
			}
		}

		internal static void BuildFrom(Scene scene)
		{
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			Map val = (from g in ((Scene)(ref scene)).GetRootGameObjects()
				select g.GetComponent<Map>()).FirstOrDefault((Func<Map, bool>)((Map x) => (Object)(object)x != (Object)null));
			if ((Object)(object)val == (Object)null)
			{
				CustomCardsPlugin.Log.LogWarning((object)"Test map: loaded scene has no Map.");
				return;
			}
			val.size = 20f;
			Collider2D val2 = FindGroundTemplate(val);
			GameObject val3 = (((Object)(object)val2 != (Object)null) ? CloneAsFloor(((Component)val2).gameObject, ((Component)val).transform) : FloorFromBoxPrefab(((Component)val).transform));
			if ((Object)(object)val3 == (Object)null)
			{
				CustomCardsPlugin.Log.LogWarning((object)"Test map: couldn't build a floor; using the normal map.");
				return;
			}
			foreach (Transform item in ((IEnumerable)((Component)val).transform).Cast<Transform>().ToList())
			{
				if ((Object)(object)((Component)item).gameObject != (Object)(object)val3)
				{
					Object.DestroyImmediate((Object)(object)((Component)item).gameObject);
				}
			}
			GameObject[] rootGameObjects = ((Scene)(ref scene)).GetRootGameObjects();
			foreach (GameObject val4 in rootGameObjects)
			{
				if ((Object)(object)val4 != (Object)(object)((Component)val).gameObject && (Object)(object)val4.GetComponentInChildren<Collider2D>(true) != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)val4);
				}
			}
			val3.transform.SetAsFirstSibling();
			AddSpawnPoint(val, PlayerSpawn, 0);
			AddSpawnPoint(val, TargetSpawn, 1);
			AddSpawnPoint(val, ShooterSpawn, 1);
			map = val;
			floor = val3;
			props.Clear();
			propByName.Clear();
			val.mapIsReadyAction = (Action)Delegate.Combine(val.mapIsReadyAction, new Action(SpawnProps));
			CustomCardsPlugin.Log.LogInfo((object)("Test map: built from '" + ((Scene)(ref scene)).name + "' using floor template '" + (((Object)(object)val2 != (Object)null) ? ((Object)val2).name : "box prefab") + "'."));
		}

		private static Collider2D FindGroundTemplate(Map m)
		{
			List<BoxCollider2D> list = ((Component)m).GetComponentsInChildren<BoxCollider2D>(true).Where(delegate(BoxCollider2D c)
			{
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				//IL_001b: Unknown result type (might be due to invalid IL or missing references)
				//IL_003f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0063: Unknown result type (might be due to invalid IL or missing references)
				//IL_0069: Invalid comparison between Unknown and I4
				if (((Collider2D)c).isTrigger || c.size.x <= 0f || c.size.y <= 0f)
				{
					return false;
				}
				SpriteRenderer component = ((Component)c).GetComponent<SpriteRenderer>();
				if ((Object)(object)component == (Object)null || component.color.a < 0.5f)
				{
					return false;
				}
				Rigidbody2D componentInParent = ((Component)c).GetComponentInParent<Rigidbody2D>();
				if ((Object)(object)componentInParent != (Object)null && (int)componentInParent.bodyType != 2)
				{
					return false;
				}
				return (Object)(object)((Component)c).GetComponentInParent<PhotonMapObject>() == (Object)null && (Object)(object)((Component)c).GetComponentInParent<NetworkPhysicsObject>() == (Object)null;
			}).ToList();
			List<BoxCollider2D> list2 = list.Where((BoxCollider2D c) => ((Component)c).GetComponents<MonoBehaviour>().All((MonoBehaviour b) => (Object)(object)b == (Object)null || b is SFPolygon)).ToList();
			return (Collider2D)(object)((list2.Count > 0) ? list2 : list).OrderByDescending((BoxCollider2D c) => c.size.x * ((Component)c).transform.lossyScale.x * c.size.y * ((Component)c).transform.lossyScale.y).FirstOrDefault();
		}

		private static GameObject CloneAsFloor(GameObject template, Transform parent)
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Object.Instantiate<GameObject>(template, parent);
			((Object)val).name = "Test floor";
			foreach (Transform item in ((IEnumerable)val.transform).Cast<Transform>().ToList())
			{
				Object.DestroyImmediate((Object)(object)((Component)item).gameObject);
			}
			ShapeFloor(val, template.transform.position.z);
			return val;
		}

		private static GameObject FloorFromBoxPrefab(Transform parent)
		{
			GameObject val = ((IEnumerable<GameObject>)Resources.LoadAll<GameObject>("4 Map Objects")).FirstOrDefault((Func<GameObject, bool>)((GameObject p) => ((Object)p).name.ToLower() == "box"));
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			GameObject val2 = Object.Instantiate<GameObject>(val, parent);
			((Object)val2).name = "Test floor";
			MonoBehaviour[] componentsInChildren = val2.GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val3 in componentsInChildren)
			{
				if (!(val3 is SFPolygon) && !(val3 is PhotonView))
				{
					Object.DestroyImmediate((Object)(object)val3);
				}
			}
			PhotonView[] componentsInChildren2 = val2.GetComponentsInChildren<PhotonView>(true);
			for (int num = 0; num < componentsInChildren2.Length; num++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren2[num]);
			}
			Rigidbody2D[] componentsInChildren3 = val2.GetComponentsInChildren<Rigidbody2D>(true);
			for (int num = 0; num < componentsInChildren3.Length; num++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren3[num]);
			}
			if ((Object)(object)val2.GetComponent<BoxCollider2D>() == (Object)null)
			{
				Object.DestroyImmediate((Object)(object)val2);
				return null;
			}
			ShapeFloor(val2, 0f);
			return val2;
		}

		private static void ShapeFloor(GameObject g, float z)
		{
			//IL_000d: 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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			BoxCollider2D component = g.GetComponent<BoxCollider2D>();
			g.transform.localRotation = Quaternion.identity;
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(100f / component.size.x, 14f / component.size.y, 1f);
			g.transform.localScale = val;
			g.transform.localPosition = new Vector3((0f - ((Collider2D)component).offset.x) * val.x, -16f - ((Collider2D)component).offset.y * val.y, z);
			SFPolygon component2 = g.GetComponent<SFPolygon>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.CopyFromCollider((Collider2D)(object)component);
			}
		}

		private static void AddSpawnPoint(Map m, Vector3 pos, int team)
		{
			//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_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Test spawn");
			val.transform.SetParent(((Component)m).transform, false);
			val.transform.localPosition = pos;
			val.AddComponent<SpawnPoint>().TEAMID = team;
		}

		public static bool IsPropEnabled(string name)
		{
			bool value;
			return propEnabled.TryGetValue(name, out value) && value;
		}

		public static string PropLabel(string name)
		{
			return CultureInfo.InvariantCulture.TextInfo.ToTitleCase(name.Replace('_', ' '));
		}

		public static void SetPropEnabled(string name, bool on)
		{
			if (!propEnabled.ContainsKey(name) || propEnabled[name] == on)
			{
				return;
			}
			propEnabled[name] = on;
			if (Active && !((Object)(object)map == (Object)null))
			{
				GameObject value;
				if (on)
				{
					SpawnProp(name);
				}
				else if (propByName.TryGetValue(name, out value))
				{
					DestroyProp(value);
					props.Remove(value);
					propByName.Remove(name);
				}
			}
		}

		private static void SpawnProps()
		{
			if (!Active || (Object)(object)map == (Object)null)
			{
				return;
			}
			string[] propNames = PropNames;
			foreach (string name in propNames)
			{
				if (IsPropEnabled(name))
				{
					SpawnProp(name);
				}
			}
		}

		private static void SpawnProp(string name)
		{
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			if (propByName.TryGetValue(name, out var value) && (Object)(object)value != (Object)null)
			{
				return;
			}
			GameObject val = ((IEnumerable<GameObject>)Resources.LoadAll<GameObject>("4 Map Objects")).FirstOrDefault((Func<GameObject, bool>)((GameObject p) => ((Object)p).name.ToLower() == name));
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			float num = -31f + 3.2f * (float)Array.IndexOf(PropNames, name);
			try
			{
				GameObject val2 = PhotonNetwork.Instantiate("4 Map Objects/" + ((Object)val).name, new Vector3(num, -5f, 0f), Quaternion.identity, (byte)0, (object[])null);
				props.Add(val2);
				propByName[name] = val2;
				((MonoBehaviour)CustomCardsPlugin.Instance).StartCoroutine(WakeProp(val2));
			}
			catch (Exception ex)
			{
				CustomCardsPlugin.Log.LogWarning((object)("Test map: couldn't spawn " + ((Object)val).name + ": " + ex.Message));
			}
		}

		public static bool IsDummyEnabled(DummyKind kind)
		{
			Player val = Dummy(kind);
			if ((Object)(object)val != (Object)null)
			{
				return !((Component)val).GetComponent<TestDummy>().Disabled;
			}
			return false;
		}

		public static void SetDummyEnabled(DummyKind kind, bool on)
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			Player val = Dummy(kind);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			TestDummy component = ((Component)val).GetComponent<TestDummy>();
			if (component.Disabled != !on)
			{
				component.Disabled = !on;
				if (on)
				{
					((Component)val).gameObject.SetActive(true);
					val.data.isPlaying = true;
					val.data.health = val.data.maxHealth;
					Teleport(val, component.Home);
				}
				else
				{
					val.data.isPlaying = false;
					((Component)val).gameObject.SetActive(false);
				}
			}
		}

		private static IEnumerator WakeProp(GameObject go)
		{
			for (int i = 0; i < 5; i++)
			{
				yield return null;
			}
			if ((Object)(object)go == (Object)null)
			{
				yield break;
			}
			Rigidbody2D[] componentsInChildren = go.GetComponentsInChildren<Rigidbody2D>();
			foreach (Rigidbody2D val in componentsInChildren)
			{
				if ((int)val.bodyType != 2)
				{
					val.isKinematic = false;
					val.simulated = true;
					val.gravityScale = 1f;
				}
			}
		}

		public static void ResetProps()
		{
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Invalid comparison between Unknown and I4
			if (!Active || (Object)(object)map == (Object)null)
			{
				return;
			}
			foreach (GameObject prop in props)
			{
				DestroyProp(prop);
			}
			props.Clear();
			propByName.Clear();
			Rigidbody2D[] componentsInChildren = ((Component)map).GetComponentsInChildren<Rigidbody2D>(true);
			foreach (Rigidbody2D val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).gameObject != (Object)(object)floor && (Object)(object)((Component)val).GetComponentInParent<Player>() == (Object)null && (int)val.bodyType != 2)
				{
					DestroyProp(((Component)val).gameObject);
				}
			}
			SpawnProps();
		}

		private static void DestroyProp(GameObject go)
		{
			if (!((Object)(object)go == (Object)null))
			{
				PhotonView component = go.GetComponent<PhotonView>();
				if ((Object)(object)component != (Object)null && component.IsMine)
				{
					PhotonNetwork.Destroy(go);
				}
				else
				{
					Object.Destroy((Object)(object)go);
				}
			}
		}

		public static void ClearBullets()
		{
			ProjectileHit[] array = Object.FindObjectsOfType<ProjectileHit>();
			foreach (ProjectileHit val in array)
			{
				if ((Object)(object)val != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)val).gameObject);
				}
			}
			MapTransition instance = MapTransition.instance;
			if (instance != null)
			{
				instance.ClearObjects();
			}
		}

		public static void ResetEverything()
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			ClearBullets();
			ResetProps();
			foreach (Player item in PlayerManager.instance.players.ToList())
			{
				if (!((Object)(object)item == (Object)null) && !item.data.dead && ((Component)item).gameObject.activeSelf)
				{
					item.data.health = item.data.maxHealth;
					TestDummy component = ((Component)item).GetComponent<TestDummy>();
					Teleport(item, ((Object)(object)component != (Object)null) ? component.Home : PlayerSpawn);
					if ((Object)(object)component != (Object)null)
					{
						component.ResetStats();
					}
				}
			}
			DamageLog.Clear();
		}

		public static void SetTimeScale(float scale)
		{
			TimeScale = scale;
			if (!((Object)(object)TimeHandler.instance == (Object)null))
			{
				if (defaultBaseTimeScale < 0f)
				{
					defaultBaseTimeScale = TimeHandler.instance.baseTimeScale;
				}
				TimeHandler.instance.baseTimeScale = defaultBaseTimeScale * scale;
			}
		}

		internal static void OnPlayerAdded(Player player)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			if (!Active || (Object)(object)player == (Object)null)
			{
				return;
			}
			TestDummy component = ((Component)player).GetComponent<TestDummy>();
			Teleport(player, ((Object)(object)component != (Object)null) ? component.Home : PlayerSpawn);
			int num;
			if ((Object)(object)component == (Object)null)
			{
				num = ((!player.data.input.controlledElseWhere) ? 1 : 0);
				if (num != 0 && player.teamID != 0)
				{
					player.AssignTeamID(0);
					PlayerExtensions.AssignColorID(player, 0);
				}
			}
			else
			{
				num = 0;
			}
			if (num != 0 && !dummiesRequested)
			{
				dummiesRequested = true;
				((MonoBehaviour)CustomCardsPlugin.Instance).StartCoroutine(SpawnDummies());
			}
		}

		private static IEnumerator SpawnDummies()
		{
			yield return (object)new WaitForSecondsRealtime(0.5f);
			if ((Object)(object)Dummy(DummyKind.Target) == (Object)null)
			{
				yield return SpawnDummy(DummyKind.Target);
			}
			if ((Object)(object)Dummy(DummyKind.Shooter) == (Object)null)
			{
				yield return SpawnDummy(DummyKind.Shooter);
			}
		}

		internal static void HandleJoining()
		{
			PlayerAssigner instance = PlayerAssigner.instance;
			if ((Object)(object)instance == (Object)null || DevConsole.isTyping || GameManager.lockInput || Time.unscaledTime - lastJoinAt < 0.5f || PlayerManager.instance.players.Count >= instance.maxPlayers)
			{
				return;
			}
			List<Player> source = PlayerManager.instance.players.Where((Player p) => (Object)(object)p != (Object)null && p.data.playerActions != null && !p.data.input.controlledElseWhere).ToList();
			if (Input.GetKey((KeyCode)32) && !source.Any((Player p) => ((PlayerActionSet)p.data.playerActions).Device == null))
			{
				lastJoinAt = Time.unscaledTime;
				((MonoBehaviour)instance).StartCoroutine(instance.CreatePlayer((InputDevice)null, false));
				return;
			}
			foreach (InputDevice device in InputManager.ActiveDevices)
			{
				if ((((OneAxisInputControl)device.Action1).WasPressed || ((OneAxisInputControl)device.Action2).WasPressed || ((OneAxisInputControl)device.Action3).WasPressed || ((OneAxisInputControl)device.Action4).WasPressed) && !source.Any((Player p) => ((PlayerActionSet)p.data.playerActions).Device == device))
				{
					lastJoinAt = Time.unscaledTime;
					((MonoBehaviour)instance).StartCoroutine(instance.CreatePlayer(device, false));
					break;
				}
			}
		}

		public static void RespawnMissingDummies()
		{
			if (Active)
			{
				((MonoBehaviour)CustomCardsPlugin.Instance).StartCoroutine(SpawnDummies());
			}
		}

		private static IEnumerator SpawnDummy(DummyKind kind)
		{
			if (!Active)
			{
				yield break;
			}
			int before = PlayerManager.instance.players.Count;
			yield return PlayerAssigner.instance.CreatePlayer((InputDevice)null, true);
			if (PlayerManager.instance.players.Count <= before)
			{
				CustomCardsPlugin.Log.LogWarning((object)"Test map: couldn't create a dummy (player limit?).");
				yield break;
			}
			Player p = PlayerManager.instance.players.Last();
			StripAI(p);
			PlayerAPI component = ((Component)p).GetComponent<PlayerAPI>();
			if ((Object)(object)component != (Object)null)
			{
				((Behaviour)component).enabled = false;
			}
			p.AssignTeamID(1);
			PlayerExtensions.AssignColorID(p, (kind == DummyKind.Target) ? 1 : 3);
			TestDummy d = ((Component)p).gameObject.AddComponent<TestDummy>();
			d.Kind = kind;
			d.Home = ((kind == DummyKind.Target) ? TargetSpawn : ShooterSpawn);
			yield return null;
			Teleport(p, d.Home);
		}

		private static void StripAI(Player p)
		{
			MonoBehaviour[] componentsInChildren = ((Component)p).GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					Type type = ((object)val).GetType();
					if (!(type == typeof(PlayerAPI)) && (type.Name.Contains("AI") || (type.Namespace != null && type.Namespace.Contains("AI"))))
					{
						Object.Destroy((Object)(object)val);
					}
				}
			}
		}

		public static void Teleport(Player p, Vector3 pos)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)p == (Object)null))
			{
				((Component)p).transform.position = pos;
				if ((Object)(object)p.data.playerVel != (Object)null)
				{
					Velocity.Invoke(p.data.playerVel) = Vector2.zero;
				}
				PlayerCollision component = ((Component)p).GetComponent<PlayerCollision>();
				if ((Object)(object)component != (Object)null)
				{
					component.IgnoreWallForFrames(2);
				}
			}
		}
	}
	[HarmonyPatch(typeof(MapManager), "GetRandomMap")]
	internal static class TestMapPickLevel
	{
		private static bool Prefix(MapManager __instance, ref string __result)
		{
			if (!TestMap.Active || __instance.levels == null || __instance.levels.Length == 0)
			{
				return true;
			}
			__result = __instance.levels[0];
			return false;
		}
	}
	[HarmonyPatch(typeof(MapManager), "OnLevelFinishedLoading")]
	internal static class TestMapBuildPatch
	{
		private static void Prefix(Scene scene)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			if (TestMap.Active)
			{
				TestMap.BuildFrom(scene);
			}
		}
	}
	[HarmonyPatch(typeof(GM_Test), "PlayerWasAdded")]
	internal static class TestMapPlayerAddedPatch
	{
		private static void Postfix(Player player)
		{
			TestMap.OnPlayerAdded(player);
		}
	}
	[HarmonyPatch(typeof(HealthHandler), "RPCA_Die")]
	internal static class TestMapNoDeathPatch
	{
		[HarmonyPriority(800)]
		private static bool Prefix(HealthHandler __instance)
		{
			Player component = ((Component)__instance).GetComponent<Player>();
			if (!TestMap.IsImmortal(component))
			{
				return true;
			}
			component.data.health = component.data.maxHealth;
			return false;
		}
	}
	[HarmonyPatch(typeof(PlayerAssigner), "LateUpdate")]
	internal static class TestMapJoinPatch
	{
		private static bool Prefix()
		{
			if (!TestMap.Active)
			{
				return true;
			}
			TestMap.HandleJoining();
			return false;
		}
	}
	public class TestMapUI : MonoBehaviour
	{
		public const string LockKey = "CustomCards_TestMap";

		private bool visible = true;

		private Rect mainRect = new Rect(15f, 110f, 450f, 820f);

		private Rect logRect = new Rect(-1f, 110f, 500f, 600f);

		private int tab;

		private int targetIndex;

		private string search = "";

		private Vector2 cardScroll;

		private Vector2 loadoutScroll;

		private Vector2 logScroll;

		private Vector2 statsScroll;

		private float busyUntil;

		private bool mouseOver;

		private bool logOnlyDummies;

		private float scale = 1f;

		private List<CardInfo> cards;

		private Dictionary<CardInfo, string> categories;

		private float cardsRefreshedAt = -100f;

		private GUIStyle small;

		private GUIStyle smallDim;

		private GUIStyle bold;

		private GUIStyle richButton;

		private GUIStyle worldNumber;

		private GUIStyle worldLabel;

		private GUIStyle shadow;

		private static readonly string[] Tabs = new string[4] { "Cards", "Dummies", "Objects", "Tools" };

		private const string AllMods = "All mods";

		private string modFilter = "All mods";

		private string[] modNames = new string[1] { "All mods" };

		private static readonly string[] Targets = new string[3] { "You", "Target dummy", "Shooter dummy" };

		private static readonly float[] Speeds = new float[4] { 0.25f, 0.5f, 1f, 1.5f };

		private static readonly string[] SpeedNames = new string[4] { "0.25×", "0.5×", "1×", "1.5×" };

		private const float NumberLifetime = 1.2f;

		private void Update()
		{
			if (!TestMap.Active)
			{
				mouseOver = false;
				return;
			}
			if (Input.GetKeyDown((KeyCode)283))
			{
				visible = !visible;
			}
			Unbound.lockInputBools["CustomCards_TestMap"] = visible && (mouseOver || GUIUtility.keyboardControl != 0);
		}

		private void OnGUI()
		{
			//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_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Expected O, but got Unknown
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: 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_0110: Expected O, but got Unknown
			//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_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: 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_0168: Invalid comparison between Unknown and I4
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Invalid comparison between Unknown and I4
			if (!TestMap.Active)
			{
				return;
			}
			InitStyles();
			scale = Mathf.Max(0.5f, (float)Screen.height / 1080f);
			GUI.matrix = Matrix4x4.Scale(new Vector3(scale, scale, 1f));
			float num = (float)Screen.width / scale;
			DrawWorldText();
			if (!visible)
			{
				GUI.Label(new Rect(10f, 8f, 400f, 24f), "F2: show test map panel", small);
				mouseOver = false;
				return;
			}
			if (((Rect)(ref logRect)).x < 0f)
			{
				((Rect)(ref logRect)).x = num - ((Rect)(ref logRect)).width - 15f;
			}
			mainRect = GUI.Window(73001, mainRect, new WindowFunction(DrawMain), "TEST MAP   (F2 hides)");
			logRect = GUI.Window(73002, logRect, new WindowFunction(DrawLog), "DAMAGE LOG");
			Vector2 mousePosition = Event.current.mousePosition;
			mouseOver = ((Rect)(ref mainRect)).Contains(mousePosition) || ((Rect)(ref logRect)).Contains(mousePosition);
			if ((int)Event.current.type == 0 && !mouseOver)
			{
				GUIUtility.keyboardControl = 0;
			}
			if ((int)Event.current.type == 4 && (int)Event.current.keyCode == 27)
			{
				GUIUtility.keyboardControl = 0;
			}
		}

		private void InitStyles()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Expected O, but got Unknown
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Expected O, but got Unknown
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Expected O, but got Unknown
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Expected O, but got Unknown
			if (small == null)
			{
				small = new GUIStyle(GUI.skin.label)
				{
					fontSize = 13,
					wordWrap = true,
					richText = true
				};
				GUIStyle val = new GUIStyle(small);
				val.normal.textColor = new Color(0.7f, 0.75f, 0.8f);
				smallDim = val;
				bold = new GUIStyle(small)
				{
					fontStyle = (FontStyle)1,
					fontSize = 14
				};
				richButton = new GUIStyle(GUI.skin.button)
				{
					richText = true,
					alignment = (TextAnchor)3,
					fontSize = 13
				};
				worldNumber = new GUIStyle(GUI.skin.label)
				{
					fontSize = 24,
					fontStyle = (FontStyle)1,
					alignment = (TextAnchor)4,
					richText = false
				};
				worldLabel = new GUIStyle(GUI.skin.label)
				{
					fontSize = 14,
					alignment = (TextAnchor)1,
					richText = true
				};
				GUIStyle val2 = new GUIStyle(worldNumber);
				val2.normal.textColor = Color.black;
				shadow = val2;
			}
		}

		private void DrawMain(int id)
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			tab = GUILayout.Toolbar(tab, Tabs, Array.Empty<GUILayoutOption>());
			GUILayout.Space(4f);
			switch (tab)
			{
			case 0:
				DrawCardsTab();
				break;
			case 1:
				DrawDummiesTab();
				break;
			case 2:
				DrawObjectsTab();
				break;
			default:
				DrawToolsTab();
				break;
			}
			GUI.DragWindow(new Rect(0f, 0f, 10000f, 22f));
		}

		private Player SelectedPlayer()
		{
			if (targetIndex != 0)
			{
				return TestMap.Dummy((targetIndex != 1) ? DummyKind.Shooter : DummyKind.Target);
			}
			return TestMap.Human;
		}

		private void DrawCardsTab()
		{
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f9: 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)
			GUILayout.Label("Give cards to:", small, Array.Empty<GUILayoutOption>());
			targetIndex = GUILayout.Toolbar(targetIndex, Targets, Array.Empty<GUILayoutOption>());
			Player val = SelectedPlayer();
			if ((Object)(object)val == (Object)null)
			{
				GUILayout.Label((targetIndex == 0) ? "<color=#ffcc66>Press jump (or any controller button) to join first.</color>" : "<color=#ffcc66>That dummy isn't here. Dummies tab → Respawn missing dummies.</color>", small, Array.Empty<GUILayoutOption>());
			}
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Search", small, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) });
			search = GUILayout.TextField(search, Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("×", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(24f) }))
			{
				search = "";
				GUIUtility.keyboardControl = 0;
			}
			GUILayout.EndHorizontal();
			RefreshCards();
			int num = Array.IndexOf(modNames, modFilter);
			if (num < 0)
			{
				num = 0;
				modFilter = "All mods";
			}
			int num2 = GUILayout.SelectionGrid(num, modNames, Mathf.Min(3, modNames.Length), Array.Empty<GUILayoutOption>());
			modFilter = modNames[num2];
			string text = search.Trim().ToLower();
			cardScroll = GUILayout.BeginScrollView(cardScroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height((modNames.Length > 3) ? 290f : 310f) });
			foreach (CardInfo card in cards)
			{
				if (text.Length > 0 && !card.cardName.ToLower().Contains(text))
				{
					continue;
				}
				string value;
				string text2 = (categories.TryGetValue(card, out value) ? value : "");
				if (!(modFilter != "All mods") || !(text2 != modFilter))
				{
					string text3 = $"{card.cardName}   <size=11><color=#8fa0b0>{card.rarity} · {text2}</color></size>";
					GUI.enabled = (Object)(object)val != (Object)null && Time.time >= busyUntil;
					if (GUILayout.Button(text3, richButton, Array.Empty<GUILayoutOption>()))
					{
						AddCard(val, card);
					}
					GUI.enabled = true;
				}
			}
			GUILayout.EndScrollView();
			GUILayout.Space(6f);
			List<CardInfo> list = (((Object)(object)val != (Object)null) ? val.data.currentCards : new List<CardInfo>());
			GUILayout.Label($"Loadout ({list.Count} cards)" + ((Time.time < busyUntil) ? "  <color=#8fa0b0>updating…</color>" : ""), bold, Array.Empty<GUILayoutOption>());
			loadoutScroll = GUILayout.BeginScrollView(loadoutScroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(230f) });
			for (int i = 0; i < list.Count; i++)
			{
				if (!((Object)(object)list[i] == (Object)null))
				{
					GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
					GUILayout.Label($"{i + 1}. {list[i].cardName}", small, Array.Empty<GUILayoutOption>());
					GUI.enabled = Time.time >= busyUntil;
					if (GUILayout.Button("Remove", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) }))
					{
						RemoveCard(val, i);
					}
					GUI.enabled = true;
					GUILayout.EndHorizontal();
				}
			}
			GUILayout.EndScrollView();
			GUI.enabled = (Object)(object)val != (Object)null && list.Count > 0 && Time.time >= busyUntil;
			if (GUILayout.Button("Remove all cards", Array.Empty<GUILayoutOption>()))
			{
				RemoveAll(val);
			}
			GUI.enabled = true;
			GUILayout.Label("<color=#8fa0b0>Sandbox chat still works too: press Enter, type a card name, then shoot the card.</color>", small, Array.Empty<GUILayoutOption>());
		}

		private void RefreshCards()
		{
			if (cards != null && Time.time - cardsRefreshedAt < 5f)
			{
				return;
			}
			cardsRefreshedAt = Time.time;
			categories = new Dictionary<CardInfo, string>();
			foreach (KeyValuePair<string, Card> card in CardManager.cards)
			{
				if ((Object)(object)card.Value?.cardInfo != (Object)null && !categories.ContainsKey(card.Value.cardInfo))
				{
					categories[card.Value.cardInfo] = card.Value.category;
				}
			}
			cards = (from c in categories.Keys
				where (Object)(object)c != (Object)null
				orderby c.cardName
				select c).ToList();
			modNames = new string[1] { "All mods" }.Concat(from v in categories.Values.Where((string v) => !string.IsNullOrEmpty(v)).Distinct()
				orderby (!(v == "Vanilla")) ? v : ""
				select v).ToArray();
		}

		private void DrawObjectsTab()
		{
			GUILayout.Label("Physics objects", bold, Array.Empty<GUILayoutOption>());
			foreach (string prop in TestMap.PropList)
			{
				bool flag = TestMap.IsPropEnabled(prop);
				bool flag2 = GUILayout.Toggle(flag, " " + TestMap.PropLabel(prop), Array.Empty<GUILayoutOption>());
				if (flag2 != flag)
				{
					TestMap.SetPropEnabled(prop, flag2);
				}
			}
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("Enable all", Array.Empty<GUILayoutOption>()))
			{
				foreach (string item in TestMap.PropList.ToList())
				{
					TestMap.SetPropEnabled(item, on: true);
				}
			}
			if (GUILayout.Button("Disable all", Array.Empty<GUILayoutOption>()))
			{
				foreach (string item2 in TestMap.PropList.ToList())
				{
					TestMap.SetPropEnabled(item2, on: false);
				}
			}
			GUILayout.EndHorizontal();
			GUILayout.Label("<color=#8fa0b0>Turning one back on spawns a fresh copy in its spot. Leftover debris goes away with Tools → Reset physics objects.</color>", small, Array.Empty<GUILayoutOption>());
			GUILayout.Space(10f);
			GUILayout.Label("Dummies", bold, Array.Empty<GUILayoutOption>());
			DummyKind[] array = new DummyKind[2]
			{
				DummyKind.Target,
				DummyKind.Shooter
			};
			foreach (DummyKind dummyKind in array)
			{
				Player val = TestMap.Dummy(dummyKind);
				string text = ((dummyKind == DummyKind.Target) ? " Target dummy" : " Shooter dummy");
				if ((Object)(object)val == (Object)null)
				{
					GUILayout.Label("<color=#ffcc66>" + text.Trim() + " missing (Dummies tab → Respawn)</color>", small, Array.Empty<GUILayoutOption>());
					continue;
				}
				bool flag3 = TestMap.IsDummyEnabled(dummyKind);
				bool flag4 = GUILayout.Toggle(flag3, text, Array.Empty<GUILayoutOption>());
				if (flag4 != flag3)
				{
					TestMap.SetDummyEnabled(dummyKind, flag4);
				}
			}
			GUILayout.Label("<color=#8fa0b0>A disabled dummy is hidden and out of play: bullets pass through and cards like One Man Army don't count it.</color>", small, Array.Empty<GUILayoutOption>());
		}

		private void AddCard(Player target, CardInfo card)
		{
			if (!((Object)(object)target == (Object)null) && !((Object)(object)card == (Object)null))
			{
				Cards.instance.AddCardToPlayer(target, card, false, "", 0f, 0f, true);
			}
		}

		private void RemoveCard(Player target, int index)
		{
			if (!((Object)(object)target == (Object)null))
			{
				CustomEffects.ClearAllReversibleEffects(((Component)target).gameObject);
				Cards.instance.RemoveCardFromPlayer(target, index, true);
				busyUntil = Time.time + 0.5f;
			}
		}

		private void RemoveAll(Player target)
		{
			CustomEffects.ClearAllReversibleEffects(((Component)target).gameObject);
			Cards.instance.RemoveAllCardsFromPlayer(target, true);
			busyUntil = Time.time + 0.3f;
		}

		private void DrawDummiesTab()
		{
			//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
			TestMap.DummiesImmortal = GUILayout.Toggle(TestMap.DummiesImmortal, " Immortal (lethal hits refill HP instead of killing)", Array.Empty<GUILayoutOption>());
			TestMap.DummiesAutoHeal = GUILayout.Toggle(TestMap.DummiesAutoHeal, " Auto-heal 2.5s after the last hit", Array.Empty<GUILayoutOption>());
			TestMap.DummiesWalkBack = GUILayout.Toggle(TestMap.DummiesWalkBack, " Walk back to their spot after being knocked away", Array.Empty<GUILayoutOption>());
			GUILayout.Label("<color=#8fa0b0>Turn immortality off to test kill effects (Detonater, Bloodthirsty). The sandbox revives them after 2.5s.</color>", small, Array.Empty<GUILayoutOption>());
			GUILayout.Space(8f);
			DrawDummy(TestMap.Dummy(DummyKind.Target));
			GUILayout.Space(8f);
			Player val = TestMap.Dummy(DummyKind.Shooter);
			DrawDummy(val);
			if ((Object)(object)val != (Object)null)
			{
				TestMap.ShooterFiring = GUILayout.Toggle(TestMap.ShooterFiring, " Shooting at you", Array.Empty<GUILayoutOption>());
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.Label($"Fires every {TestMap.ShooterInterval:0.0#}s", small, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) });
				if (GUILayout.Button("−", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(30f) }))
				{
					TestMap.ShooterInterval = Mathf.Max(0.1f, TestMap.ShooterInterval - ((TestMap.ShooterInterval > 1f) ? 0.5f : 0.1f));
				}
				if (GUILayout.Button("+", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(30f) }))
				{
					TestMap.ShooterInterval = Mathf.Min(5f, TestMap.ShooterInterval + ((TestMap.ShooterInterval >= 1f) ? 0.5f : 0.1f));
				}
				GUILayout.EndHorizontal();
				Gun gun = val.data.weaponHandler.gun;
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.Label($"Bullet damage {gun.damage * 55f:0.#}", small, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) });
				if (GUILayout.Button("÷2", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(36f) }))
				{
					gun.damage *= 0.5f;
				}
				if (GUILayout.Button("×2", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(36f) }))
				{
					gun.damage *= 2f;
				}
				if (GUILayout.Button("55", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(36f) }))
				{
					gun.damage = 1f;
				}
				GUILayout.EndHorizontal();
				GUILayout.Label("<color=#8fa0b0>Give the shooter cards from the Cards tab to test what they do to you.</color>", small, Array.Empty<GUILayoutOption>());
			}
			GUILayout.Space(10f);
			if (GUILayout.Button("Respawn missing dummies", Array.Empty<GUILayoutOption>()))
			{
				TestMap.RespawnMissingDummies();
			}
			if (!GUILayout.Button("Send dummies back to their spots", Array.Empty<GUILayoutOption>()))
			{
				return;
			}
			DummyKind[] array = new DummyKind[2]
			{
				DummyKind.Target,
				DummyKind.Shooter
			};
			for (int i = 0; i < array.Length; i++)
			{
				Player val2 = TestMap.Dummy(array[i]);
				if ((Object)(object)val2 != (Object)null)
				{
					TestMap.Teleport(val2, ((Component)val2).GetComponent<TestDummy>().Home);
				}
			}
		}

		private void DrawDummy(Player p)
		{
			if ((Object)(object)p == (Object)null)
			{
				GUILayout.Label("<color=#ffcc66>(dummy missing)</color>", small, Array.Empty<GUILayoutOption>());
				return;
			}
			TestDummy component = ((Component)p).GetComponent<TestDummy>();
			GUILayout.Label(component.Name, bold, Array.Empty<GUILayoutOption>());
			GUILayout.Label(p.data.dead ? "Dead (reviving…)" : ($"HP {p.data.health:0.#} / {p.data.maxHealth:0.#}    DPS (3s) {component.Dps:0.#}\n" + $"Total {component.TotalDamage:0.#} over {component.Hits} hits    Biggest hit {component.BiggestHit:0.#}"), small, Array.Empty<GUILayoutOption>());
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Max HP", small, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(55f) });
			float[] array = new float[4] { 100f, 250f, 500f, 1000f };
			for (int i = 0; i < array.Length; i++)
			{
				float num = array[i];
				if (GUILayout.Button(num.ToString("0"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) }))
				{
					p.data.maxHealth = num;
					p.data.health = num;
				}
			}
			if (GUILayout.Button("Reset stats", Array.Empty<GUILayoutOption>()))
			{
				component.ResetStats();
			}
			GUILayout.EndHorizontal();
		}

		private void DrawToolsTab()
		{
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			if (GUILayout.Button("Reset physics objects", Array.Empty<GUILayoutOption>()))
			{
				TestMap.ResetProps();
			}
			if (GUILayout.Button("Clear bullets and lingering effects", Array.Empty<GUILayoutOption>()))
			{
				TestMap.ClearBullets();
			}
			if (GUILayout.Button("Reset everything (props, bullets, HP, positions, log)", Array.Empty<GUILayoutOption>()))
			{
				TestMap.ResetEverything();
			}
			if (GUILayout.Button("Place Treasure map X (normally happens each round)", Array.Empty<GUILayoutOption>()))
			{
				TreasureMap.PlaceNow();
			}
			GUILayout.Space(8f);
			GUILayout.Label("You", bold, Array.Empty<GUILayoutOption>());
			TestMap.GodMode = GUILayout.Toggle(TestMap.GodMode, " God mode (lethal hits refill your HP)", Array.Empty<GUILayoutOption>());
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			Player human = TestMap.Human;
			GUI.enabled = (Object)(object)human != (Object)null;
			if (GUILayout.Button("Heal to full", Array.Empty<GUILayoutOption>()) && (Object)(object)human != (Object)null)
			{
				human.data.health = human.data.maxHealth;
			}
			if (GUILayout.Button("Back to spawn", Array.Empty<GUILayoutOption>()) && (Object)(object)human != (Object)null)
			{
				TestMap.Teleport(human, TestMap.PlayerSpawn);
			}
			if (GUILayout.Button("Refill block", Array.Empty<GUILayoutOption>()) && (Object)(object)human != (Object)null)
			{
				human.data.block.ResetCD(false);
			}
			GUI.enabled = true;
			GUILayout.EndHorizontal();
			GUILayout.Space(8f);
			GUILayout.Label("Game speed", bold, Array.Empty<GUILayoutOption>());
			int num = Array.IndexOf(Speeds, TestMap.TimeScale);
			int num2 = GUILayout.Toolbar((num < 0) ? 2 : num, SpeedNames, Array.Empty<GUILayoutOption>());
			if (Speeds[num2] != TestMap.TimeScale)
			{
				TestMap.SetTimeScale(Speeds[num2]);
			}
			GUILayout.Label("<color=#8fa0b0>Slows players and bullets; boxes still fall at normal speed.</color>", small, Array.Empty<GUILayoutOption>());
			GUILayout.Space(8f);
			GUILayout.Label("Stats of:", bold, Array.Empty<GUILayoutOption>());
			targetIndex = GUILayout.Toolbar(targetIndex, Targets, Array.Empty<GUILayoutOption>());
			statsScroll = GUILayout.BeginScrollView(statsScroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(330f) });
			GUILayout.Label(StatsText(SelectedPlayer()), small, Array.Empty<GUILayoutOption>());
			GUILayout.EndScrollView();
		}

		private static string StatsText(Player p)
		{
			if ((Object)(object)p == (Object)null)
			{
				return "(not here)";
			}
			CharacterData data = p.data;
			Gun gun = data.weaponHandler.gun;
			GunAmmo componentInChildren = ((Component)gun).GetComponentInChildren<GunAmmo>();
			CharacterStatModifiers stats = data.stats;
			float num = (((Object)(object)componentInChildren != (Object)null) ? ((componentInChildren.reloadTime + componentInChildren.reloadTimeAdd) * componentInChildren.reloadTimeMultiplier) : 0f);
			return $"HP  {data.health:0.#} / {data.maxHealth:0.#}    regen {data.healthHandler.regeneration:0.#}/s\n" + $"Bullet damage  {gun.damage * 55f:0.#}  (×{gun.damage:0.##})\n" + $"Bullets per shot  {gun.numberOfProjectiles}    bounces {gun.reflects}\n" + $"Attack speed  {gun.attackSpeed:0.###}s  (lower = faster)\n" + $"Bullet speed  ×{gun.projectileSpeed:0.##}    sim speed ×{gun.projectielSimulatonSpeed:0.##}\n" + $"Ammo  {(((Object)(object)componentInChildren != (Object)null) ? componentInChildren.maxAmmo : 0)}    reload {num:0.##}s\n" + $"Block cooldown  {data.block.cooldown:0.##}s\n" + $"Move speed  ×{stats.movementSpeed:0.##}    jump ×{stats.jump:0.##}    extra jumps {stats.numberOfJumps}\n" + $"Lifesteal  {stats.lifeSteal:0.##}    size ×{stats.sizeMultiplier:0.##}\n\n" + "Cards: " + string.Join(", ", from c in data.currentCards
				where (Object)(object)c != (Object)null
				select c.cardName);
		}

		private void DrawLog(int id)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0272: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			logOnlyDummies = GUILayout.Toggle(logOnlyDummies, " Only hits on dummies", Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("Clear", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }))
			{
				DamageLog.Records.Clear();
			}
			GUILayout.EndHorizontal();
			logScroll = GUILayout.BeginScrollView(logScroll, Array.Empty<GUILayoutOption>());
			int num = 0;
			foreach (DamageRecord record in DamageLog.Records)
			{
				if (logOnlyDummies && ((Object)(object)record.victim == (Object)null || (Object)(object)((Component)record.victim).GetComponent<TestDummy>() == (Object)null))
				{
					continue;
				}
				num++;
				GUILayout.Label($"{record.source}: {NameOf(record.attacker)} → {NameOf(record.victim)}   <color=#8fa0b0>{Time.time - record.time:0.0}s ago</color>", bold, Array.Empty<GUILayoutOption>());
				foreach (string step in record.steps)
				{
					GUILayout.Label("    " + step, small, Array.Empty<GUILayoutOption>());
				}
				string text;
				if (record.blocked)
				{
					text = "<color=#66ccff>Blocked: no damage</color>";
				}
				else if (record.applied < 0f)
				{
					text = $"<color=#b0ff66>Spread over time: {record.current:0.#} total (shows as separate ticks)</color>";
				}
				else
				{
					text = $"<color=#ff7766>HP {record.hpBefore:0.#} → {(record.refilled ? 0f : record.hpAfter):0.#}  (−{record.applied:0.#} of {record.maxHp:0} max)</color>";
					if (record.refilled)
					{
						text += "\n    <color=#ffd633>Lethal: refilled to full (immortal)</color>";
					}
				}
				GUILayout.Label("    " + text, small, Array.Empty<GUILayoutOption>());
				GUILayout.Space(6f);
			}
			if (num == 0)
			{
				GUILayout.Label("No hits yet. Shoot a dummy!", smallDim, Array.Empty<GUILayoutOption>());
			}
			GUILayout.EndScrollView();
			GUI.DragWindow(new Rect(0f, 0f, 10000f, 22f));
		}

		private static string NameOf(Player p)
		{
			if ((Object)(object)p == (Object)null)
			{
				return "?";
			}
			TestDummy component = ((Component)p).GetComponent<TestDummy>();
			if ((Object)(object)component != (Object)null)
			{
				return component.Name;
			}
			Player val = DoublingCherry.MasterOf(p);
			if ((Object)(object)val != (Object)null)
			{
				if (!((Object)(object)val == (Object)(object)TestMap.Human))
				{
					return "Copy of player " + (val.playerID + 1);
				}
				return "Your copy";
			}
			if (!((Object)(object)p == (Object)(object)TestMap.Human))
			{
				return "Player " + (p.playerID + 1);
			}
			return "You";
		}

		private void DrawWorldText()
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			Camera val = (((Object)(object)MainCam.instance != (Object)null) ? MainCam.instance.cam : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Rect val3 = default(Rect);
			for (int num = DamageLog.Numbers.Count - 1; num >= 0; num--)
			{
				DamageLog.FloatingNumber floatingNumber = DamageLog.Numbers[num];
				float num2 = Time.time - floatingNumber.born;
				if (num2 > 1.2f)
				{
					DamageLog.Numbers.RemoveAt(num);
				}
				else
				{
					Vector2 val2 = ToGui(val, floatingNumber.pos + Vector3.up * num2 * 1.5f);
					((Rect)(ref val3))..ctor(val2.x - 100f, val2.y - 15f, 200f, 30f);
					float num3 = 1f - num2 / 1.2f;
					shadow.normal.textColor = new Color(0f, 0f, 0f, num3 * 0.8f);
					GUI.Label(new Rect(((Rect)(ref val3)).x + 2f, ((Rect)(ref val3)).y + 2f, ((Rect)(ref val3)).width, ((Rect)(ref val3)).height), floatingNumber.text, shadow);
					worldNumber.normal.textColor = new Color(floatingNumber.color.r, floatingNumber.color.g, floatingNumber.color.b, num3);
					GUI.Label(val3, floatingNumber.text, worldNumber);
				}
			}
			if ((Object)(object)PlayerManager.instance == (Object)null)
			{
				return;
			}
			foreach (Player player in PlayerManager.instance.players)
			{
				TestDummy testDummy = (((Object)(object)player != (Object)null) ? ((Component)player).GetComponent<TestDummy>() : null);
				if (!((Object)(object)testDummy == (Object)null) && !player.data.dead)
				{
					Vector2 val4 = ToGui(val, ((Component)player).transform.position + Vector3.down * 1.6f);
					GUI.Label(new Rect(val4.x - 120f, val4.y, 240f, 40f), $"<b>{testDummy.Name}</b>\n{player.data.health:0} / {player.data.maxHealth:0} HP   DPS {testDummy.Dps:0}", worldLabel);
				}
			}
		}

		private Vector2 ToGui(Camera cam, Vector3 world)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = cam.WorldToScreenPoint(world);
			return new Vector2(val.x / scale, ((float)Screen.height - val.y) / scale);
		}
	}
}
namespace CustomCards.Patches
{
	[HarmonyPatch(typeof(HealthHandler), "CallTakeDamage")]
	internal static class DamageReductionPatch
	{
		[HarmonyPriority(200)]
		private static void Prefix(HealthHandler __instance, ref Vector2 damage)
		{
			//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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			if (damage == Vector2.zero)
			{
				return;
			}
			Player component = ((Component)__instance).GetComponent<Player>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			float num = ((Vector2)(ref damage)).magnitude;
			int num2 = CardUtils.CountCard(component, "Slippery");
			if (num2 > 0)
			{
				Vector2 val = CardUtils.Velocity(component);
				if (((Vector2)(ref val)).magnitude > 2f)
				{
					float before = num;
					float num3 = Mathf.Min(0.75f, 0.25f * (float)num2);
					num *= 1f - num3;
					DamageLog.Step($"Slippery −{num3 * 100f:0}%", before, num);
				}
			}
			int num4 = CardUtils.CountCard(component, "Plating");
			if (num4 > 0)
			{
				float before2 = num;
				num = Mathf.Max(1f, num - 8f * (float)num4);
				DamageLog.Step($"Plating −{8f * (float)num4:0}", before2, num);
			}
			damage = ((Vector2)(ref damage)).normalized * num;
		}
	}
	[HarmonyPatch(typeof(Gun), "ApplyProjectileStats")]
	internal static class BulletDamageBonusPatch
	{
		private static void Postfix(Gun __instance, GameObject obj)
		{
			Player shooter = __instance.player;
			if ((Object)(object)shooter == (Object)null)
			{
				return;
			}
			ProjectileHit component = obj.GetComponent<ProjectileHit>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			float num = 1f;
			BulletNotes bulletNotes = null;
			if (DamageLog.Enabled)
			{
				bulletNotes = obj.GetComponent<BulletNotes>();
				if ((Object)(object)bulletNotes == (Object)null)
				{
					bulletNotes = obj.AddComponent<BulletNotes>();
				}
				bulletNotes.mods.Clear();
				bulletNotes.fired = component.damage;
			}
			int num2 = CardUtils.CountCard(shooter, "Fragile");
			if (num2 > 0 && shooter.data.maxHealth > 0f)
			{
				float num3 = Mathf.Clamp01(1f - shooter.data.health / shooter.data.maxHealth);
				float num4 = 1f + 1f * (float)num2 * num3;
				num *= num4;
				bulletNotes?.mods.Add($"Fragile ×{num4:0.##} ({num3 * 100f:0}% HP missing)");
			}
			int num5 = CardUtils.CountCard(shooter, "One Man Army");
			if (num5 > 0)
			{
				int num6 = CardUtils.Enemies(shooter).Count((Player e) => Vector2.Distance(Vector2.op_Implicit(((Component)e).transform.position), Vector2.op_Implicit(((Component)shooter).transform.position)) <= 7.5f);
				float num7 = 1f + 0.3f * (float)num5 * (float)num6;
				num *= num7;
				bulletNotes?.mods.Add($"One Man Army ×{num7:0.##} ({num6} enemies near)");
			}
			component.damage *= num;
			if ((Object)(object)bulletNotes != (Object)null)
			{
				bulletNotes.finalAtFire = component.damage;
			}
		}
	}
	[HarmonyPatch(typeof(HealthHandler), "DoDamage")]
	internal static class TookDamagePatch
	{
		private static void Prefix(HealthHandler __instance, out float __state)
		{
			CharacterData component = ((Component)__instance).GetComponent<CharacterData>();
			__state = (Object.op_Implicit((Object)(object)component) ? component.health : 0f);
		}

		private static void Postfix(HealthHandler __instance, float __state)
		{
			CharacterData component = ((Component)__instance).GetComponent<CharacterData>();
			if (!((Object)(object)component == (Object)null) && !(component.health >= __state))
			{
				FlameOnBehaviour component2 = ((Component)__instance).GetComponent<FlameOnBehaviour>();
				if (Object.op_Implicit((Object)(object)component2))
				{
					component2.Ignite();
				}
				WoundedBehaviour component3 = ((Component)__instance).GetComponent<WoundedBehaviour>();
				if (Object.op_Implicit((Object)(object)component3))
				{
					component3.CheckTrigger();
				}
			}
		}
	}
	[HarmonyPatch(typeof(HealthHandler), "RPCA_Die")]
	internal static class PlayerDiedPatch
	{
		private static void Prefix(HealthHandler __instance, out bool __state)
		{
			CharacterData component = ((Component)__instance).GetComponent<CharacterData>();
			__state = Object.op_Implicit((Object)(object)component) && component.isPlaying && !component.dead;
		}

		private static void Postfix(HealthHandler __instance, bool __state)
		{
			if (__state)
			{
				Player component = ((Component)__instance).GetComponent<Player>();
				if (!((Object)(object)component == (Object)null) && component.data.dead)
				{
					Detonater.OnPlayerDied(component);
					Bloodthirsty.OnPlayerDied(component);
				}
			}
		}
	}
	[HarmonyPatch(typeof(ProjectileHit), "RPCA_DoHit")]
	internal static class TeslaHitPatch
	{
		private static void Postfix(ProjectileHit __instance, Vector2 hitPoint, int viewID, int colliderID, bool wasBlocked)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			if (!wasBlocked && !((Object)(object)__instance == (Object)null))
			{
				NormalizeHitWindowPatch.Pending = null;
				Tesla.OnBulletHit(__instance, hitPoint, viewID, colliderID);
			}
		}
	}
	[HarmonyPatch(typeof(GeneralInput), "Update")]
	internal static class BloodthirstyInputPatch
	{
		private static void Postfix(GeneralInput __instance, CharacterData ___data)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			if (__instance.controlledElseWhere || (Object)(object)___data == (Object)null || GameManager.lockInput || !___data.isPlaying)
			{
				return;
			}
			Player player = ___data.player;
			if (!Bloodthirsty.IsForced(player))
			{
				return;
			}
			Player val = CardUtils.ClosestEnemy(player);
			if (!((Object)(object)val == (Object)null))
			{
				float num = ((Component)val).transform.position.x - ((Component)player).transform.position.x;
				if (!(Mathf.Abs(num) < 0.5f))
				{
					__instance.direction = new Vector3(Mathf.Sign(num), __instance.direction.y, 0f);
					__instance.latestPressedDirection = __instance.direction;
				}
			}
		}
	}
	internal static class PerPointResets
	{
		public static void RegisterHooks()
		{
			GameModeManager.AddHook("GameStart", (Func<IGameModeHandler, IEnumerator>)((IGameModeHandler _) => Reset()));
			GameModeManager.AddHook("PointStart", (Func<IGameModeHandler, IEnumerator>)((IGameModeHandler _) => Reset()));
		}

		private static IEnumerator Reset()
		{
			WoundedBehaviour.UsedThisPoint.Clear();
			Bloodthirsty.Reset();
			yield break;
		}
	}
	internal static class GreedPicks
	{
		private static readonly Dictionary<int, int> bonusPicks = new Dictionary<int, int>();

		private static readonly HashSet<int> skippedPlayerIDs = new HashSet<int>();

		private static bool decisionReceived;

		internal static bool StartingBonusPick;

		private const float DecisionTimeout = 3f;

		public static void RegisterHooks()
		{
			GameModeManager.AddHook("GameStart", (Func<IGameModeHandler, IEnumerator>)((IGameModeHandler _) => ResetAll()));
			GameModeManager.AddHook("PickStart", (Func<IGameModeHandler, IEnumerator>)OnPickStart);
			GameModeManager.AddHook("PickEnd", (Func<IGameModeHandler, IEnumerator>)((IGameModeHandler _) => ResetAll()));
		}

		public static void AddBonusPicks(int playerID, int count)
		{
			bonusPicks.TryGetValue(playerID, out var value);
			bonusPicks[playerID] = value + count;
		}

		private static IEnumerator ResetAll()
		{
			bonusPicks.Clear();
			skippedPlayerIDs.Clear();
			decisionReceived = false;
			yield break;
		}

		private static IEnumerator OnPickStart(IGameModeHandler gm)
		{
			if (PhotonNetwork.OfflineMode || PhotonNetwork.IsMasterClient)
			{
				int[] array = (from p in PlayerManager.instance.players
					where Random.value < GreedCard.SkipChance(CardUtils.CountCard(p, "Greed"))
					select p.playerID).ToArray();
				NetworkingManager.RPC(typeof(GreedPicks), "RPCA_SetSkippedPlayers", new object[1] { array });
			}
			float waited = 0f;
			while (!decisionReceived && waited < 3f)
			{
				waited += Time.unscaledDeltaTime;
				yield return null;
			}
			if (!decisionReceived)
			{
				CustomCardsPlugin.Log.LogWarning((object)"Greed: no skip decision from host; nobody skipped this pick phase.");
			}
		}

		[UnboundRPC]
		public static void RPCA_SetSkippedPlayers(int[] playerIDs)
		{
			skippedPlayerIDs.Clear();
			foreach (int item in playerIDs)
			{
				skippedPlayerIDs.Add(item);
			}
			decisionReceived = true;
		}

		public static bool IsSkipped(int playerID)
		{
			return skippedPlayerIDs.Contains(playerID);
		}

		public static IEnumerator SkippedPick()
		{
			UIHandler.instance.ShowJoinGameText("GREED - PICK SKIPPED", new Color(0.6f, 0.2f, 0.8f));
			yield return (object)new WaitForSecondsRealtime(1.5f);
			UIHandler.instance.HideJoinGameText();
			UIHandler.instance.StopShowPicker();
			CardChoiceVisuals.instance.Hide();
		}

		public static IEnumerator PickThenBonusPicks(IEnumerator normalPick, int playerID)
		{
			yield return normalPick;
			while (true)
			{
				yield return (object)new WaitForSecondsRealtime(0.25f);
				if (bonusPicks.TryGetValue(playerID, out var value) && value > 0)
				{
					bonusPicks[playerID] = value - 1;
					int num = PlayerManager.instance.players.FindIndex((Player p) => p.playerID == playerID);
					if (num >= 0)
					{
						CardChoiceVisuals.instance.Show(num, true);
						StartingBonusPick = true;
						IEnumerator enumerator;
						try
						{
							enumerator = CardChoice.instance.DoPick(1, playerID, (PickerType)1);
						}
						finally
						{
							StartingBonusPick = false;
						}
						yield return enumerator;
						continue;
					}
					break;
				}
				break;
			}
		}
	}
	[HarmonyPatch(typeof(CardChoice), "DoPick")]
	internal static class GreedDoPickPatch
	{
		private static bool Prefix(int picketIDToSet, PickerType pType, ref IEnumerator __result)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Invalid comparison between Unknown and I4
			if (GreedPicks.StartingBonusPick || (int)pType != 1 || !GreedPicks.IsSkipped(picketIDToSet))
			{
				return true;
			}
			__result = GreedPicks.SkippedPick();
			return false;
		}

		private static void Postfix(int picketIDToSet, PickerType pType, ref IEnumerator __result)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Invalid comparison between Unknown and I4
			if (!GreedPicks.StartingBonusPick && (int)pType == 1)
			{
				__result = GreedPicks.PickThenBonusPicks(__result, picketIDToSet);
			}
		}
	}
	[HarmonyPatch(typeof(Gun), "ApplyProjectileStats")]
	internal static class NeoLifetimePatch
	{
		private static void Postfix(Gun __instance, GameObject obj)
		{
			int num = CardUtils.CountCard(__instance.player, "Neo");
			if (num > 0)
			{
				RemoveAfterSeconds component = obj.GetComponent<RemoveAfterSeconds>();
				if ((Object)(object)component != (Object)null)
				{
					component.seconds /= Mathf.Pow(0.5f, (float)num);
				}
			}
		}
	}
	[HarmonyPatch(typeof(ProjectileHit), "RPCA_DoHit")]
	internal static class NormalizeHitWindowPatch
	{
		internal static ProjectileHit Pending;

		private static void Prefix(ProjectileHit __instance)
		{
			Pending = ((CardUtils.CountCard(__instance.ownPlayer, "Normalize") > 0) ? __instance : null);
		}

		private static Exception Finalizer(Exception __exception)
		{
			Pending = null;
			return __exception;
		}
	}
	[HarmonyPatch(typeof(HealthHandler), "CallTakeDamage")]
	internal static class NormalizeDamagePatch
	{
		private static void Prefix(HealthHandler __instance, ref Vector2 damage)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			ProjectileHit pending = NormalizeHitWindowPatch.Pending;
			if (!((Object)(object)pending == (Object)null))
			{
				NormalizeHitWindowPatch.Pending = null;
				CharacterData component = ((Component)__instance).GetComponent<CharacterData>();
				if (!((Object)(object)component == (Object)null) && !(damage == Vector2.zero))
				{
					int num = CardUtils.CountCard(pending.ownPlayer, "Normalize");
					float num2 = NormalizeCard.PercentFor(((Vector2)(ref damage)).magnitude, Mathf.Max(num, 1));
					float magnitude = ((Vector2)(ref damage)).magnitude;
					damage = ((Vector2)(ref damage)).normalized * (component.maxHealth * num2);
					DamageLog.Step($"Normalize ({num2 * 100f:0.#}% of {component.maxHealth:0} max HP)", magnitude, ((Vector2)(ref damage)).magnitude);
				}
			}
		}
	}
	internal static class PiercerClash
	{
		private static readonly FieldRef<ProjectileHitEmpower, bool> EmpowerDone = AccessTools.FieldRefAccess<ProjectileHitEmpower, bool>("done");

		public static bool Applies(ProjectileHit a, ProjectileHit b, out int stacksA, out int stacksB)
		{
			stacksA = (stacksB = 0);
			if ((Object)(object)a == (Object)null || (Object)(object)b == (Object)null || (Object)(object)a == (Object)(object)b)
			{
				return false;
			}
			Player ownPlayer = a.ownPlayer;
			Player ownPlayer2 = b.ownPlayer;
			if ((Object)(object)ownPlayer == (Object)null || (Object)(object)ownPlayer2 == (Object)null)
			{
				return false;
			}
			stacksA = CardUtils.CountCard(ownPlayer, "Piercer");
			stacksB = CardUtils.CountCard(ownPlayer2, "Piercer");
			if (stacksA == 0 && stacksB == 0)
			{
				return false;
			}
			if (ownPlayer.teamID == ownPlayer2.teamID)
			{
				stacksA = (stacksB = Mathf.Max(stacksA, stacksB));
			}
			return true;
		}

		public static void Resolve(ProjectileHit hitBullet, ProjectileHit incoming, int hitStacks, int incomingStacks, HitInfo hit)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: 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_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: 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_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			if (!ClashMemory.IsNewContact(((Component)hitBullet).gameObject, ((Component)incoming).gameObject))
			{
				return;
			}
			Vector2 val = ContactNormal(hit, ((Component)incoming).gameObject, ((Component)hitBullet).gameObject);
			Vector2 val2 = hit?.point ?? Vector2.op_Implicit(((Component)hitBullet).transform.position);
			ProjectileCollision componentInChildren = ((Component)hitBullet).GetComponentInChildren<ProjectileCollision>();
			ProjectileCollision componentInChildren2 = ((Component)incoming).GetComponentInChildren<ProjectileCollision>();
			if (hitStacks > incomingStacks)
			{
				if (Object.op_Implicit((Object)(object)componentInChildren2))
				{
					componentInChildren2.TakeDamage(float.MaxValue);
				}
				TriggerHitEffects(((Component)hitBullet).gameObject, val2, -val, componentInChildren2);
				return;
			}
			if (incomingStacks > hitStacks)
			{
				if (Object.op_Implicit((Object)(object)componentInChildren))
				{
					componentInChildren.TakeDamage(float.MaxValue);
				}
				TriggerHitEffects(((Component)incoming).gameObject, val2, val, componentInChildren);
				return;
			}
			Reflect(((Component)incoming).gameObject, val);
			Reflect(((Component)hitBullet).gameObject, -val);
			((Component)incoming).transform.position = Vector2.op_Implicit(val2 + val * 0.05f);
			RayCastTrail component = ((Component)incoming).GetComponent<RayCastTrail>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.MoveRay();
			}
			TriggerHitEffects(((Component)incoming).gameObject, val2, val, componentInChildren);
			TriggerHitEffects(((Component)hitBullet).gameObject, val2, -val, componentInChildren2);
		}

		private static Vector2 ContactNormal(HitInfo hit, GameObject incoming, GameObject hitBullet)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result ty