Decompiled source of EvenMoreCards v0.5.0

plugins/EvenMoreCards.dll

Decompiled 12 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.Mono;
using Effects;
using Effects.MotionEasing;
using Game;
using HarmonyLib;
using Menus.UI;
using Microsoft.CodeAnalysis;
using Obstacles;
using Obstacles.ObstacleAffixes;
using Obstacles.ObstacleGameModifiers;
using Player;
using Sounds;
using Sounds.SplitScreenAudio;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Rendering;
using Utils;
using World;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("EvenMoreCards")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.5.0.0")]
[assembly: AssemblyInformationalVersion("0.5.0+7a90ef3734679febe0314885d4aeed55ee43d3c8")]
[assembly: AssemblyProduct("EvenMoreCards")]
[assembly: AssemblyTitle("EvenMoreCards")]
[assembly: AssemblyVersion("0.5.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 EvenMoreCards
{
	internal static class BoostSurface
	{
		private static Surface _surface;

		public static Surface Make(Surface asphalt)
		{
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Expected O, but got Unknown
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			_surface = Cards.CopySurface(asphalt, "EvenMoreCards_Boost");
			Material material = _surface.effects.material;
			Color val = default(Color);
			((Color)(ref val))..ctor(0.3f, 0.8f, 1f);
			string[] array = new string[2] { "_BaseColor", "_Color" };
			foreach (string text in array)
			{
				if (material.HasProperty(text))
				{
					material.SetColor(text, material.GetColor(text) * val);
				}
			}
			ManualLogSource log = Plugin.Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(34, 2, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Boost surface shader '");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(((Object)material.shader).name);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("', tinted: ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(material.HasProperty("_BaseColor") || material.HasProperty("_Color"));
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(".");
			}
			log.LogInfo(val2);
			return _surface;
		}

		[HarmonyPatch(typeof(SphereCarController), "ApplyModifiers")]
		[HarmonyPostfix]
		private static void Boost(SphereCarController __instance)
		{
			if (!((Object)(object)_surface == (Object)null) && !((Object)(object)__instance.CurrentSurface != (Object)(object)_surface) && __instance.OnGround)
			{
				float value = Plugin.BoostMultiplier.Value;
				__instance.maxSpeed *= value;
				if (__instance.Acceleration > 0f)
				{
					__instance.speed *= value;
				}
				if (__instance.CarSpeedRaw < __instance.maxSpeed)
				{
					__instance.AddSpeed(Plugin.BoostPush.Value, (ModifierValueType)1);
				}
			}
		}
	}
	internal static class Bumper
	{
		private const float Size = 0.75f;

		public static void Build(Obstacle donut)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			if (((Component)donut).transform.childCount > 0)
			{
				Transform child = ((Component)donut).transform.GetChild(0);
				child.localScale *= 0.75f;
				child.localPosition += new Vector3(0f, 0f, -0.14f);
			}
			BumperFx bumperFx = ((Component)donut).gameObject.AddComponent<BumperFx>();
			foreach (Collider item in from c in ((Component)donut).GetComponentsInChildren<Collider>(true)
				where !c.isTrigger
				select c)
			{
				BounceZone obj = ((Component)item).gameObject.AddComponent<BounceZone>();
				obj.bounceFactor = Plugin.BumperStrength.Value;
				obj.counterNegativeVelocity = true;
				obj.onBounce01 = new UnityEvent<float>();
				obj.onBounce01.AddListener((UnityAction<float>)bumperFx.Hit);
			}
			Reskin(donut);
		}

		private static void Reskin(Obstacle donut)
		{
			Mesh val = Bundle.Get<Mesh>("Bumper");
			Transform val2 = ((((Component)donut).transform.childCount > 0) ? ((Component)donut).transform.GetChild(0) : null);
			MeshRenderer val3 = (((Object)(object)val2 != (Object)null) ? ((Component)val2).GetComponent<MeshRenderer>() : null);
			MeshRenderer val4 = (((Object)(object)val2 != (Object)null) ? (from Transform t in (IEnumerable)val2
				select ((Component)t).GetComponent<MeshRenderer>()).FirstOrDefault((Func<MeshRenderer, bool>)((MeshRenderer r) => (Object)(object)r != (Object)null)) : null);
			if (!((Object)(object)val == (Object)null) && !((Object)(object)val3 == (Object)null) && !((Object)(object)val4 == (Object)null))
			{
				((Component)val2).GetComponent<MeshFilter>().sharedMesh = val;
				Material[] sharedMaterials = ((Renderer)val3).sharedMaterials;
				((Renderer)val3).materials = (Material[])(object)new Material[3]
				{
					sharedMaterials[0],
					sharedMaterials[1],
					((Renderer)val4).sharedMaterial
				};
				((Renderer)val4).enabled = false;
			}
		}
	}
	internal class BumperFx : MonoBehaviour
	{
		private const float PunchTime = 0.35f;

		private static SplitScreenAudioAudioClipCollection _soft;

		private static SplitScreenAudioAudioClipCollection _strong;

		private Transform _visual;

		private Vector3 _baseScale;

		private Transform[] _colliders;

		private Vector3[] _colliderScales;

		private Coroutine _punch;

		private void Awake()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			_visual = ((((Component)this).transform.childCount > 0) ? ((Component)this).transform.GetChild(0) : ((Component)this).transform);
			_baseScale = _visual.localScale;
			_colliders = (from c in ((Component)_visual).GetComponentsInChildren<Collider>(true)
				select ((Component)c).transform into t
				where (Object)(object)t != (Object)(object)_visual
				select t).ToArray();
			_colliderScales = _colliders.Select((Transform t) => t.localScale).ToArray();
		}

		public void Hit(float strength)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_soft == (Object)null)
			{
				SplitScreenAudioAudioClipCollection[] source = Resources.FindObjectsOfTypeAll<SplitScreenAudioAudioClipCollection>();
				_soft = ((IEnumerable<SplitScreenAudioAudioClipCollection>)source).FirstOrDefault((Func<SplitScreenAudioAudioClipCollection, bool>)((SplitScreenAudioAudioClipCollection c) => ((Object)c).name == "SoftBounceClipCollection"));
				_strong = ((IEnumerable<SplitScreenAudioAudioClipCollection>)source).FirstOrDefault((Func<SplitScreenAudioAudioClipCollection, bool>)((SplitScreenAudioAudioClipCollection c) => ((Object)c).name == "StrongBounceClipCollection"));
			}
			SplitScreenAudioManager.PlayClipAtPoint(((Component)this).transform.position, (strength > 0.5f) ? _strong : _soft, 1f, 1f);
			if (_punch != null)
			{
				((MonoBehaviour)this).StopCoroutine(_punch);
			}
			_punch = ((MonoBehaviour)this).StartCoroutine(Punch(0.15f + 0.25f * strength));
		}

		private IEnumerator Punch(float amount)
		{
			for (float t = 0f; t < 0.35f; t += Time.deltaTime)
			{
				float num = t / 0.35f;
				float num2 = Mathf.Sin(num * MathF.PI * 2.5f) * (1f - num);
				float num3 = 1f + amount * num2;
				float num4 = 1f - amount * 0.5f * num2;
				_visual.localScale = new Vector3(_baseScale.x * num3, _baseScale.y * num3, _baseScale.z * num4);
				for (int i = 0; i < _colliders.Length; i++)
				{
					_colliders[i].localScale = new Vector3(_colliderScales[i].x / num3, _colliderScales[i].y / num3, _colliderScales[i].z / num4);
				}
				yield return null;
			}
			_visual.localScale = _baseScale;
			for (int j = 0; j < _colliders.Length; j++)
			{
				_colliders[j].localScale = _colliderScales[j];
			}
		}
	}
	internal static class Bundle
	{
		private const string BundleFile = "evenmorecards.bundle";

		private static Dictionary<(string, Type), Object> _assets;

		public static void Load()
		{
			string text = Path.Combine(Path.GetDirectoryName(typeof(Bundle).Assembly.Location), "evenmorecards.bundle");
			if (!File.Exists(text))
			{
				Plugin.Log.LogInfo((object)"No asset bundle next to the DLL; cards use the game's own sounds and models.");
				return;
			}
			AssetBundle assetBundle = AssetBundle.LoadFromFileAsync(text).assetBundle;
			if ((Object)(object)assetBundle == (Object)null)
			{
				Plugin.Log.LogWarning((object)"Asset bundle failed to load; was it built with Unity 2022.3 for Windows?");
				return;
			}
			Object[] allAssets = assetBundle.LoadAllAssetsAsync().allAssets;
			_assets = new Dictionary<(string, Type), Object>();
			Object[] array = allAssets;
			foreach (Object val in array)
			{
				_assets[(val.name, ((object)val).GetType())] = val;
			}
			Plugin.Log.LogInfo((object)("Bundle loaded: " + string.Join(", ", allAssets.Select((Object a) => a.name + " (" + ((object)a).GetType().Name + ")"))));
		}

		public static T Get<T>(string name) where T : Object
		{
			if (_assets == null || !_assets.TryGetValue((name, typeof(T)), out var value))
			{
				return default(T);
			}
			return (T)(object)value;
		}
	}
	internal static class Buzzsaw
	{
		internal static Transform HitSparks;

		internal const float GroundZ = -0.56f;

		internal const float AxleHeight = 0.8f;

		internal const float BladeRadius = 1.5f;

		internal const float Travel = 0.9f;

		private static Material _dark;

		private static Material _steel;

		public static void Build(Obstacle donut)
		{
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Expected O, but got Unknown
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0324: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e3: Unknown result type (might be due to invalid IL or missing references)
			Mesh val = Bundle.Get<Mesh>("BuzzsawBase");
			Mesh val2 = Bundle.Get<Mesh>("BuzzsawBlade");
			Transform val3 = ((((Component)donut).transform.childCount > 0) ? ((Component)donut).transform.GetChild(0) : null);
			MeshRenderer val4 = (((Object)(object)val3 != (Object)null) ? ((Component)val3).GetComponent<MeshRenderer>() : null);
			MeshRenderer val5 = (((Object)(object)val3 != (Object)null) ? (from Transform t in (IEnumerable)val3
				select ((Component)t).GetComponent<MeshRenderer>()).FirstOrDefault((Func<MeshRenderer, bool>)((MeshRenderer r) => (Object)(object)r != (Object)null)) : null);
			if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null || (Object)(object)val4 == (Object)null || (Object)(object)val5 == (Object)null)
			{
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExWarningLogInterpolatedStringHandler val6 = new BepInExWarningLogInterpolatedStringHandler(88, 4, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val6).AppendLiteral("Buzzsaw: parts missing (base mesh ");
					((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<bool>((Object)(object)val != (Object)null);
					((BepInExLogInterpolatedStringHandler)val6).AppendLiteral(", blade mesh ");
					((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<bool>((Object)(object)val2 != (Object)null);
					((BepInExLogInterpolatedStringHandler)val6).AppendLiteral(", ");
					((BepInExLogInterpolatedStringHandler)val6).AppendLiteral("donut ");
					((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<bool>((Object)(object)val4 != (Object)null);
					((BepInExLogInterpolatedStringHandler)val6).AppendLiteral(", icing ");
					((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<bool>((Object)(object)val5 != (Object)null);
					((BepInExLogInterpolatedStringHandler)val6).AppendLiteral("); leaving a plain donut.");
				}
				log.LogWarning(val6);
				return;
			}
			if ((Object)(object)_dark == (Object)null)
			{
				_dark = Urp.Lit(new Color(0.08f, 0.08f, 0.09f), 0.4f, 0.8f);
				_steel = Urp.Lit(new Color(0.78f, 0.8f, 0.84f), 0.85f, 1f);
				if ((Object)(object)_dark == (Object)null)
				{
					return;
				}
			}
			Material val7 = ((Renderer)val4).sharedMaterials[0];
			Material sharedMaterial = ((Renderer)val5).sharedMaterial;
			Renderer[] componentsInChildren = ((Component)val3).GetComponentsInChildren<Renderer>(true);
			for (int num = 0; num < componentsInChildren.Length; num++)
			{
				componentsInChildren[num].enabled = false;
			}
			Collider[] componentsInChildren2 = ((Component)val3).GetComponentsInChildren<Collider>(true);
			for (int num = 0; num < componentsInChildren2.Length; num++)
			{
				componentsInChildren2[num].enabled = false;
			}
			int layer = ((Component)donut).gameObject.layer;
			Transform val8 = Child(((Component)donut).transform, "EvenMoreCards_Buzzsaw", layer);
			val8.localPosition = new Vector3(0f, 0f, -0.56f);
			Transform val9 = Child(val8, "Base", layer);
			((Component)val9).gameObject.AddComponent<MeshFilter>().sharedMesh = val;
			((Renderer)((Component)val9).gameObject.AddComponent<MeshRenderer>()).materials = (Material[])(object)new Material[3] { val7, sharedMaterial, _dark };
			BoxCollider val10 = ((Component)val9).gameObject.AddComponent<BoxCollider>();
			val10.center = new Vector3(0f, 0f, 0.4f);
			val10.size = new Vector3(5f, 1f, 0.8f);
			Transform val11 = Child(val8, "Slider", layer);
			val11.localPosition = new Vector3(0f, 0f, 0.8f);
			Transform val12 = Child(val11, "Blade", layer);
			((Component)val12).gameObject.AddComponent<MeshFilter>().sharedMesh = val2;
			((Renderer)((Component)val12).gameObject.AddComponent<MeshRenderer>()).sharedMaterial = _steel;
			Collider[] array = (Collider[])(object)new Collider[6];
			float num2 = 1.4488888f;
			float num3 = 0.38822854f;
			for (int num4 = 0; num4 < array.Length; num4++)
			{
				Transform obj = Child(val11, "KillZone" + num4, layer);
				obj.localRotation = Quaternion.AngleAxis((float)num4 * 30f, Vector3.up);
				BoxCollider val13 = ((Component)obj).gameObject.AddComponent<BoxCollider>();
				((Collider)val13).isTrigger = true;
				val13.size = new Vector3(num2 * 2f, 0.25f, num3 * 2f);
				((Collider)val13).enabled = false;
				KillZone obj2 = ((Component)obj).gameObject.AddComponent<KillZone>();
				obj2.parent = donut;
				obj2.alignedVelocityToKill = 0f;
				array[num4] = (Collider)(object)val13;
			}
			((Component)val8).gameObject.AddComponent<BuzzsawRunner>().Init(donut, val11, val12, array);
			Traverse.Create((object)donut).Field("colliders").SetValue((object)new Collider[1] { (Collider)val10 });
		}

		private static Transform Child(Transform parent, string name, int layer)
		{
			//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_000d: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name)
			{
				layer = layer
			};
			val.transform.SetParent(parent, false);
			return val.transform;
		}
	}
	internal class BuzzsawRunner : MonoBehaviour
	{
		private Obstacle _obstacle;

		private Transform _slider;

		private Transform _blade;

		private Collider[] _triggers;

		private float _phase;

		private readonly Dictionary<PlayerData, long> _lastKilledBy = new Dictionary<PlayerData, long>();

		private readonly Dictionary<PlayerData, int> _lastLives = new Dictionary<PlayerData, int>();

		private float _lastEffect = -1f;

		private static AudioClip _shing;

		private static bool _shingLoaded;

		public void Init(Obstacle obstacle, Transform slider, Transform blade, Collider[] triggers)
		{
			_obstacle = obstacle;
			_slider = slider;
			_blade = blade;
			_triggers = triggers;
			_phase = BuzzsawMath.Phase(((NetworkBehaviour)obstacle).NetworkObjectId);
		}

		private static double Now()
		{
			NetworkManager singleton = NetworkManager.Singleton;
			if (!((Object)(object)singleton != (Object)null) || !singleton.IsListening)
			{
				return Time.time;
			}
			return TimeUtils.CurrentTimeOnServerSec;
		}

		private void Update()
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Invalid comparison between Unknown and I4
			if (!((Object)(object)_obstacle == (Object)null))
			{
				double t = Now();
				_slider.localPosition = new Vector3(BuzzsawMath.Slide(t, Plugin.BuzzsawSlideSeconds.Value, _phase, 0.9f), 0f, 0.8f);
				_blade.localRotation = Quaternion.AngleAxis(BuzzsawMath.SpinAngle(t, Plugin.BuzzsawSpinSpeed.Value), Vector3.up);
				bool flag = (int)_obstacle.state == 3;
				Collider[] triggers = _triggers;
				for (int i = 0; i < triggers.Length; i++)
				{
					triggers[i].enabled = flag;
				}
				if (flag)
				{
					WatchKills();
				}
			}
		}

		private void WatchKills()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: 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)
			List<PlayerData> players = GameManager.Players;
			if (players == null)
			{
				return;
			}
			long networkObjectId = (long)((NetworkBehaviour)_obstacle).NetworkObjectId;
			float num = 3f * ((Component)this).transform.lossyScale.x;
			foreach (PlayerData item in players)
			{
				if ((Object)(object)item == (Object)null)
				{
					continue;
				}
				long value = item.killedBy.Value;
				int value2 = item.lifeCount.Value;
				long value3;
				int value4;
				bool num2 = _lastKilledBy.TryGetValue(item, out value3) & _lastLives.TryGetValue(item, out value4);
				_lastKilledBy[item] = value;
				_lastLives[item] = value2;
				if (num2 && !((Object)(object)item.controller == (Object)null))
				{
					Vector3 position = item.controller.sphereRigidbody.position;
					if ((BuzzsawMath.IsNewKill(value3, value, networkObjectId) || (BuzzsawMath.LostLife(value4, value2) && Vector3.Distance(position, _slider.position) < num)) && Time.time - _lastEffect > 0.5f)
					{
						_lastEffect = Time.time;
						OnKill(position);
					}
				}
			}
		}

		private void OnKill(Vector3 at)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			if (!_shingLoaded)
			{
				_shing = Bundle.Get<AudioClip>("BuzzsawKill");
				_shingLoaded = true;
			}
			if ((Object)(object)_shing != (Object)null)
			{
				SplitScreenAudioManager.PlayClipAtPoint(at, _shing, 1f, 1f);
			}
			if (!((Object)(object)Buzzsaw.HitSparks == (Object)null))
			{
				Burst(at, null);
				Burst(at, (Color?)new Color(0.75f, 0.04f, 0.04f));
			}
		}

		private static void Burst(Vector3 at, Color? tint)
		{
			//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_0037: 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_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Object.Instantiate<GameObject>(((Component)Buzzsaw.HitSparks).gameObject, at, Quaternion.identity);
			val.SetActive(true);
			ParticleSystem[] componentsInChildren = val.GetComponentsInChildren<ParticleSystem>(true);
			foreach (ParticleSystem val2 in componentsInChildren)
			{
				if (tint.HasValue)
				{
					MainModule main = val2.main;
					((MainModule)(ref main)).startColor = new MinMaxGradient(tint.Value);
					((MainModule)(ref main)).startSize = new MinMaxCurve(0.45f);
					((MainModule)(ref main)).startSpeed = new MinMaxCurve(4f);
				}
				val2.Play();
			}
			Object.Destroy((Object)(object)val, 3f);
		}
	}
	internal static class BuzzsawMath
	{
		public static float Slide(double t, float period, float phase, float travel)
		{
			if (period <= 0f)
			{
				return 0f;
			}
			double num = t / (double)period;
			num -= Math.Floor(num);
			return (float)((double)travel * Math.Sin(Math.PI * 2.0 * num + (double)phase));
		}

		public static float SpinAngle(double t, float degreesPerSecond)
		{
			double num = t * (double)degreesPerSecond % 360.0;
			return (float)((num < 0.0) ? (num + 360.0) : num);
		}

		public static float Phase(ulong networkObjectId)
		{
			return (float)((double)(networkObjectId * 2654435761u % 1000) / 1000.0 * 2.0 * Math.PI);
		}

		public static bool LostLife(int previous, int current)
		{
			return current < previous;
		}

		public static bool IsNewKill(long previous, long current, long obstacleId)
		{
			if (current == obstacleId)
			{
				return previous != current;
			}
			return false;
		}
	}
	internal class Card
	{
		public string Id;

		public string Name;

		public string Text;

		public string Art;

		public string Background;

		public string StyleFrom;

		public bool Giant;

		public ObstacleRarity? Rarity;

		public Action Apply;

		public Action<PlayerData> ApplyToOwner;

		public Func<Surface, Surface> MakeSurface;

		public Action<Obstacle> Decorate;

		public Func<ObstacleDescription, bool> RandomFrom;

		public string CarrierPrefab;

		public ObstacleDescription Asset;

		public ObstacleDescription Carrier;

		public Surface SurfaceAsset;
	}
	internal static class Cards
	{
		public static readonly List<Card> All = new List<Card>
		{
			new Card
			{
				Id = "3f6b2c1e-8d4a-4f7b-9c2e-5a1d0e7b4c90",
				Name = "Remove All Peas",
				Text = "Removes every pea from the map",
				Rarity = (ObstacleRarity)4,
				Background = "RemoveAllPeas.png",
				Apply = RemoveAllPeas
			},
			new Card
			{
				Id = "9a4e7d21-6c3b-4e8f-b1a5-2d7c9e0f3b46",
				Name = "Invisible",
				Text = "Makes a section of road invisible",
				Background = "Blank.png",
				MakeSurface = MakeInvisible
			},
			new Card
			{
				Id = "c7e15a3d-2b9f-4d06-8e4a-91f3b5d2a7c8",
				Name = "Launcher",
				Text = "A boosted tube that launches cars out the other end",
				Art = "Launcher.png",
				CarrierPrefab = "ToiletPaperRoll",
				Decorate = Launcher.Build
			},
			new Card
			{
				Id = "5d8b3f60-a2e4-4c19-9f7d-3e6a1b0c8d52",
				Name = "Bumper",
				Text = "A pinball pop bumper that knocks cars away",
				Rarity = (ObstacleRarity)3,
				Art = "Bumper.png",
				CarrierPrefab = "DonutObstacle",
				Decorate = Bumper.Build
			},
			new Card
			{
				Id = "3e9c7a51-8b2d-4f60-a1d4-6c0f2b8e5d97",
				Name = "Buzzsaw",
				Text = "A spinning, sliding saw blade. Touch it and you're out",
				StyleFrom = "LaserObstacle",
				Art = "Buzzsaw.png",
				Giant = true,
				CarrierPrefab = "DonutObstacle",
				Decorate = Buzzsaw.Build
			},
			new Card
			{
				Id = "e2a9c4b7-1f5d-4a3e-8b60-7c9d2f4e1a35",
				Name = "Drunk",
				Text = "Next round, everyone's screen goes wavy and steering is reversed",
				Rarity = (ObstacleRarity)2,
				Art = "Drunk.png",
				Apply = Drunk.Play
			},
			new Card
			{
				Id = "4b7f2e9a-6d1c-4e85-a3b0-8f5c2d7e9b14",
				Name = "Train Horn",
				Text = "Next round, your horn stalls every other car and bounces them up. Every 10s",
				Rarity = (ObstacleRarity)3,
				Background = "TrainHorn.png",
				ApplyToOwner = TrainHorn.Give
			},
			new Card
			{
				Id = "8c1d5e7f-3a2b-4f69-b0e4-6d9a2c5f1e83",
				Name = "Boost Surface",
				Text = "A section of road that boosts cars along it",
				Background = "BoostSurface.png",
				MakeSurface = BoostSurface.Make
			},
			new Card
			{
				Id = "b5d2e8f1-7c4a-4e93-9a06-1f3c8d5b7e24",
				Name = "Honey Road",
				Text = "A section of road covered in honey. Sticky going, no jumping",
				Background = "HoneyRoad.png",
				MakeSurface = HoneyRoad.Make
			},
			new Card
			{
				Id = "a6f3d9b2-7e1c-4b58-9d24-0c8e5f7a3b61",
				Name = "Peas Everywhere",
				Text = "Turns every object on the map into a pea",
				Rarity = (ObstacleRarity)3,
				Background = "PeasEverywhere.png",
				ApplyToOwner = TurnEverythingIntoPeas
			},
			new Card
			{
				Id = "d3b8e1a4-5c7f-4e92-8a16-2f4b9c0d7e58",
				Name = "RC Mode",
				Text = "Next round, every car is tiny and four times as fast",
				Rarity = (ObstacleRarity)3,
				Background = "RcMode.png",
				Apply = RcMode.Play
			},
			new Card
			{
				Id = "f1c7a2e9-4d6b-4a83-b5e0-9e2d6c8b3f17",
				Name = "Pea Cluster",
				Text = "Scatters a cluster of peas",
				StyleFrom = "ObstacleScatterNails",
				Art = "PeaCluster.png",
				CarrierPrefab = "ObstacleScatterLandMines",
				Decorate = ScatterPeas
			},
			new Card
			{
				Id = "b9e4c6d1-2f8a-4c37-a5b9-7d1e3f6a0c24",
				Name = "Low Gravity",
				Text = "Next round, everyone has low gravity",
				Rarity = (ObstacleRarity)2,
				Apply = LowGravity.Play
			},
			new Card
			{
				Id = "7a2e5f9c-0b4d-4e16-8c3a-5f9b1d7e2a40",
				Name = "-10%",
				Text = "Every car is 10% smaller for the rest of the game. Stacks",
				Rarity = (ObstacleRarity)2,
				Art = "Shrink.png",
				Apply = Shrink.Play
			},
			new Card
			{
				Id = "2c8f4a6e-9b1d-4e73-a5c0-6d3e8f1b7a92",
				Name = "Random Item",
				Text = "Turns into a random item when you pick it",
				Rarity = (ObstacleRarity)0,
				Art = "RandomItem.png",
				CarrierPrefab = "DonutObstacle",
				RandomFrom = (ObstacleDescription d) => (int)d.type != 4
			},
			new Card
			{
				Id = "e4b1d7a3-5f2c-4b86-9e0a-1c7f3d5a8b26",
				Name = "Random Modifier",
				Text = "Turns into a random modifier when you pick it",
				Rarity = (ObstacleRarity)0,
				Background = "RandomModifier.png",
				RandomFrom = (ObstacleDescription d) => (int)d.type == 4
			},
			new Card
			{
				Id = "5d1e8b3f-a7c2-4f96-b04e-9c3a6f2d8e71",
				Name = "No Brakes",
				Text = "Next round, nobody can brake or reverse",
				Rarity = (ObstacleRarity)2,
				Background = "NoBrakes.png",
				Apply = NoBrakes.Play
			}
		};

		private const string PeaId = "bed8133d-50d9-43f9-a313-d5331e2727a6";

		private const float PeaClusterSize = 0.5f;

		private const float PeaLift = 0.35f;

		private static void RemoveAllPeas()
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			List<Obstacle> list = ObstacleManager.AllObstacles.Where((Obstacle o) => (Object)(object)o != (Object)null && (Object)(object)o.description != (Object)null && ((object)o.description.id).ToString() == "bed8133d-50d9-43f9-a313-d5331e2727a6").ToList();
			ObstacleManager.Delete(list);
			ManualLogSource log = Plugin.Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(25, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Remove All Peas: ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(list.Count);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" pea(s).");
			}
			log.LogInfo(val);
		}

		private static void ScatterPeas(Obstacle cluster)
		{
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: 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_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			ObstacleDescription descriptionById = ObstacleManager.GetDescriptionById("bed8133d-50d9-43f9-a313-d5331e2727a6");
			if ((Object)(object)descriptionById != (Object)null)
			{
				ObstacleScatter val = (ObstacleScatter)(object)((cluster is ObstacleScatter) ? cluster : null);
				if (val != null)
				{
					val.obstacleToScatter = descriptionById;
					val.scatterRadius *= 0.5f;
					ScaleFlat(((Component)cluster).transform.Find("Cylinder"), 0.5f);
					ScaleFlat(((Component)cluster).transform.Find("ScatterArrow"), 0.5f);
					ScaleFlat(((Component)cluster).transform.Find("ScatterArrow/Arrow"), 2f);
					Transform obj = ((Component)cluster).transform.Find("Decal");
					Component val2 = ((obj != null) ? ((IEnumerable<Component>)((Component)obj).GetComponents<Component>()).FirstOrDefault((Func<Component, bool>)((Component c) => ((object)c).GetType().Name == "DecalProjector")) : null);
					PropertyInfo propertyInfo = ((object)val2)?.GetType().GetProperty("size");
					if (propertyInfo != null)
					{
						Vector3 val3 = (Vector3)propertyInfo.GetValue(val2);
						propertyInfo.SetValue(val2, (object)new Vector3(val3.x * 0.5f, val3.y * 0.5f, val3.z));
					}
					return;
				}
			}
			Plugin.Log.LogWarning((object)"Pea Cluster: pea card or scatter part missing; scattering mines instead.");
		}

		private static void ScaleFlat(Transform t, float factor)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)t == (Object)null))
			{
				Vector3 localScale = t.localScale;
				t.localScale = new Vector3(localScale.x * factor, localScale.y, localScale.z * factor);
			}
		}

		[HarmonyPatch(typeof(ObstacleScatter), "GetScatterPositions")]
		[HarmonyPostfix]
		private static void LiftScatteredPeas(ObstacleScatter __instance, List<(Vector3, Quaternion, bool)> __result)
		{
			//IL_0037: 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_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)__instance.obstacleToScatter == (Object)null) && !(((object)__instance.obstacleToScatter.id).ToString() != "bed8133d-50d9-43f9-a313-d5331e2727a6"))
			{
				for (int i = 0; i < __result.Count; i++)
				{
					(Vector3, Quaternion, bool) tuple = __result[i];
					Vector3 item = tuple.Item1;
					Quaternion item2 = tuple.Item2;
					bool item3 = tuple.Item3;
					__result[i] = (item + Vector3.up * 0.35f, item2, item3);
				}
			}
		}

		private static void TurnEverythingIntoPeas(PlayerData player)
		{
			//IL_0092: 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_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Expected O, but got Unknown
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkManager.Singleton.IsServer)
			{
				return;
			}
			ObstacleDescription descriptionById = ObstacleManager.GetDescriptionById("bed8133d-50d9-43f9-a313-d5331e2727a6");
			if ((Object)(object)descriptionById == (Object)null)
			{
				Plugin.Log.LogWarning((object)"Peas Everywhere: pea card not in this game's catalog.");
				return;
			}
			List<Obstacle> list = ObstacleManager.AllObstacles.Where((Obstacle o) => (Object)(object)o != (Object)null && (Object)(object)o.description != (Object)null && (int)o.state == 3 && (int)o.description.type != 1 && (int)o.description.type != 4 && ((object)o.description.id).ToString() != "bed8133d-50d9-43f9-a313-d5331e2727a6").ToList();
			foreach (Obstacle item in list)
			{
				Vector3 val = (((Object)(object)item.center != (Object)null) ? item.center.position : ((Component)item).transform.position);
				descriptionById.Spawn(((Object)(object)item.playerInfos != (Object)null) ? item.playerInfos : player, val, Quaternion.identity, true, -1);
			}
			ObstacleManager.Delete(list);
			ManualLogSource log = Plugin.Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(45, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Peas Everywhere: ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(list.Count);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" object(s) turned into peas.");
			}
			log.LogInfo(val2);
		}

		private static Surface MakeInvisible(Surface asphalt)
		{
			Surface val = CopySurface(asphalt, "EvenMoreCards_Invisible");
			Material material = val.effects.material;
			foreach (string item in new string[11]
			{
				"UniversalForward", "UniversalForwardOnly", "UniversalGBuffer", "SRPDefaultUnlit", "ShadowCaster", "DepthOnly", "DepthNormals", "DepthNormalsOnly", "MotionVectors", "Meta",
				"Universal2D"
			}.Concat(Enumerable.Range(0, material.passCount).Select((Func<int, string>)material.GetPassName)))
			{
				material.SetShaderPassEnabled(item, false);
			}
			return val;
		}

		internal static Surface CopySurface(Surface asphalt, string name)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Expected O, but got Unknown
			Surface val = ScriptableObject.CreateInstance<Surface>();
			Plugin.CopyFields(asphalt, val);
			((Object)val).name = name;
			val.inGameCarModifiers = new List<CarModifier>(asphalt.inGameCarModifiers);
			val.carModifiersToIgnore = new HashSet<CarModifier>(asphalt.carModifiersToIgnore);
			val.effects = new SurfaceEffects();
			Plugin.CopyFields(asphalt.effects, val.effects);
			val.effects.material = new Material(asphalt.effects.material)
			{
				name = ((Object)asphalt.effects.material).name + " " + name
			};
			return val;
		}
	}
	internal static class Drunk
	{
		private const float RampSeconds = 2f;

		private static readonly OneRound Round = new OneRound();

		private static readonly Dictionary<Camera, (Quaternion rotation, float fov)> Saved = new Dictionary<Camera, (Quaternion, float)>();

		public static void Play()
		{
			Round.Arm();
			RenderPipelineManager.beginCameraRendering -= Wobble;
			RenderPipelineManager.beginCameraRendering += Wobble;
			RenderPipelineManager.endCameraRendering -= Restore;
			RenderPipelineManager.endCameraRendering += Restore;
		}

		private static void Wobble(ScriptableRenderContext context, Camera cam)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Invalid comparison between Unknown and I4
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			if (Round.Active && (int)cam.cameraType == 1)
			{
				Saved[cam] = (((Component)cam).transform.rotation, cam.fieldOfView);
				float num = Time.time - Round.StartTime;
				float num2 = Mathf.Clamp01(num / 2f) * Plugin.DrunkStrength.Value;
				float num3 = (Mathf.Sin(num * 0.9f) * 12f + Mathf.Sin(num * 2.6f) * 4f) * num2;
				float num4 = (Mathf.Sin(num * 0.6f + 1f) * 5f + Mathf.Sin(num * 1.9f) * 1.5f) * num2;
				float num5 = Mathf.Sin(num * 1.3f + 2f) * 3.5f * num2;
				((Component)cam).transform.rotation = ((Component)cam).transform.rotation * Quaternion.Euler(num5, num4, num3);
				cam.fieldOfView += (Mathf.Sin(num * 1.7f) * 9f + Mathf.Sin(num * 0.4f) * 5f) * num2;
			}
		}

		private static void Restore(ScriptableRenderContext context, Camera cam)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			if (Saved.TryGetValue(cam, out (Quaternion, float) value))
			{
				Saved.Remove(cam);
				if (!((Object)(object)cam == (Object)null))
				{
					((Component)cam).transform.rotation = value.Item1;
					cam.fieldOfView = value.Item2;
				}
			}
		}

		public static void PatchSteering(Harmony harmony)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.GetDeclaredMethods(typeof(SphereCarController)).First((MethodInfo m) => m.Name == "SetSteer" && m.GetParameters()[0].ParameterType != typeof(float));
			harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(Drunk), "ReverseSteer", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		private static void ReverseSteer(SphereCarController __instance)
		{
			if (Round.Active && Plugin.DrunkReverseSteer.Value)
			{
				__instance.SetSteer(0f - __instance.Steer);
			}
		}
	}
	internal static class HoneyRoad
	{
		internal static ObstacleDescription Honey;

		private static Surface _surface;

		private static CarModifier _sticky;

		private static bool _resolved;

		public static Surface Make(Surface asphalt)
		{
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Expected O, but got Unknown
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0284: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			_surface = Cards.CopySurface(asphalt, "EvenMoreCards_Honey");
			Surface val = SurfaceManager.instance?.surfaces?.FirstOrDefault((Func<Surface, bool>)((Surface x) => (Object)(object)x?.effects?.material != (Object)null && ((Object)x.effects.material).name == "Mud"));
			Material material = _surface.effects.material;
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)"Honey Road: Mud road not found; using a plain amber tint.");
				string[] array = new string[2] { "_BaseColor", "_Color" };
				foreach (string text in array)
				{
					if (material.HasProperty(text))
					{
						material.SetColor(text, material.GetColor(text) * new Color(1f, 0.68f, 0.12f));
					}
				}
				return _surface;
			}
			material = new Material(val.effects.material)
			{
				name = ((Object)material).name
			};
			material.SetColor("_Color", new Color(1f, 0.84f, 0.22f));
			material.SetColor("_ColorSecondary", new Color(0.92f, 0.66f, 0.12f));
			material.SetColor("_RampTint", new Color(0.85f, 0.62f, 0.18f));
			material.SetColor("_SpecularTint", new Color(1f, 0.97f, 0.8f));
			material.SetColor("_TrailsColor", new Color(1f, 0.92f, 0.5f));
			material.SetFloat("_Smoothness", 0.9f);
			material.SetFloat("_Sliminess", 1f);
			material.SetFloat("_Metalness", 0.6f);
			material.SetFloat("_Dustiness", 0f);
			material.SetFloat("_Mossy", 0f);
			material.SetFloat("_PebblesIntensity", 0.3f);
			material.SetFloat("_GlitterIntensity", 0f);
			material.SetFloat("_RimBrightness", 1.6f);
			_surface.effects.material = material;
			_surface.effects.lightColor = new Color(1f, 0.95f, 0.6f);
			_surface.effects.mainColor = new Color(1f, 0.84f, 0.22f);
			_surface.effects.darkColor = new Color(0.85f, 0.6f, 0.12f);
			_surface.skidMarkColor = new Color32((byte)200, (byte)145, (byte)30, byte.MaxValue);
			return _surface;
		}

		[HarmonyPatch(typeof(SphereCarController), "ApplyModifiers")]
		[HarmonyPostfix]
		private static void Stick(SphereCarController __instance)
		{
			if ((Object)(object)_surface == (Object)null)
			{
				return;
			}
			if (!_resolved)
			{
				Resolve();
			}
			bool flag = (Object)(object)__instance.CurrentSurface == (Object)(object)_surface && __instance.OnGround;
			if (flag)
			{
				__instance.DisableJumpFromModifier(true);
			}
			if ((Object)(object)_sticky == (Object)null)
			{
				if (flag)
				{
					__instance.maxSpeed *= 0.5f;
					__instance.speed *= 0.5f;
				}
			}
			else if (flag)
			{
				_sticky.Register(__instance, (object)_surface);
			}
			else if (_sticky.hasInfiniteDuration)
			{
				__instance.UnregisterModifiers((object)_surface);
			}
		}

		private static void Resolve()
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Expected O, but got Unknown
			_resolved = true;
			_sticky = ((!((Object)(object)Honey != (Object)null) || !((Object)(object)Honey.prefab != (Object)null)) ? null : ((Component)Honey.prefab).GetComponentInChildren<CarModifierApplier>(true)?.modifierToApply);
			if ((Object)(object)_sticky == (Object)null)
			{
				Plugin.Log.LogWarning((object)"Honey Road: honey item's modifier not found; using a plain half-speed slowdown.");
				return;
			}
			ManualLogSource log = Plugin.Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(39, 2, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Honey Road: using honey modifier '");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((Object)_sticky).name);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' (");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(_sticky.hasInfiniteDuration ? "no time limit" : (_sticky.durationSeconds + " s"));
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(").");
			}
			log.LogInfo(val);
		}
	}
	internal static class Launcher
	{
		internal static ObstacleDescription MegaBoost;

		private const float BoreRadius = 1.64f;

		private static Material _tyre;

		private static Material _glow;

		private static readonly int PrimaryColor = Shader.PropertyToID("_PlayerPrimaryColor");

		private static readonly int SecondaryColor = Shader.PropertyToID("_PlayerSecondaryColor");

		public static void Build(Obstacle tube)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: 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_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: 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_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Expected O, but got Unknown
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: 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_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Expected O, but got Unknown
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: 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)
			Bounds bounds = ((Component)tube).GetComponent<MeshFilter>().sharedMesh.bounds;
			Vector3 size = ((Bounds)(ref bounds)).size;
			Vector3 val = ((size.x >= size.y && size.x >= size.z) ? Vector3.right : ((size.y >= size.z) ? Vector3.up : Vector3.forward));
			Quaternion val2 = Quaternion.FromToRotation(Vector3.up, val);
			GameObject val3 = new GameObject("EvenMoreCards_LaunchZone")
			{
				layer = ((Component)tube).gameObject.layer
			};
			val3.transform.SetParent(((Component)tube).transform, false);
			val3.transform.localPosition = ((Bounds)(ref bounds)).center;
			val3.transform.localRotation = val2;
			BoxCollider obj = val3.AddComponent<BoxCollider>();
			((Collider)obj).isTrigger = true;
			float num = 1.64f * Mathf.Sqrt(2f);
			obj.size = new Vector3(num, Mathf.Abs((Quaternion.Inverse(val2) * size).y), num);
			LaunchZone launch = val3.AddComponent<LaunchZone>();
			ManualLogSource log = Plugin.Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val4 = new BepInExInfoLogInterpolatedStringHandler(48, 3, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("Launcher: tube mesh bounds centre ");
				((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<Vector3>(((Bounds)(ref bounds)).center);
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" size ");
				((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<Vector3>(size);
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(", axis ");
				((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<Vector3>(val);
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(".");
			}
			log.LogInfo(val4);
			CarModifier val5 = ((!((Object)(object)MegaBoost?.prefab != (Object)null)) ? null : ((Component)MegaBoost.prefab).GetComponentInChildren<CarModifierApplier>(true)?.modifierToApply);
			if ((Object)(object)val5 != (Object)null)
			{
				val3.AddComponent<CarModifierApplier>().modifierToApply = val5;
			}
			else
			{
				Plugin.Log.LogWarning((object)"Launcher: Mega Boost effect not found; tube only launches, no boost.");
			}
			Reskin(tube, launch);
		}

		private static void Reskin(Obstacle tube, LaunchZone launch)
		{
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Expected O, but got Unknown
			//IL_00a2: 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_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			Mesh val = Bundle.Get<Mesh>("Launcher");
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			if ((Object)(object)_tyre == (Object)null)
			{
				_tyre = Urp.Lit(new Color(0.03f, 0.03f, 0.03f), 0.2f);
				_glow = Urp.Unlit(new Color(1f, 0.45f, 0f));
				if ((Object)(object)_tyre == (Object)null)
				{
					return;
				}
			}
			((Component)tube).GetComponent<MeshFilter>().sharedMesh = val;
			MeshRenderer component = ((Component)tube).GetComponent<MeshRenderer>();
			Material sharedMaterial = ((Renderer)component).sharedMaterial;
			Material val2 = new Material(sharedMaterial);
			sharedMaterial.SetColor(SecondaryColor, sharedMaterial.GetColor(PrimaryColor));
			val2.SetColor(PrimaryColor, val2.GetColor(SecondaryColor));
			((Renderer)component).materials = (Material[])(object)new Material[4] { sharedMaterial, _tyre, _glow, val2 };
			launch.Muzzles = new MuzzlePulse[2]
			{
				Muzzle(tube, "LauncherMuzzleBottom", sharedMaterial, val2),
				Muzzle(tube, "LauncherMuzzleTop", sharedMaterial, val2)
			};
		}

		private static MuzzlePulse Muzzle(Obstacle tube, string name, Material body, Material rings)
		{
			//IL_001d: 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_0034: Expected O, but got Unknown
			Mesh val = Bundle.Get<Mesh>(name);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			GameObject val2 = new GameObject("EvenMoreCards_" + name)
			{
				layer = ((Component)tube).gameObject.layer
			};
			val2.transform.SetParent(((Component)tube).transform, false);
			val2.AddComponent<MeshFilter>().sharedMesh = val;
			((Renderer)val2.AddComponent<MeshRenderer>()).materials = (Material[])(object)new Material[2] { body, rings };
			return val2.AddComponent<MuzzlePulse>();
		}
	}
	internal class MuzzlePulse : MonoBehaviour
	{
		private const float Duration = 0.5f;

		private const float Swell = 0.2f;

		private float _start = -1f;

		public void Pulse()
		{
			_start = Time.time;
			((Behaviour)this).enabled = true;
		}

		private void Update()
		{
			//IL_0059: 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)
			float num = (Time.time - _start) / 0.5f;
			if (num >= 1f)
			{
				((Component)this).transform.localScale = Vector3.one;
				((Behaviour)this).enabled = false;
			}
			else
			{
				float num2 = 1f + 0.2f * Mathf.Sin(num * MathF.PI);
				((Component)this).transform.localScale = new Vector3(num2, 1f, num2);
			}
		}
	}
	internal class LaunchZone : MonoBehaviour
	{
		private static AudioClip _boom;

		private static bool _boomLoaded;

		private float _lastBoom = -1f;

		internal MuzzlePulse[] Muzzles;

		private void OnTriggerExit(Collider other)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: 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_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: 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_00b2: Expected O, but got Unknown
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			Rigidbody attachedRigidbody = other.attachedRigidbody;
			PlayerNetworking componentInParent = ((Component)other).GetComponentInParent<PlayerNetworking>();
			if ((Object)(object)attachedRigidbody == (Object)null || (Object)(object)componentInParent == (Object)null)
			{
				return;
			}
			float y = ((Component)this).transform.InverseTransformPoint(attachedRigidbody.position).y;
			bool flag = Mathf.Abs(y) > ((Component)this).GetComponent<BoxCollider>().size.y * 0.35f;
			if (flag && Time.time - _lastBoom > 0.5f)
			{
				_lastBoom = Time.time;
				MuzzlePulse[] muzzles = Muzzles;
				MuzzlePulse muzzlePulse = ((muzzles != null) ? muzzles[(y > 0f) ? 1u : 0u] : null);
				muzzlePulse?.Pulse();
				ManualLogSource log = Plugin.Log;
				bool flag2 = default(bool);
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(40, 2, ref flag2);
				if (flag2)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Launcher: car left by the ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>((y > 0f) ? "top" : "bottom");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" end; muzzle ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((Object)(object)muzzlePulse != (Object)null) ? ((Object)muzzlePulse).name : "missing");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(".");
				}
				log.LogInfo(val);
				if (!_boomLoaded)
				{
					_boom = Bundle.Get<AudioClip>("Cannon");
					_boomLoaded = true;
				}
				if ((Object)(object)_boom != (Object)null)
				{
					SplitScreenAudioManager.PlayClipAtPoint(attachedRigidbody.position, _boom, Plugin.CannonVolume.Value, 1f);
				}
			}
			if (((NetworkBehaviour)componentInParent).IsOwner && flag)
			{
				Vector3 up = ((Component)this).transform.up;
				float num = Vector3.Dot(attachedRigidbody.velocity, up);
				if (!(Mathf.Abs(num) < 1f))
				{
					attachedRigidbody.velocity = up * Mathf.Sign(num) * Plugin.LaunchSpeed.Value + Vector3.up * Plugin.LaunchLift.Value;
				}
			}
		}
	}
	internal static class LowGravity
	{
		private static readonly OneRound Round = new OneRound();

		public static void Play()
		{
			Round.Arm();
		}

		[HarmonyPatch(typeof(GravityShapesManager), "GetGravityAtPoint", new Type[] { typeof(Vector3) })]
		[HarmonyPostfix]
		private static void Lower(ref Vector3 __result)
		{
			//IL_000e: 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_0022: Unknown result type (might be due to invalid IL or missing references)
			if (Round.Active)
			{
				__result *= Plugin.GravityScale.Value;
			}
		}

		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyPostfix]
		private static void LowerWithUp(ref Vector3 __result)
		{
			//IL_000e: 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_0022: Unknown result type (might be due to invalid IL or missing references)
			if (Round.Active)
			{
				__result *= Plugin.GravityScale.Value;
			}
		}

		[HarmonyPatch(typeof(SphereCarController), "PerformJump", new Type[]
		{
			typeof(Vector3),
			typeof(Vector3)
		})]
		[HarmonyPrefix]
		private static void NormalJumpSpeed(ref Vector3 gravity)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			if (Round.Active && Plugin.GravityScale.Value > 0f)
			{
				gravity /= Plugin.GravityScale.Value;
			}
		}
	}
	internal static class NoBrakes
	{
		private static readonly OneRound Round = new OneRound();

		public static void Play()
		{
			Round.Arm();
		}

		[HarmonyPatch(typeof(SphereCarController), "FixedUpdate")]
		[HarmonyPrefix]
		private static void CutBrakes(SphereCarController __instance)
		{
			if (Round.Active)
			{
				__instance.SetReverse(0f);
			}
		}
	}
	internal class OneRound
	{
		private bool _armed;

		private GameManager _hookedTo;

		public bool Active { get; private set; }

		public float StartTime { get; private set; }

		public event Action Ended;

		public void Arm()
		{
			_armed = true;
			if (!((Object)(object)_hookedTo == (Object)(object)GameManager.instance))
			{
				_hookedTo = GameManager.instance;
				_hookedTo.onStateChange.AddListener((UnityAction<GameState>)OnStateChange);
			}
		}

		private void OnStateChange(GameState state)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Invalid comparison between Unknown and I4
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Invalid comparison between Unknown and I4
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			if ((int)state == 4 && _armed)
			{
				_armed = false;
				Active = true;
				StartTime = Time.time;
			}
			else if (((int)state == 6 || (int)state == 10 || (int)state == 0) && Active)
			{
				Active = false;
				this.Ended?.Invoke();
			}
		}
	}
	[BepInPlugin("onlynothing.evenmorecards", "EvenMoreCards", "0.5.0")]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		private static Harmony _harmony;

		private static bool _modifierCarrierPatched;

		private static ConfigEntry<bool> _forceInDraft;

		internal static ConfigEntry<float> LaunchSpeed;

		internal static ConfigEntry<float> LaunchLift;

		internal static ConfigEntry<float> CannonVolume;

		internal static ConfigEntry<float> BuzzsawSlideSeconds;

		internal static ConfigEntry<float> BuzzsawSpinSpeed;

		internal static ConfigEntry<float> BumperStrength;

		internal static ConfigEntry<float> DrunkStrength;

		internal static ConfigEntry<bool> DrunkReverseSteer;

		internal static ConfigEntry<float> StallSeconds;

		internal static ConfigEntry<float> StallHop;

		internal static ConfigEntry<float> HornCooldown;

		internal static ConfigEntry<float> HornVolume;

		internal static ConfigEntry<float> BoostMultiplier;

		internal static ConfigEntry<float> BoostPush;

		internal static ConfigEntry<float> RcScale;

		internal static ConfigEntry<float> RcSpeed;

		internal static ConfigEntry<float> GravityScale;

		internal static ConfigEntry<float> ShrinkPercent;

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			_forceInDraft = ((BaseUnityPlugin)this).Config.Bind<bool>("Testing", "ForceInDraft", false, "Put the custom cards (newest first) into the draft slots each round (host only). For testing.");
			LaunchSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Launcher", "LaunchSpeed", 45f, "Speed (m/s) along the tube when a car leaves the Launcher.");
			LaunchLift = ((BaseUnityPlugin)this).Config.Bind<float>("Launcher", "LaunchLift", 15f, "Extra upward speed (m/s) when a car leaves the Launcher.");
			CannonVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Launcher", "CannonVolume", 1f, "Volume of the boom when a car leaves the Launcher (unity/Assets/Sounds/Cannon), 0 to 1.");
			BuzzsawSlideSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Buzzsaw", "SlideSeconds", 3f, "Seconds for the blade to slide there and back along its housing (0 = blade stays centred).");
			BuzzsawSpinSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Buzzsaw", "SpinSpeed", 720f, "Blade spin in degrees per second.");
			StallSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Train Horn", "StallSeconds", 1f, "How long other cars are stalled by a Train Horn blast.");
			StallHop = ((BaseUnityPlugin)this).Config.Bind<float>("Train Horn", "StallHop", 6f, "Upward speed (m/s) given to grounded cars by a Train Horn blast.");
			HornCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Train Horn", "HornCooldownSeconds", 10f, "Seconds between Train Horn blasts, so the horn can't be spammed. Checked on each player's own game, so keep it the same for everyone.");
			HornVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Train Horn", "HornVolume", 1f, "Volume of the custom Train Horn sound (unity/Assets/Sounds/TrainHorn), 0 to 1.");
			DrunkStrength = ((BaseUnityPlugin)this).Config.Bind<float>("Drunk", "DrunkStrength", 1f, "How hard the Drunk card sways the camera (0 = off, 2 = double).");
			DrunkReverseSteer = ((BaseUnityPlugin)this).Config.Bind<bool>("Drunk", "ReverseSteer", true, "Drunk also swaps left and right steering for the round.");
			BumperStrength = ((BaseUnityPlugin)this).Config.Bind<float>("Bumper", "BumperStrength", 1.5f, "Bounce speed as a multiple of impact speed (1 = same speed back).");
			ShrinkPercent = ((BaseUnityPlugin)this).Config.Bind<float>("Shrink", "ShrinkPercent", 10f, "How much smaller every car gets per Shrink card played (stacks, lasts the game).");
			GravityScale = ((BaseUnityPlugin)this).Config.Bind<float>("Low Gravity", "GravityScale", 0.4f, "Gravity during a Low Gravity round (1 = normal). Jumps go 1/this as high.");
			RcScale = ((BaseUnityPlugin)this).Config.Bind<float>("RC Mode", "Scale", 0.3f, "Car size during an RC Mode round (1 = normal).");
			RcSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("RC Mode", "SpeedMultiplier", 4f, "Top speed and push multiplier during an RC Mode round.");
			BoostMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Boost Surface", "BoostMultiplier", 2f, "Top speed multiplier on a Boost Surface (acceleration too, while accelerating).");
			BoostPush = ((BaseUnityPlugin)this).Config.Bind<float>("Boost Surface", "PushStrength", 30f, "Forward push (m/s per second) on a Boost Surface, up to its raised top speed. Normal acceleration is about 6.6.");
			_harmony = Harmony.CreateAndPatchAll(typeof(Plugin), (string)null);
			_harmony.PatchAll(typeof(TrainHorn));
			_harmony.PatchAll(typeof(BoostSurface));
			_harmony.PatchAll(typeof(HoneyRoad));
			_harmony.PatchAll(typeof(RcMode));
			_harmony.PatchAll(typeof(LowGravity));
			_harmony.PatchAll(typeof(NoBrakes));
			_harmony.PatchAll(typeof(Shrink));
			_harmony.PatchAll(typeof(Cards));
			_harmony.PatchAll(typeof(RandomCard));
			Drunk.PatchSteering(_harmony);
			Bundle.Load();
			Log.LogInfo((object)"EvenMoreCards loaded.");
		}

		[HarmonyPatch(typeof(ObstacleGameModifierSurfacesSwap), "ApplyModifier")]
		[HarmonyPrefix]
		private static void SwapOurSurfacesToo(ObstacleGameModifierSurfacesSwap __instance)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: 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)
			List<SurfaceSwapTuple> surfaceSwaps = __instance.surfaceSwaps;
			if (surfaceSwaps == null || surfaceSwaps.Count == 0)
			{
				return;
			}
			Surface to = surfaceSwaps[0].to;
			if (surfaceSwaps.Any((SurfaceSwapTuple s) => (Object)(object)s.to != (Object)(object)to))
			{
				return;
			}
			foreach (Surface ours in from c in Cards.All
				select c.SurfaceAsset into s
				where (Object)(object)s != (Object)null
				select s)
			{
				if ((Object)(object)ours != (Object)(object)to && surfaceSwaps.All((SurfaceSwapTuple s) => (Object)(object)s.from != (Object)(object)ours))
				{
					surfaceSwaps.Add(new SurfaceSwapTuple
					{
						from = ours,
						to = to
					});
				}
			}
		}

		[HarmonyPatch(typeof(SurfaceManager), "Awake")]
		[HarmonyPostfix]
		private static void RegisterSurfaces(SurfaceManager __instance)
		{
			if ((Object)(object)__instance != (Object)(object)SurfaceManager.instance || (Object)(object)__instance.defaultSurface == (Object)null)
			{
				return;
			}
			foreach (Card item in Cards.All.Where((Card c) => c.MakeSurface != null && (Object)(object)c.SurfaceAsset == (Object)null))
			{
				item.SurfaceAsset = item.MakeSurface(__instance.defaultSurface);
			}
			IEnumerable<Surface> first = from c in Cards.All
				where (Object)(object)c.SurfaceAsset != (Object)null
				select c.SurfaceAsset;
			__instance.surfaces = __instance.surfaces.Concat(first.Except(__instance.surfaces)).ToArray();
		}

		[HarmonyPatch(typeof(Obstacle), "Init")]
		[HarmonyPostfix]
		private static void SetUpPlacedCard(Obstacle __instance)
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Expected O, but got Unknown
			Card card = CardPlayedBy(__instance);
			if (card == null || !((Object)__instance).name.StartsWith(((Object)card.Carrier.prefab).name))
			{
				return;
			}
			try
			{
				if ((Object)(object)card.SurfaceAsset != (Object)null)
				{
					ObstacleSurfaceSwap val = (ObstacleSurfaceSwap)(object)((__instance is ObstacleSurfaceSwap) ? __instance : null);
					if (val != null)
					{
						val.surfaceToSwapTo = card.SurfaceAsset;
					}
				}
				if (card.Decorate != null)
				{
					card.Decorate(__instance);
					RecacheRenderers(__instance);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Log;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(21, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Setting up '");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(card.Name);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("' threw: ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Exception>(ex);
				}
				log.LogError(val2);
			}
		}

		private static void RecacheRenderers(Obstacle obstacle)
		{
			MeshRenderer[] array = (from r in ((Component)obstacle).GetComponentsInChildren<MeshRenderer>(true)
				where (Object)(object)((Component)r).GetComponent<MeshFilter>() != (Object)null
				select r).ToArray();
			MeshFilter[] array2 = array.Select((MeshRenderer r) => ((Component)r).GetComponent<MeshFilter>()).ToArray();
			Traverse obj = Traverse.Create((object)obstacle);
			obj.Property("MeshRenderers", (object[])null).SetValue((object)array);
			obj.Field("_meshFilters").SetValue((object)array2);
			Dictionary<MeshRenderer, MeshFilter> value = obj.Field("_meshRenderersToFilters").GetValue<Dictionary<MeshRenderer, MeshFilter>>();
			if (value != null)
			{
				for (int num = 0; num < array.Length; num++)
				{
					value.TryAdd(array[num], array2[num]);
				}
			}
		}

		[HarmonyPatch(typeof(ObstacleManager), "Awake")]
		[HarmonyPostfix]
		private static void RegisterCards(ObstacleManager __instance)
		{
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Expected O, but got Unknown
			//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f4: Expected O, but got Unknown
			//IL_0305: Unknown result type (might be due to invalid IL or missing references)
			//IL_030c: Expected O, but got Unknown
			if ((Object)(object)__instance != (Object)(object)ObstacleManager.instance || __instance.allowedObstacleDescriptions == null)
			{
				return;
			}
			ObstacleDescription[] allowedObstacleDescriptions = __instance.allowedObstacleDescriptions;
			ObstacleDescription val = ((IEnumerable<ObstacleDescription>)allowedObstacleDescriptions).FirstOrDefault((Func<ObstacleDescription, bool>)((ObstacleDescription d) => (Object)(object)d?.prefab != (Object)null && (int)d.type == 4 && (Object)(object)((Component)d.prefab).GetComponent<ObstacleGameModifier>() != (Object)null));
			ObstacleDescription val2 = ((IEnumerable<ObstacleDescription>)allowedObstacleDescriptions).FirstOrDefault((Func<ObstacleDescription, bool>)((ObstacleDescription d) => (Object)(object)d?.prefab != (Object)null && (Object)(object)((Component)d.prefab).GetComponent<ObstacleSurfaceSwap>() != (Object)null));
			Launcher.MegaBoost = ((IEnumerable<ObstacleDescription>)allowedObstacleDescriptions).FirstOrDefault((Func<ObstacleDescription, bool>)((ObstacleDescription d) => (Object)(object)d?.prefab != (Object)null && ((Object)d.prefab).name == "BoostZoneMega"));
			HoneyRoad.Honey = ((IEnumerable<ObstacleDescription>)allowedObstacleDescriptions).FirstOrDefault((Func<ObstacleDescription, bool>)((ObstacleDescription d) => (Object)(object)d?.prefab != (Object)null && ((Object)d.prefab).name == "HoneySplatterObstacle"));
			ObstacleDescription? obj = ((IEnumerable<ObstacleDescription>)allowedObstacleDescriptions).FirstOrDefault((Func<ObstacleDescription, bool>)((ObstacleDescription d) => (Object)(object)d?.prefab != (Object)null && ((Object)d.prefab).name == "LaserObstacle"));
			Buzzsaw.HitSparks = ((obj != null) ? ((Component)obj.prefab).transform.Find("HitSparks") : null);
			if ((Object)(object)Buzzsaw.HitSparks == (Object)null)
			{
				Log.LogWarning((object)"Laser's HitSparks not found; Buzzsaw kills won't show sparks.");
			}
			bool flag = default(bool);
			foreach (Card card in Cards.All.Where((Card c) => (Object)(object)c.Asset == (Object)null))
			{
				ObstacleDescription val3 = (ObstacleDescription)((card.CarrierPrefab != null) ? ((object)((IEnumerable<ObstacleDescription>)allowedObstacleDescriptions).FirstOrDefault((Func<ObstacleDescription, bool>)((ObstacleDescription d) => (Object)(object)d?.prefab != (Object)null && ((Object)d.prefab).name == card.CarrierPrefab))) : ((object)((card.MakeSurface != null) ? val2 : val)));
				if ((Object)(object)val3 == (Object)null)
				{
					ManualLogSource log = Log;
					BepInExWarningLogInterpolatedStringHandler val4 = new BepInExWarningLogInterpolatedStringHandler(34, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("No carrier card for '");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(card.Name);
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("'; not added.");
					}
					log.LogWarning(val4);
				}
				else
				{
					card.Carrier = val3;
					card.Asset = BuildDescription(card, val3, allowedObstacleDescriptions);
				}
			}
			IEnumerable<ObstacleDescription> enumerable = from c in Cards.All
				where (Object)(object)c.Asset != (Object)null
				select c.Asset;
			__instance.allowedObstacleDescriptions = allowedObstacleDescriptions.Concat(enumerable.Except(allowedObstacleDescriptions)).ToArray();
			if (!_modifierCarrierPatched && (Object)(object)val != (Object)null)
			{
				Type type = ((object)((Component)val.prefab).GetComponent<ObstacleGameModifier>()).GetType();
				_harmony.Patch((MethodBase)AccessTools.Method(type, "ApplyModifier", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Plugin), "ApplyCardEffect", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				_modifierCarrierPatched = true;
				ManualLogSource log2 = Log;
				BepInExInfoLogInterpolatedStringHandler val5 = new BepInExInfoLogInterpolatedStringHandler(50, 3, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("Added ");
					((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<int>(enumerable.Count());
					((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" card(s). Carriers: modifier '");
					((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(((Object)val).name);
					((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("', surface '");
					((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>((val2 != null) ? ((Object)val2).name : null);
					((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("'.");
				}
				log2.LogInfo(val5);
			}
		}

		private static ObstacleDescription BuildDescription(Card card, ObstacleDescription carrier, ObstacleDescription[] catalog)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Expected O, but got Unknown
			//IL_0317: Unknown result type (might be due to invalid IL or missing references)
			//IL_031c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: 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)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Expected O, but got Unknown
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Expected O, but got Unknown
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fb: Unknown result type (might be due to invalid IL or missing references)
			ObstacleDescription val = ScriptableObject.CreateInstance<ObstacleDescription>();
			CopyFields(carrier, val);
			((Object)val).name = "EvenMoreCards_" + card.Name.Replace(" ", "");
			val.id = new SerializableGuid(new Guid(card.Id));
			if (card.StyleFrom != null)
			{
				ObstacleDescription val2 = ((IEnumerable<ObstacleDescription>)catalog).FirstOrDefault((Func<ObstacleDescription, bool>)((ObstacleDescription x) => (Object)(object)x?.prefab != (Object)null && ((Object)x.prefab).name == card.StyleFrom));
				bool flag = default(bool);
				if ((Object)(object)val2 == (Object)null)
				{
					ManualLogSource log = Log;
					BepInExWarningLogInterpolatedStringHandler val3 = new BepInExWarningLogInterpolatedStringHandler(56, 2, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("'");
						((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(card.Name);
						((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("': style card '");
						((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(card.StyleFrom);
						((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("' not found; keeping the carrier's look.");
					}
					log.LogWarning(val3);
				}
				else
				{
					val.rarity = val2.rarity;
					val.isFullArt = val2.isFullArt;
					val.overrideBackGroundMaterial = val2.overrideBackGroundMaterial;
					val.overrideBackGroundMaterialTexture = val2.overrideBackGroundMaterialTexture;
					val.overrideBackGroundMaterialNormalMap = val2.overrideBackGroundMaterialNormalMap;
					val.overrideThumbnailMaterial = val2.overrideThumbnailMaterial;
					val.overrideNameFontMaterial = val2.overrideNameFontMaterial;
					val.overrideShineColor = val2.overrideShineColor;
					val.shineColor = val2.shineColor;
					val.overrideBackColor = val2.overrideBackColor;
					val.backColor = val2.backColor;
					val.thumbnail = val2.thumbnail;
					val.thumbnailOffset = val2.thumbnailOffset;
					ManualLogSource log2 = Log;
					BepInExInfoLogInterpolatedStringHandler val4 = new BepInExInfoLogInterpolatedStringHandler(81, 7, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("'");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(card.Name);
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("': look and rarity (");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<ObstacleRarity>(val2.rarity);
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(") from '");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(((Object)val2).name);
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("' (full art ");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<bool>(val2.isFullArt);
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(", ");
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("bg material ");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(((Object)(object)val2.overrideBackGroundMaterial != (Object)null) ? ((Object)val2.overrideBackGroundMaterial).name : "none");
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(", ");
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("bg sprite ");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(((Object)(object)val2.overrideBackGroundMaterialTexture != (Object)null) ? ((Object)val2.overrideBackGroundMaterialTexture).name : "none");
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(", ");
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("thumbnail ");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(((Object)(object)val2.thumbnail != (Object)null) ? ((Object)val2.thumbnail).name : "none");
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(").");
					}
					log2.LogInfo(val4);
				}
			}
			if (card.Rarity.HasValue)
			{
				val.rarity = card.Rarity.Value;
			}
			val.maxQuantity = -1;
			val.generationContexts = null;
			val.allowedAffixes = (card.Giant ? WithGiant(carrier.allowedAffixes, catalog) : null);
			Texture2D val5 = LoadArt(card.Art);
			if ((Object)(object)val5 != (Object)null)
			{
				val.thumbnail = val5;
				val.isFullArt = false;
				val.overrideBackGroundMaterial = null;
				val.overrideBackGroundMaterialTexture = null;
				val.overrideBackGroundMaterialNormalMap = null;
				val.overrideThumbnailMaterial = null;
				val.overrideNameFontMaterial = null;
				val.overrideBackColor = false;
				val.overrideShineColor = false;
				val.thumbnailOffset = Vector3.zero;
			}
			Texture2D val6 = LoadArt(card.Background);
			if ((Object)(object)val6 != (Object)null)
			{
				val.overrideBackGroundMaterialTexture = Sprite.Create(val6, new Rect(0f, 0f, (float)((Texture)val6).width, (float)((Texture)val6).height), new Vector2(0.5f, 0.5f));
				val.thumbnail = val6;
				string text = card.Background.Replace(".png", "_normal.png");
				if (typeof(Plugin).Assembly.GetManifestResourceInfo(text) != null)
				{
					val.overrideBackGroundMaterialNormalMap = (Texture)(object)LoadArt(text);
				}
			}
			return val;
		}

		private static ObstacleAffixDescription[] WithGiant(ObstacleAffixDescription[] own, ObstacleDescription[] catalog)
		{
			List<ObstacleAffixDescription> list = ((IEnumerable<ObstacleAffixDescription>)(((object)own) ?? ((object)new ObstacleAffixDescription[0]))).Where((ObstacleAffixDescription a) => (Object)(object)a != (Object)null).ToList();
			if (list.Any(IsGiant))
			{
				return list.ToArray();
			}
			ObstacleAffixDescription val = catalog.Where((ObstacleDescription x) => x?.allowedAffixes != null).SelectMany((ObstacleDescription x) => x.allowedAffixes).FirstOrDefault((Func<ObstacleAffixDescription, bool>)IsGiant) ?? ObstacleAffixManager.instance?.allowedObstacleAffixDescriptions?.FirstOrDefault((Func<ObstacleAffixDescription, bool>)IsGiant);
			if ((Object)(object)val == (Object)null)
			{
				Log.LogWarning((object)"No Giant affix found; the card won't roll Giant.");
			}
			else
			{
				list.Add(val);
			}
			return list.ToArray();
		}

		private static bool IsGiant(ObstacleAffixDescription a)
		{
			if ((Object)(object)a != (Object)null)
			{
				return a.callbacks is ObstacleAffixGiantCallBacks;
			}
			return false;
		}

		internal static void CopyFields(object from, object to)
		{
			FieldInfo[] fields = from.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (FieldInfo fieldInfo in fields)
			{
				fieldInfo.SetValue(to, fieldInfo.GetValue(from));
			}
		}

		private static Texture2D LoadArt(string file)
		{
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Expected O, but got Unknown
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Expected O, but got Unknown
			if (file == null)
			{
				return null;
			}
			using Stream stream = typeof(Plugin).Assembly.GetManifestResourceStream(file);
			bool flag = default(bool);
			BepInExWarningLogInterpolatedStringHandler val;
			if (stream == null)
			{
				ManualLogSource log = Log;
				val = new BepInExWarningLogInterpolatedStringHandler(42, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Card art '");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(file);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' isn't embedded; is it in art/?");
				}
				log.LogWarning(val);
				return null;
			}
			byte[] array = new byte[stream.Length];
			stream.Read(array, 0, array.Length);
			Texture2D val2 = new Texture2D(2, 2, (TextureFormat)4, false)
			{
				name = file,
				wrapMode = (TextureWrapMode)1
			};
			if (ImageConversion.LoadImage(val2, array))
			{
				return val2;
			}
			ManualLogSource log2 = Log;
			val = new BepInExWarningLogInterpolatedStringHandler(33, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Card art '");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(file);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' isn't a readable PNG.");
			}
			log2.LogWarning(val);
			return null;
		}

		private static bool ApplyCardEffect(ObstacleGameModifier __instance)
		{
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Expected O, but got Unknown
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Expected O, but got Unknown
			Card card = CardPlayedBy((Obstacle)(object)__instance);
			if (card == null || (card.Apply == null && card.ApplyToOwner == null))
			{
				return true;
			}
			bool flag = default(bool);
			try
			{
				if (card.ApplyToOwner != null)
				{
					card.ApplyToOwner(OwnerOf((Obstacle)(object)__instance));
				}
				else
				{
					card.Apply();
				}
				ManualLogSource log = Log;
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(10, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Played '");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(card.Name);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("'.");
				}
				log.LogInfo(val);
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = Log;
				BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(17, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("'");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(card.Name);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("' effect threw: ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Exception>(ex);
				}
				log2.LogError(val2);
			}
			return false;
		}

		private static PlayerData OwnerOf(Obstacle obstacle)
		{
			return GameManager.Players?.FirstOrDefault((Func<PlayerData, bool>)((PlayerData p) => (Object)(object)p != (Object)null && p.playerIndex.Value == obstacle.playerInfosIndex.Value));
		}

		private static Card CardPlayedBy(Obstacle obstacle)
		{
			PlayerData val = OwnerOf(obstacle);
			NetworkList<int> val2 = GameManager.instance?.networkVariables?.obstaclesToSelectIndices;
			ObstacleDescription[] catalog = ObstacleManager.instance?.allowedObstacleDescriptions;
			if ((Object)(object)val == (Object)null || val2 == null || catalog == null)
			{
				return null;
			}
			int value = val.selectedObstacleIndex.Value;
			if (value < 0 || value >= val2.Count)
			{
				return null;
			}
			int index = val2[value];
			if (index < 0 || index >= catalog.Length)
			{
				return null;
			}
			return Cards.All.FirstOrDefault((Card c) => (Object)(object)c.Asset == (Object)(object)catalog[index]);
		}

		[HarmonyPatch(typeof(ObstacleManager), "GetRandomObstaclesDescriptions")]
		[HarmonyPostfix]
		private static void ForceCardsInDraft(((int, ObstacleDescription)[], (int, ObstacleAffixDescription)[]) __result)
		{
			(int, ObstacleDescription)[] item = __result.Item1;
			ObstacleDescription[] array = ObstacleManager.instance?.allowedObstacleDescriptions;
			if (!_forceInDraft.Value || item == null || array == null)
			{
				return;
			}
			List<Card> list = Cards.All.AsEnumerable().Reverse().ToList();
			for (int i = 0; i < list.Count && i < item.Length; i++)
			{
				int num = Array.IndexOf(array, list[i].Asset);
				if (num >= 0)
				{
					item[i] = (num, list[i].Asset);
				}
			}
		}

		[HarmonyPatch(typeof(ObstacleSelectionElement), "Init")]
		[HarmonyPostfix]
		private static void LabelCard(ObstacleSelectionElement __instance, ObstacleDescription obstacleDescription)
		{
			Card card = Cards.All.FirstOrDefault((Card c) => (Object)(object)c.Asset == (Object)(object)obstacleDescription);
			if (card != null)
			{
				if ((Object)(object)__instance.nameLabel != (Object)null)
				{
					__instance.nameLabel.text = card.Name;
				}
				if ((Object)(object)__instance.descriptionLabel != (Object)null)
				{
					__instance.descriptionLabel.text = card.Text;
				}
			}
		}
	}
	internal static class RandomCard
	{
		private const float TurnAwaySeconds = 0.3f;

		private const float TurnBackSeconds = 0.6f;

		private const float RevealSeconds = 2.2f;

		private const float WaitForRollSeconds = 2f;

		private static bool _rolledThisDraft;

		private static readonly Dictionary<ObstacleSelectionElement, float> WaitingSince = new Dictionary<ObstacleSelectionElement, float>();

		private static readonly Dictionary<ObstacleSelectionElement, float> RevealedAt = new Dictionary<ObstacleSelectionElement, float>();

		private static bool IsRandom(ObstacleDescription d)
		{
			return Cards.All.Any((Card c) => c.RandomFrom != null && (Object)(object)c.Asset == (Object)(object)d);
		}

		[HarmonyPatch(typeof(GameManager), "SelectObstacleDescription")]
		[HarmonyPostfix]
		private static void Roll(GameManager __instance, PlayerData player, int obstacleDescriptionIndex)
		{
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Expected O, but got Unknown
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Expected O, but got Unknown
			Traverse val = Traverse.Create((object)__instance);
			PlayerData[] value = val.Field("_playerObstaclesSelection").GetValue<PlayerData[]>();
			(int, ObstacleDescription)[] slots = val.Field("_obstaclesToSelect").GetValue<(int, ObstacleDescription)[]>();
			(int, ObstacleAffixDescription)[] value2 = val.Field("_obstacleAffixDescriptions").GetValue<(int, ObstacleAffixDescription)[]>();
			int slot = obstacleDescriptionIndex;
			if (value == null || slots == null || value2 == null || slot < 0 || slot >= slots.Length || (Object)(object)value[slot] != (Object)(object)player)
			{
				return;
			}
			Card card = Cards.All.FirstOrDefault((Card c) => c.RandomFrom != null && (Object)(object)c.Asset == (Object)(object)slots[slot].Item2);
			if (card == null)
			{
				return;
			}
			ObstacleManager instance = ObstacleManager.instance;
			ObstacleDescription[] allowedObstacleDescriptions = instance.allowedObstacleDescriptions;
			ObstacleDescription[] array = ObstacleManager.FilterDescriptionsWithGameRules(allowedObstacleDescriptions.Where((ObstacleDescription d) => (Object)(object)d?.prefab != (Object)null && card.RandomFrom(d) && !IsRandom(d)).ToArray());
			bool flag = default(bool);
			if (array.Length == 0)
			{
				ManualLogSource log = Plugin.Log;
				BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(79, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("'");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(card.Name);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("': nothing to roll (the lobby's rules ban every candidate); it stays as it is.");
				}
				log.LogWarning(val2);
				return;
			}
			int randomObstacleIndex = instance.GetRandomObstacleIndex(array, (ValueTuple<int, ObstacleDescription>[])null, 0);
			ObstacleDescription val3 = allowedObstacleDescriptions[randomObstacleIndex];
			(int, ObstacleAffixDescription) tuple = (((double)Random.value < instance.obstacleModifierChance) ? ObstacleAffixManager.GetRandomAffixWithIndex(val3) : (0, ObstacleAffixManager.None));
			slots[slot] = (randomObstacleIndex, val3);
			value2[slot] = tuple;
			__instance.networkVariables.obstaclesToSelectIndices[slot] = randomObstacleIndex;
			__instance.networkVariables.obstaclesModifiersIndices[slot] = tuple.Item1;
			_rolledThisDraft = true;
			ManualLogSource log2 = Plugin.Log;
			BepInExInfoLogInterpolatedStringHandler val4 = new BepInExInfoLogInterpolatedStringHandler(9, 3, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("'");
				((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(card.Name);
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("' -> '");
				((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(((Object)val3).name);
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("'");
				object obj;
				if (tuple.Item1 == 0)
				{
					obj = "";
				}
				else
				{
					ObstacleAffixDescription item = tuple.Item2;
					obj = " (" + ((item != null) ? ((Object)item).name : null) + ")";
				}
				((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>((string)obj);
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(".");
			}
			log2.LogInfo(val4);
		}

		[HarmonyPatch(typeof(ObstacleSelectionElement), "SetSelected")]
		[HarmonyPrefix]
		private static bool Reveal(ObstacleSelectionElement __instance)
		{
			if (RevealedAt.TryGetValue(__instance, out var value))
			{
				return Time.time - value >= 2.2f;
			}
			if (!IsRandom(__instance.Description))
			{
				return true;
			}
			if (!WaitingSince.TryGetValue(__instance, out var value2))
			{
				value2 = (WaitingSince[__instance] = Time.time);
			}
			GameManagerNetworkVariables val = GameManager.instance?.networkVariables;
			int value3 = Traverse.Create((object)__instance).Field("_index").GetValue<int>();
			if ((Object)(object)val == (Object)null || value3 < 0 || value3 >= val.obstaclesToSelectIndices.Count)
			{
				return true;
			}
			ObstacleDescription descriptionFromIndex = ObstacleManager.GetDescriptionFromIndex(val.obstaclesToSelectIndices[value3], false);
			if ((Object)(object)descriptionFromIndex == (Object)(object)__instance.Description)
			{
				return Time.time - value2 >= 2f;
			}
			int num = ((value3 < val.obstaclesModifiersIndices.Count) ? val.obstaclesModifiersIndices[value3] : 0);
			((MonoBehaviour)__instance).StartCoroutine(Flip(__instance, descriptionFromIndex, ObstacleAffixManager.GetAffixByIndex(num)));
			RevealedAt[__instance] = Time.time;
			return false;
		}

		private static IEnumerator Flip(ObstacleSelectionElement card, ObstacleDescription rolled, ObstacleAffixDescription affix)
		{
			EasedRotation[] array = (EasedRotation[])(((object)card.rotationEasing) ?? ((object)new EasedRotation[0]));
			foreach (EasedRotation val in array)
			{
				if (Object.op_Implicit((Object)(object)val))
				{
					((Behaviour)val).enabled = false;
				}
			}
			RectTransform turn = card.mainContainer;
			if (Object.op_Implicit((Object)(object)card.rotateSoundsStart))
			{
				SplitScreenAudioManager.PlayStaticClip(card.rotateSoundsStart, 0f, 1f, 1f);
			}
			for (float s = 0f; s < 0.3f; s += Time.deltaTime)
			{
				float num = s / 0.3f;
				((Transform)turn).rotation = Quaternion.Euler(0f, 180f * num * num, 0f);
				yield return null;
			}
			card.Init(rolled, affix);
			if (Object.op_Implicit((Object)(object)card.cardBack))
			{
				((Component)card.cardBack).gameObject.SetActive(true);
			}
			for (float s = 0f; s < 0.6f; s += Time.deltaTime)
			{
				float num2 = 1f - s / 0.6f;
				((Transform)turn).rotation = Quaternion.Euler(0f, 180f * num2 * num2, 0f);
				yield return null;
			}
			((Transform)turn).rotation = Quaternion.identity;
			if (Object.op_Implicit((Object)(object)card.rotateSoundsEnd))
			{
				SplitScreenAudioManager.PlayStaticClip(card.rotateSoundsEnd, 0f, 1f, 1f);
			}
		}

		[HarmonyPatch(typeof(GameManager), "WaitAndGoToPlacingObstacles")]
		[HarmonyPostfix]
		private static void HoldDraftForReveal(ref IEnumerator __result)
		{
			if (_rolledThisDraft)
			{
				_rolledThisDraft = false;
				__result = After(2.2f, __result);
			}
		}

		private static IEnumerator After(float seconds, IEnumerator then)
		{
			yield return (object)new WaitForSeconds(seconds);
			while (then.MoveNext())
			{
				yield return then.Current;
			}
		}
	}
	internal static class RcMode
	{
		private static readonly OneRound Round = new OneRound();

		public static void Play()
		{
			Round.Arm();
		}

		[HarmonyPatch(typeof(SphereCarController), "ApplyModifiers")]
		[HarmonyPostfix]
		private static void Shrink(SphereCarController __instance)
		{
			//IL_000e: 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)
			if (Round.Active)
			{
				__instance.AddScale(Vector3.one * Plugin.RcScale.Value, (ModifierValueType)2);
				__instance.maxSpeed *= Plugin.RcSpeed.Value;
				__instance.speed *= Plugin.RcSpeed.Value;
			}
		}
	}
	internal static class Shrink
	{
		private static float _scale = 1f;

		private static GameManager _hookedTo;

		public static void Play()
		{
			if ((Object)(object)_hookedTo != (Object)(object)GameManager.instance)
			{
				_scale = 1f;
				_hookedTo = GameManager.instance;
				_hookedTo.onStateChange.AddListener((UnityAction<GameState>)delegate(GameState state)
				{
					//IL_0000: Unknown result type (might be due to invalid IL or missing references)
					//IL_0003: Invalid comparison between Unknown and I4
					//IL_0005: Unknown result type (might be due to invalid IL or missing references)
					if ((int)state == 10 || (int)state == 0)
					{
						_scale = 1f;
					}
				});
			}
			_scale *= 1f - Plugin.ShrinkPercent.Value / 100f;
		}

		[HarmonyPatch(typeof(SphereCarController), "ApplyModifiers")]
		[HarmonyPostfix]
		private static void Apply(SphereCarController __instance)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if (_scale != 1f)
			{
				__instance.AddScale(Vector3.one * _scale, (ModifierValueType)2);
			}
		}
	}
	internal static class TrainHorn
	{
		private const float HornPitch = 0.45f;

		private static AudioClip _sound;

		private static bool _soundLoaded;

		private static readonly OneRound Round;

		private static readonly HashSet<PlayerData> Holders;

		private static readonly Dictionary<PlayerData, float> LastBlast;

		static TrainHorn()
		{
			Round = new OneRound();
			Holders = new HashSet<PlayerData>();
			LastBlast = new Dictionary<PlayerData, float>();
			Round.Ended += delegate
			{
				Holders.Clear();
				LastBlast.Clear();
			};
		}

		public static void Give(PlayerData holder)
		{
			if (!((Object)(object)holder == (Object)null))
			{
				Holders.Add(holder);
				Round.Arm();
			}
		}

		private static void LogClip(AudioClip clip)
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			float[] array = new float[Math.Min(4096, clip.samples * clip.channels)];
			bool data = clip.GetData(array, 0);
			float num = ((array.Length == 0) ? 0f : ((IEnumerable<float>)array).Max((Func<float, float>)Math.Abs));
			ManualLogSource log = Plugin.Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(51, 6, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Train Horn sound: ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((Object)clip).name);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(clip.length, "0.00");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("s, ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(clip.channels);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("ch ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(clip.frequency);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Hz, data readable=");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(data);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", peak=");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(num, "0.000");
			}
			log.LogInfo(val)