Decompiled source of SuperBattleBros v0.7.7

SbgShields.dll

Decompiled 5 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using FMOD.Studio;
using FMODUnity;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mirror;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.Rendering;

[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("SbgShields")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+6117a8cb81b860e7f21d94cef7865cd7fba20110")]
[assembly: AssemblyProduct("SbgShields")]
[assembly: AssemblyTitle("SbgShields")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[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 SbgShields
{
	internal static class Hud
	{
		private struct ShakeStep
		{
			public float pct;

			public float secs;
		}

		private static Font _font;

		private static bool _fontSearched;

		private static Texture2D _bubbleTex;

		private static Texture2D _dotTex;

		private static GUIStyle _percentStyle;

		private static GUIStyle _timerStyle;

		private static GUIStyle _labelStyle;

		private static double _shakeStart = double.MinValue;

		private static float _shakeSeed;

		private static int _cachedPct = int.MinValue;

		private static int _cachedFontSize = -1;

		private static readonly GUIContent _pctContent = new GUIContent();

		private static Vector2 _pctSize;

		private static Vector2 _pctMax;

		private static bool _pipsWereShown;

		private static double _pipsShownAt = double.MinValue;

		private static Vector2 _lastOffset;

		private static ShakeStep[] _shakeTable;

		private static string _shakeTableSource;

		private static GUIStyle _noticeBig;

		private static GUIStyle _noticeSmall;

		private static Texture2D _panelTex;

		internal static void Init()
		{
			ShieldState.PercentIncreased -= OnPercentIncreased;
			ShieldState.PercentIncreased += OnPercentIncreased;
		}

		internal static void Shutdown()
		{
			ShieldState.PercentIncreased -= OnPercentIncreased;
			if ((Object)(object)_panelTex != (Object)null)
			{
				Object.Destroy((Object)(object)_panelTex);
				_panelTex = null;
			}
			if ((Object)(object)_bubbleTex != (Object)null)
			{
				Object.Destroy((Object)(object)_bubbleTex);
				_bubbleTex = null;
			}
			if ((Object)(object)_dotTex != (Object)null)
			{
				Object.Destroy((Object)(object)_dotTex);
				_dotTex = null;
			}
			_percentStyle = null;
			_fontSearched = false;
			_cachedPct = int.MinValue;
		}

		internal static void InvalidateFont()
		{
			_fontSearched = false;
			_percentStyle = null;
			_cachedPct = int.MinValue;
		}

		private static void OnPercentIncreased(float _)
		{
			_shakeStart = Time.timeAsDouble;
			_shakeSeed = Random.value * 100f;
		}

		private static void EnsureAssets()
		{
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Expected O, but got Unknown
			//IL_0106: 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_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Expected O, but got Unknown
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Expected O, but got Unknown
			if (!_fontSearched)
			{
				_fontSearched = true;
				_font = FindFont(Plugin.PercentFontName.Value);
				if ((Object)(object)_font == (Object)null)
				{
					Plugin.Log.LogWarning((object)("Font '" + Plugin.PercentFontName.Value + "' not installed on this machine; using the default. Install DF Gothic as a system font and restart to use it."));
				}
				else
				{
					Plugin.Log.LogInfo((object)("Percent font: " + ((Object)_font).name));
				}
			}
			if ((Object)(object)_bubbleTex == (Object)null)
			{
				_bubbleTex = MakeBubbleTexture(128);
			}
			if ((Object)(object)_dotTex == (Object)null)
			{
				_dotTex = MakeDotTexture(24);
			}
			if (_percentStyle == null)
			{
				_percentStyle = new GUIStyle(GUI.skin.label)
				{
					alignment = (TextAnchor)6,
					fontStyle = (FontStyle)1,
					wordWrap = false,
					clipping = (TextClipping)0
				};
				if ((Object)(object)_font != (Object)null)
				{
					_percentStyle.font = _font;
				}
				_percentStyle.normal.textColor = Color.white;
				_timerStyle = new GUIStyle(_percentStyle)
				{
					alignment = (TextAnchor)4
				};
				_labelStyle = new GUIStyle(_percentStyle)
				{
					alignment = (TextAnchor)4,
					fontStyle = (FontStyle)0
				};
			}
		}

		private static Font FindFont(string wanted)
		{
			if (string.IsNullOrEmpty(wanted))
			{
				return null;
			}
			try
			{
				string[] oSInstalledFontNames = Font.GetOSInstalledFontNames();
				string text = Normalize(wanted);
				string text2 = null;
				string[] array = oSInstalledFontNames;
				foreach (string text3 in array)
				{
					string text4 = Normalize(text3);
					if (text4 == text)
					{
						text2 = text3;
						break;
					}
					if (text2 == null && text4.Contains(text))
					{
						text2 = text3;
					}
				}
				if (text2 == null)
				{
					return null;
				}
				return Font.CreateDynamicFontFromOSFont(text2, 64);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Font lookup failed: " + ex.Message));
				return null;
			}
		}

		private static string Normalize(string s)
		{
			return s.Replace(" ", "").Replace("-", "").Replace("_", "")
				.ToLowerInvariant();
		}

		private static Texture2D MakeBubbleTexture(int size)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(size, size, (TextureFormat)4, false)
			{
				wrapMode = (TextureWrapMode)1,
				filterMode = (FilterMode)1
			};
			float num = (float)size * 0.5f;
			Color[] array = (Color[])(object)new Color[size * size];
			for (int i = 0; i < size; i++)
			{
				for (int j = 0; j < size; j++)
				{
					float num2 = ((float)j + 0.5f - num) / num;
					float num3 = ((float)i + 0.5f - num) / num;
					float num4 = Mathf.Sqrt(num2 * num2 + num3 * num3);
					float num5 = 0f;
					if (num4 < 1f)
					{
						float num6 = Mathf.Lerp(0.22f, 0.55f, Mathf.Pow(num4, 2.5f));
						float num7 = Mathf.Exp(0f - Mathf.Pow((num4 - 0.93f) / 0.05f, 2f)) * 0.9f;
						float num8 = num2 + 0.42f;
						float num9 = num3 - 0.42f;
						float num10 = Mathf.Exp((0f - (num8 * num8 + num9 * num9)) / 0.05f) * 0.85f;
						num5 = Mathf.Clamp01(num6 + num7 + num10);
						num5 *= Mathf.Clamp01((1f - num4) / 0.03f);
					}
					array[i * size + j] = new Color(1f, 1f, 1f, num5);
				}
			}
			val.SetPixels(array);
			val.Apply();
			return val;
		}

		private static Texture2D MakeDotTexture(int size)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_003d: 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_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(size, size, (TextureFormat)4, false)
			{
				wrapMode = (TextureWrapMode)1
			};
			float num = (float)size * 0.5f;
			Color[] array = (Color[])(object)new Color[size * size];
			for (int i = 0; i < size; i++)
			{
				for (int j = 0; j < size; j++)
				{
					float num2 = Vector2.Distance(new Vector2((float)j + 0.5f, (float)i + 0.5f), new Vector2(num, num)) / num;
					array[i * size + j] = new Color(1f, 1f, 1f, Mathf.Clamp01((1f - num2) / 0.12f));
				}
			}
			val.SetPixels(array);
			val.Apply();
			return val;
		}

		internal static void Draw()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Invalid comparison between Unknown and I4
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
			if (Event.current == null || (int)Event.current.type != 7 || !Plugin.ShowHud.Value)
			{
				return;
			}
			if (!ModHandshake.GameplayEnabled)
			{
				DrawStandDownNotice();
				return;
			}
			PlayerInfo localPlayerInfo = GameManager.LocalPlayerInfo;
			if ((Object)(object)localPlayerInfo == (Object)null || !ShouldShow())
			{
				return;
			}
			try
			{
				if ((Object)(object)localPlayerInfo.Movement != (Object)null && localPlayerInfo.Movement.IsRespawningOrDrowning)
				{
					return;
				}
			}
			catch
			{
			}
			if (!KillZone.IsLingering)
			{
				EnsureAssets();
				float value = Plugin.HudScale.Value;
				float num = (float)Screen.height - Plugin.HudBottomMargin.Value * value;
				bool inPlayableHole = ShieldState.InPlayableHole;
				int num2 = Mathf.RoundToInt((float)Plugin.PercentFontSize.Value * value);
				int num3 = Mathf.RoundToInt(ShieldState.Percent);
				if (num3 != _cachedPct || num2 != _cachedFontSize)
				{
					_cachedPct = num3;
					_cachedFontSize = num2;
					_pctContent.text = num3 + "%";
					_percentStyle.fontSize = Mathf.RoundToInt((float)num2 * (1f + Plugin.PercentShakePunch.Value));
					_pctMax = _percentStyle.CalcSize(_pctContent);
					_percentStyle.fontSize = num2;
					_pctSize = _percentStyle.CalcSize(_pctContent);
				}
				float num4 = (inPlayableHole ? (((float)Screen.width - _pctSize.x) * 0.5f + Plugin.HudHorizontalOffset.Value * value) : ((float)Screen.width * 0.5f + Plugin.HudHorizontalOffset.Value * value));
				float num5 = num + Plugin.PercentVerticalOffset.Value * value;
				if (inPlayableHole)
				{
					DrawPercent(new Rect(num4, num5 - _pctSize.y, _pctSize.x, _pctSize.y), _pctContent.text, num2);
				}
				bool isElectromagnetShieldActive = localPlayerInfo.IsElectromagnetShieldActive;
				bool flag = ShieldState.IsOnBreakCooldown || (ShieldState.Pips <= 0 && !Plugin.RestoreAfterBreakCooldown.Value);
				bool flag2 = !isElectromagnetShieldActive && Plugin.ActivationBlockedByState(localPlayerInfo, forHud: true);
				bool flag3 = isElectromagnetShieldActive || !flag2 || flag;
				bool flag4 = Plugin.ShowPipDots.Value && flag3 && !flag && ShieldState.Pips > 0;
				if (flag4 && !_pipsWereShown)
				{
					_pipsShownAt = Time.timeAsDouble;
				}
				_pipsWereShown = flag4;
				if (flag3)
				{
					float num6 = Plugin.BubbleHudSize.Value * value;
					float num7 = Plugin.BubbleHudGap.Value * value;
					float num8 = ((!inPlayableHole) ? (num4 - num6 * 0.5f) : (Plugin.BubbleHudOnLeft.Value ? (num4 - num7 - num6) : (num4 + _pctMax.x + num7)));
					float num9 = num - num6;
					DrawBubble(localPlayerInfo, new Rect(num8, num9, num6, num6), value, isElectromagnetShieldActive, flag, flag4);
				}
			}
		}

		private static float PopEase(float t)
		{
			if (t <= 0f)
			{
				return 0f;
			}
			if (t >= 1f)
			{
				return 1f;
			}
			float num = t - 1f;
			return 1f + 2.70158f * num * num * num + 1.70158f * num * num;
		}

		private static bool ShouldShow()
		{
			//IL_0021: 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_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Invalid comparison between Unknown and I4
			try
			{
				if (PauseMenu.IsPaused)
				{
					return false;
				}
				if (Scoreboard.IsVisible)
				{
					return false;
				}
				if (ShieldState.InDrivingRange)
				{
					return true;
				}
				MatchState matchState = CourseManager.MatchState;
				if (matchState - 2 <= 3)
				{
					return true;
				}
				return false;
			}
			catch
			{
				return true;
			}
		}

		private static void DrawPercent(Rect rect, string text, int fontSize)
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_028c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Unknown result type (might be due to invalid IL or missing references)
			//IL_0299: Unknown result type (might be due to invalid IL or missing references)
			//IL_029b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a7: 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_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: 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_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_0269: Unknown result type (might be due to invalid IL or missing references)
			float num = ShakeDuration(ShieldState.Percent);
			float num2 = ((num <= 0.01f) ? 1f : ((float)((Time.timeAsDouble - _shakeStart) / (double)num)));
			float num3 = 0f;
			float num4 = 1f;
			if (num2 >= 0f && num2 < 1f)
			{
				float num5 = (1f - num2) * (1f - num2);
				num3 = Plugin.PercentShakePixels.Value * num5;
				num4 = 1f + Plugin.PercentShakePunch.Value * num5 * num5;
			}
			Vector2 zero = Vector2.zero;
			if (num3 > 0.01f)
			{
				float num6 = Time.time * Plugin.PercentShakeSpeed.Value + _shakeSeed;
				((Vector2)(ref zero))..ctor((Mathf.PerlinNoise(num6, 0.3f) - 0.5f) * 2f * num3, (Mathf.PerlinNoise(0.7f, num6) - 0.5f) * 2f * num3);
			}
			Rect r = default(Rect);
			((Rect)(ref r))..ctor(((Rect)(ref rect)).x + zero.x, ((Rect)(ref rect)).yMax - _pctSize.y + zero.y, _pctSize.x, _pctSize.y);
			Color val = PercentColor(ShieldState.Percent);
			float thickness = Mathf.Max(1f, 3f * Plugin.HudScale.Value);
			Matrix4x4 matrix = GUI.matrix;
			if (num4 != 1f)
			{
				GUIUtility.ScaleAroundPivot(new Vector2(num4, num4), ((Rect)(ref r)).center);
			}
			_percentStyle.fontSize = fontSize;
			int num7 = Mathf.RoundToInt(Plugin.PercentBlurSamples.Value);
			if (num7 > 0 && num3 > 0.5f)
			{
				Vector2 val2 = zero - _lastOffset;
				if (((Vector2)(ref val2)).sqrMagnitude > 0.01f)
				{
					float num8 = Mathf.Clamp01(num3 / Mathf.Max(1f, Plugin.PercentShakePixels.Value));
					Rect val3 = default(Rect);
					for (int i = 1; i <= num7; i++)
					{
						float num9 = (float)i / (float)(num7 + 1);
						((Rect)(ref val3))..ctor(((Rect)(ref r)).x - val2.x * num9 * Plugin.PercentBlurLength.Value, ((Rect)(ref r)).y - val2.y * num9 * Plugin.PercentBlurLength.Value, ((Rect)(ref r)).width, ((Rect)(ref r)).height);
						Color color = val;
						color.a = val.a * (1f - num9) * 0.5f * num8;
						Color color2 = GUI.color;
						GUI.color = color;
						GUI.Label(val3, text, _percentStyle);
						GUI.color = color2;
					}
				}
			}
			_lastOffset = zero;
			DrawOutlined(r, text, _percentStyle, val, Color.black, thickness);
			GUI.matrix = matrix;
		}

		private static float ShakeDuration(float pct)
		{
			ShakeStep[] array = ShakeTable();
			if (array == null || array.Length == 0)
			{
				return Plugin.PercentShakeDuration.Value;
			}
			if (pct <= array[0].pct)
			{
				return array[0].secs;
			}
			for (int i = 1; i < array.Length; i++)
			{
				if (!(pct > array[i].pct))
				{
					ShakeStep shakeStep = array[i - 1];
					ShakeStep shakeStep2 = array[i];
					float num = Mathf.Max(0.001f, shakeStep2.pct - shakeStep.pct);
					return Mathf.Lerp(shakeStep.secs, shakeStep2.secs, (pct - shakeStep.pct) / num);
				}
			}
			return array[^1].secs;
		}

		internal static void InvalidateShakeTable()
		{
			_shakeTable = null;
		}

		private static ShakeStep[] ShakeTable()
		{
			string value = Plugin.PercentShakeDurationTable.Value;
			if (_shakeTable != null && value == _shakeTableSource)
			{
				return _shakeTable;
			}
			_shakeTableSource = value;
			List<ShakeStep> list = new List<ShakeStep>();
			string[] array = value.Split(',');
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Split(':');
				if (array2.Length == 2 && float.TryParse(array2[0].Trim(), out var result) && float.TryParse(array2[1].Trim(), out var result2))
				{
					list.Add(new ShakeStep
					{
						pct = result,
						secs = Mathf.Max(0f, result2)
					});
				}
			}
			list.Sort((ShakeStep x, ShakeStep y) => x.pct.CompareTo(y.pct));
			if (list.Count == 0)
			{
				Plugin.Log.LogWarning((object)("Could not read PercentShakeDurationTable '" + value + "'; using PercentShakeDuration instead."));
			}
			_shakeTable = list.ToArray();
			return _shakeTable;
		}

		private static void DrawStandDownNotice()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Expected O, but got Unknown
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected O, but got Unknown
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_0269: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Expected O, but got Unknown
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_029b: Unknown result type (might be due to invalid IL or missing references)
			string blockReason = ModHandshake.BlockReason;
			if (!string.IsNullOrEmpty(blockReason))
			{
				if (_noticeBig == null)
				{
					_noticeBig = new GUIStyle(GUI.skin.label)
					{
						alignment = (TextAnchor)4,
						wordWrap = true,
						fontStyle = (FontStyle)1
					};
					_noticeSmall = new GUIStyle(GUI.skin.label)
					{
						alignment = (TextAnchor)4,
						wordWrap = true
					};
				}
				if ((Object)(object)_panelTex == (Object)null)
				{
					_panelTex = new Texture2D(1, 1, (TextureFormat)4, false);
					_panelTex.SetPixel(0, 0, new Color(0f, 0f, 0f, 0.78f));
					_panelTex.Apply();
				}
				float value = Plugin.HudScale.Value;
				if (!(Time.timeAsDouble - ModHandshake.BlockedSince < (double)Plugin.MismatchPopupDuration.Value))
				{
					_noticeSmall.fontSize = Mathf.RoundToInt(16f * value);
					string text = "SBG Shields inactive - " + blockReason;
					Vector2 val = _noticeSmall.CalcSize(new GUIContent(text));
					DrawOutlined(new Rect(((float)Screen.width - val.x) * 0.5f, 8f * value, val.x, val.y), text, _noticeSmall, new Color(1f, 0.78f, 0.25f), Color.black, 2f);
					return;
				}
				_noticeBig.fontSize = Mathf.RoundToInt(26f * value);
				_noticeSmall.fontSize = Mathf.RoundToInt(17f * value);
				float num = Mathf.Min((float)Screen.width * 0.7f, 720f * value);
				float num2 = 150f * value;
				Rect val2 = default(Rect);
				((Rect)(ref val2))..ctor(((float)Screen.width - num) * 0.5f, (float)Screen.height * 0.22f, num, num2);
				GUI.DrawTexture(val2, (Texture)(object)_panelTex, (ScaleMode)0);
				DrawOutlined(new Rect(((Rect)(ref val2)).x, ((Rect)(ref val2)).y + 14f * value, ((Rect)(ref val2)).width, 34f * value), "SBG Shields is standing down", _noticeBig, new Color(1f, 0.78f, 0.25f), Color.black, 2f);
				Rect r = new Rect(((Rect)(ref val2)).x + 20f * value, ((Rect)(ref val2)).y + 54f * value, ((Rect)(ref val2)).width - 40f * value, 80f * value);
				string text2 = (blockReason.Contains("public lobby") ? "The shield is disabled in public lobbies on purpose.\n\nHost a Friends or Invite Only lobby to use it." : (blockReason + ".\n\nThe match is running vanilla rules so nothing desyncs. Everyone needs SBG Shields 0.7.7 for the shield to work."));
				DrawOutlined(r, text2, _noticeSmall, Color.white, Color.black, 1.5f);
			}
		}

		private static Color PercentColor(float pct)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: 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_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: 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)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Clamp01(pct / Mathf.Max(1f, Plugin.PercentForMaxScaling.Value));
			if (num < 0.33f)
			{
				return Color.Lerp(Color.white, new Color(1f, 0.92f, 0.25f), num / 0.33f);
			}
			if (num < 0.66f)
			{
				return Color.Lerp(new Color(1f, 0.92f, 0.25f), new Color(1f, 0.55f, 0.1f), (num - 0.33f) / 0.33f);
			}
			return Color.Lerp(new Color(1f, 0.55f, 0.1f), new Color(0.9f, 0.08f, 0.08f), (num - 0.66f) / 0.34f);
		}

		private static void DrawBubble(PlayerInfo player, Rect rect, float scale, bool up, bool onBreakCd, bool showPips)
		{
			//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_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: 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_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: 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_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_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			Color val = Skin.Of(player);
			string reason;
			bool flag = ShieldState.CanActivate(out reason);
			float secondsUntilReady = ShieldState.SecondsUntilReady;
			Color color = val;
			if (up)
			{
				color = Color.Lerp(val, Color.white, 0.25f);
				rect = Grow(rect, 6f * scale);
			}
			else if (!flag)
			{
				color = val * 0.3f;
				color.a = 1f;
			}
			Color color2 = GUI.color;
			GUI.color = color;
			GUI.DrawTexture(rect, (Texture)(object)_bubbleTex, (ScaleMode)2, true);
			GUI.color = color2;
			if (!flag)
			{
				_timerStyle.fontSize = Mathf.RoundToInt((float)Plugin.PercentFontSize.Value * 0.42f * scale);
				string text = (float.IsInfinity(secondsUntilReady) ? "X" : ((secondsUntilReady >= 10f) ? $"{secondsUntilReady:0}" : $"{secondsUntilReady:0.0}"));
				DrawOutlined(rect, text, _timerStyle, Color.white, Color.black, Mathf.Max(1f, 2f * scale));
			}
			if (!showPips)
			{
				GUI.color = color2;
				return;
			}
			int num = Mathf.Max(1, Plugin.MaxPips.Value);
			float num2 = 12f * scale;
			float num3 = 5f * scale;
			float num4 = (float)num * num2 + (float)(num - 1) * num3;
			float num5 = ((Rect)(ref rect)).center.x - num4 * 0.5f;
			float num6 = ((Rect)(ref rect)).yMax + 4f * scale;
			double num7 = Time.timeAsDouble - _pipsShownAt;
			for (int i = 0; i < num; i++)
			{
				bool flag2 = i < ShieldState.Pips;
				float num8 = PopEase((float)((num7 - (double)i * 0.06) / 0.16));
				if (!(num8 <= 0f))
				{
					float num9 = num2 * num8;
					float num10 = num5 + (float)i * (num2 + num3) + num2 * 0.5f;
					float num11 = num6 + num2 * 0.5f;
					GUI.color = (Color)(flag2 ? val : new Color(0f, 0f, 0f, 0.55f));
					GUI.DrawTexture(new Rect(num10 - num9 * 0.5f, num11 - num9 * 0.5f, num9, num9), (Texture)(object)_dotTex, (ScaleMode)2, true);
				}
			}
			GUI.color = color2;
		}

		private static Rect Grow(Rect r, float by)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			return new Rect(((Rect)(ref r)).x - by, ((Rect)(ref r)).y - by, ((Rect)(ref r)).width + 2f * by, ((Rect)(ref r)).height + 2f * by);
		}

		private static void DrawOutlined(Rect r, string text, GUIStyle style, Color fill, Color outline, float thickness)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: 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_00e7: 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_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			Color textColor = style.normal.textColor;
			style.normal.textColor = outline;
			GUI.Label(new Rect(((Rect)(ref r)).x - thickness, ((Rect)(ref r)).y, ((Rect)(ref r)).width, ((Rect)(ref r)).height), text, style);
			GUI.Label(new Rect(((Rect)(ref r)).x + thickness, ((Rect)(ref r)).y, ((Rect)(ref r)).width, ((Rect)(ref r)).height), text, style);
			GUI.Label(new Rect(((Rect)(ref r)).x, ((Rect)(ref r)).y - thickness, ((Rect)(ref r)).width, ((Rect)(ref r)).height), text, style);
			GUI.Label(new Rect(((Rect)(ref r)).x, ((Rect)(ref r)).y + thickness, ((Rect)(ref r)).width, ((Rect)(ref r)).height), text, style);
			GUI.Label(new Rect(((Rect)(ref r)).x + thickness, ((Rect)(ref r)).y + thickness, ((Rect)(ref r)).width, ((Rect)(ref r)).height), text, style);
			style.normal.textColor = fill;
			GUI.Label(r, text, style);
			style.normal.textColor = textColor;
		}
	}
	internal static class KillZone
	{
		private static bool _armed;

		private static double _armedAt;

		private static bool _wentUp;

		private static bool _lingering;

		private static double _respawnAt;

		private static GameObject _flashGo;

		private static ParticleSystem _flashPs;

		private static ParticleSystem _sparkPs;

		private static Material _flashMat;

		private static Material _sparkMat;

		private static Texture2D _starTex;

		private static Texture2D _dotTex;

		internal static bool IsArmed => _armed;

		internal static bool IsLingering => _lingering;

		internal static void Arm()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: 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)
			_armed = true;
			_armedAt = Time.timeAsDouble;
			_wentUp = false;
			float value = Plugin.KillZoneUpwardBoost.Value;
			if (value > 0f)
			{
				ShieldState.PendingVelocityCorrection += Vector3.up * value;
				ShieldState.HasPendingVelocityCorrection = true;
				ShieldState.LaunchDragUntil = double.MinValue;
			}
			if (Plugin.VerboseLogging.Value)
			{
				Plugin.Log.LogInfo((object)$"Kill zone armed at {ShieldState.Percent:0}%: +{value:0} m/s up, waiting for the apex.");
			}
		}

		internal static void Disarm()
		{
			_armed = false;
		}

		internal static void Tick()
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			if (_lingering)
			{
				TickLinger();
			}
			else
			{
				if (!_armed)
				{
					return;
				}
				PlayerInfo localPlayerInfo = GameManager.LocalPlayerInfo;
				PlayerMovement val = (((Object)(object)localPlayerInfo != (Object)null) ? localPlayerInfo.Movement : null);
				if ((Object)(object)val == (Object)null)
				{
					_armed = false;
					return;
				}
				double timeAsDouble = Time.timeAsDouble;
				if (val.IsRespawningOrDrowning)
				{
					_armed = false;
					return;
				}
				if (!val.IsKnockedOut)
				{
					if (timeAsDouble - _armedAt > 1.0)
					{
						_armed = false;
					}
					return;
				}
				float y = val.Velocity.y;
				if (y > 0.5f)
				{
					_wentUp = true;
				}
				bool num = _wentUp && y <= 0f;
				bool flag = !_wentUp && timeAsDouble - _armedAt > 0.35;
				bool flag2 = timeAsDouble - _armedAt > (double)Plugin.KillZoneMaxRiseTime.Value;
				if (num || flag || flag2)
				{
					Fire(localPlayerInfo, val);
				}
			}
		}

		private static void Fire(PlayerInfo p, PlayerMovement mv)
		{
			//IL_0031: 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_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: 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_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			_armed = false;
			Vector3 val = (((Object)(object)p.ChestBone != (Object)null) ? p.ChestBone.position : (((Component)p).transform.position + Vector3.up));
			if (Plugin.VerboseLogging.Value)
			{
				Plugin.Log.LogInfo((object)$"STAR KO at {ShieldState.Percent:0}% (height {val.y:0.0}).");
			}
			if (Plugin.KillZoneFlash.Value)
			{
				try
				{
					PlayFlash(val, Skin.Of(p));
				}
				catch (Exception ex)
				{
					Plugin.Log.LogWarning((object)("Kill flash failed: " + ex.Message));
				}
			}
			if (Plugin.KillZoneBoom.Value)
			{
				try
				{
					RuntimeManager.PlayOneShot(GameManager.AudioSettings.ElectromagnetShieldExplosionEvent, val);
				}
				catch (Exception ex2)
				{
					if (Plugin.VerboseLogging.Value)
					{
						Plugin.Log.LogWarning((object)("Kill boom failed: " + ex2.Message));
					}
				}
				try
				{
					CameraModuleController.Shake(GameManager.CameraGameplaySettings.RocketExplosionScreenshakeSettings, val, 1.6f, 1.4f);
				}
				catch
				{
					try
					{
						CameraModuleController.Shake(GameManager.CameraGameplaySettings.ElectromagnetExplosionScreenshakeSettings, val, 1f, 1f);
					}
					catch
					{
					}
				}
			}
			ShieldState.Percent = Mathf.Max(0f, Plugin.PercentAfterKillZoneDeath.Value);
			ShieldState.BreakStunUntil = double.MinValue;
			ShieldState.LastKnockoutWasBreakStun = false;
			float num = Mathf.Max(0f, Plugin.KillZoneDeathLinger.Value);
			if (num > 0.01f && Hide(mv))
			{
				_lingering = true;
				_respawnAt = Time.timeAsDouble + (double)num;
			}
			else
			{
				BeginRespawn(mv);
			}
		}

		private static bool Hide(PlayerMovement mv)
		{
			try
			{
				mv.NetworkisVisible = false;
				return true;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Kill zone could not hide the player: " + ex.Message));
				return false;
			}
		}

		private static void TickLinger()
		{
			PlayerInfo localPlayerInfo = GameManager.LocalPlayerInfo;
			PlayerMovement val = (((Object)(object)localPlayerInfo != (Object)null) ? localPlayerInfo.Movement : null);
			if ((Object)(object)val == (Object)null)
			{
				_lingering = false;
			}
			else if (val.IsRespawningOrDrowning)
			{
				_lingering = false;
			}
			else if (!(Time.timeAsDouble < _respawnAt))
			{
				_lingering = false;
				BeginRespawn(val);
			}
		}

		private static void BeginRespawn(PlayerMovement mv)
		{
			ShieldState.KillZoneDeathPending = true;
			bool flag = false;
			try
			{
				flag = mv.TryBeginRespawn(false, (RespawnTarget)0, true);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Kill respawn failed: " + ex.Message));
			}
			if (!flag)
			{
				ShieldState.KillZoneDeathPending = false;
				Plugin.Log.LogWarning((object)"Kill zone: the game refused the respawn (already respawning / match resolved).");
				try
				{
					mv.NetworkisVisible = true;
				}
				catch
				{
				}
			}
		}

		internal static void CancelLinger()
		{
			if (!_lingering)
			{
				return;
			}
			_lingering = false;
			PlayerMovement val = (((Object)(object)GameManager.LocalPlayerInfo != (Object)null) ? GameManager.LocalPlayerInfo.Movement : null);
			if (!((Object)(object)val != (Object)null))
			{
				return;
			}
			try
			{
				val.NetworkisVisible = true;
			}
			catch
			{
			}
		}

		private static void EnsureFlash()
		{
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Expected O, but got Unknown
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: 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_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Expected O, but got Unknown
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_027b: Expected O, but got Unknown
			//IL_02af: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0312: Unknown result type (might be due to invalid IL or missing references)
			//IL_0323: Unknown result type (might be due to invalid IL or missing references)
			//IL_033b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0340: Unknown result type (might be due to invalid IL or missing references)
			//IL_0351: Unknown result type (might be due to invalid IL or missing references)
			//IL_036c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0371: Unknown result type (might be due to invalid IL or missing references)
			//IL_0380: Unknown result type (might be due to invalid IL or missing references)
			//IL_0385: 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_03d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fa: Expected O, but got Unknown
			//IL_03f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0404: Unknown result type (might be due to invalid IL or missing references)
			//IL_0409: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_flashGo != (Object)null))
			{
				if ((Object)(object)_starTex == (Object)null)
				{
					_starTex = MakeStarTexture(128);
				}
				if ((Object)(object)_dotTex == (Object)null)
				{
					_dotTex = MakeDotTexture(32);
				}
				if ((Object)(object)_flashMat == (Object)null)
				{
					_flashMat = LaunchVfx.MakeUnlitMaterial(_starTex, additive: true);
				}
				if ((Object)(object)_sparkMat == (Object)null)
				{
					_sparkMat = LaunchVfx.MakeUnlitMaterial(_dotTex, additive: true);
				}
				if (!((Object)(object)_flashMat == (Object)null))
				{
					_flashGo = new GameObject("SbgKillFlash");
					_flashPs = _flashGo.AddComponent<ParticleSystem>();
					_flashPs.Stop(true, (ParticleSystemStopBehavior)0);
					MainModule main = _flashPs.main;
					((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)1;
					((MainModule)(ref main)).loop = false;
					((MainModule)(ref main)).playOnAwake = false;
					((MainModule)(ref main)).duration = 0.1f;
					((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(0.55f);
					((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit(0f);
					((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(1f);
					((MainModule)(ref main)).gravityModifier = MinMaxCurve.op_Implicit(0f);
					((MainModule)(ref main)).maxParticles = 4;
					EmissionModule emission = _flashPs.emission;
					((EmissionModule)(ref emission)).enabled = true;
					((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(0f);
					((EmissionModule)(ref emission)).SetBursts((Burst[])(object)new Burst[1]
					{
						new Burst(0f, (short)1)
					});
					ShapeModule shape = _flashPs.shape;
					((ShapeModule)(ref shape)).enabled = false;
					SizeOverLifetimeModule sizeOverLifetime = _flashPs.sizeOverLifetime;
					((SizeOverLifetimeModule)(ref sizeOverLifetime)).enabled = true;
					((SizeOverLifetimeModule)(ref sizeOverLifetime)).size = new MinMaxCurve(1f, new AnimationCurve((Keyframe[])(object)new Keyframe[4]
					{
						new Keyframe(0f, 0.05f),
						new Keyframe(0.12f, 1f),
						new Keyframe(0.5f, 1.15f),
						new Keyframe(1f, 1.4f)
					}));
					ColorOverLifetimeModule colorOverLifetime = _flashPs.colorOverLifetime;
					((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled = true;
					RotationOverLifetimeModule rotationOverLifetime = _flashPs.rotationOverLifetime;
					((RotationOverLifetimeModule)(ref rotationOverLifetime)).enabled = true;
					((RotationOverLifetimeModule)(ref rotationOverLifetime)).z = MinMaxCurve.op_Implicit(0.9f);
					ParticleSystemRenderer component = _flashGo.GetComponent<ParticleSystemRenderer>();
					((Renderer)component).sharedMaterial = _flashMat;
					component.renderMode = (ParticleSystemRenderMode)0;
					((Renderer)component).shadowCastingMode = (ShadowCastingMode)0;
					((Renderer)component).receiveShadows = false;
					GameObject val = new GameObject("Sparks");
					val.transform.SetParent(_flashGo.transform, false);
					_sparkPs = val.AddComponent<ParticleSystem>();
					_sparkPs.Stop(true, (ParticleSystemStopBehavior)0);
					MainModule main2 = _sparkPs.main;
					((MainModule)(ref main2)).simulationSpace = (ParticleSystemSimulationSpace)1;
					((MainModule)(ref main2)).loop = false;
					((MainModule)(ref main2)).playOnAwake = false;
					((MainModule)(ref main2)).duration = 0.1f;
					((MainModule)(ref main2)).startLifetime = new MinMaxCurve(0.4f, 0.8f);
					((MainModule)(ref main2)).startSpeed = new MinMaxCurve(6f, 14f);
					((MainModule)(ref main2)).startSize = new MinMaxCurve(0.25f, 0.6f);
					((MainModule)(ref main2)).gravityModifier = MinMaxCurve.op_Implicit(0.3f);
					((MainModule)(ref main2)).maxParticles = 64;
					EmissionModule emission2 = _sparkPs.emission;
					((EmissionModule)(ref emission2)).enabled = true;
					((EmissionModule)(ref emission2)).rateOverTime = MinMaxCurve.op_Implicit(0f);
					((EmissionModule)(ref emission2)).SetBursts((Burst[])(object)new Burst[1]
					{
						new Burst(0f, (short)28)
					});
					ShapeModule shape2 = _sparkPs.shape;
					((ShapeModule)(ref shape2)).enabled = true;
					((ShapeModule)(ref shape2)).shapeType = (ParticleSystemShapeType)0;
					((ShapeModule)(ref shape2)).radius = 0.3f;
					SizeOverLifetimeModule sizeOverLifetime2 = _sparkPs.sizeOverLifetime;
					((SizeOverLifetimeModule)(ref sizeOverLifetime2)).enabled = true;
					((SizeOverLifetimeModule)(ref sizeOverLifetime2)).size = new MinMaxCurve(1f, new AnimationCurve((Keyframe[])(object)new Keyframe[2]
					{
						new Keyframe(0f, 1f),
						new Keyframe(1f, 0f)
					}));
					ColorOverLifetimeModule colorOverLifetime2 = _sparkPs.colorOverLifetime;
					((ColorOverLifetimeModule)(ref colorOverLifetime2)).enabled = true;
					ParticleSystemRenderer component2 = val.GetComponent<ParticleSystemRenderer>();
					((Renderer)component2).sharedMaterial = _sparkMat;
					component2.renderMode = (ParticleSystemRenderMode)1;
					component2.lengthScale = 3f;
					component2.velocityScale = 0.05f;
					((Renderer)component2).shadowCastingMode = (ShadowCastingMode)0;
					((Renderer)component2).receiveShadows = false;
				}
			}
		}

		private static void PlayFlash(Vector3 pos, Color skin)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: 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_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: 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_004d: Expected O, but got Unknown
			//IL_0056: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Expected O, but got Unknown
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			EnsureFlash();
			if (!((Object)(object)_flashGo == (Object)null))
			{
				float value = Plugin.KillZoneFlashSize.Value;
				MainModule main = _flashPs.main;
				((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(value);
				Color val = Color.Lerp(Color.white, skin, 0.6f);
				Gradient val2 = new Gradient();
				val2.SetKeys((GradientColorKey[])(object)new GradientColorKey[3]
				{
					new GradientColorKey(Color.white, 0f),
					new GradientColorKey(Color.white, 0.35f),
					new GradientColorKey(val, 1f)
				}, (GradientAlphaKey[])(object)new GradientAlphaKey[3]
				{
					new GradientAlphaKey(1f, 0f),
					new GradientAlphaKey(1f, 0.4f),
					new GradientAlphaKey(0f, 1f)
				});
				ColorOverLifetimeModule colorOverLifetime = _flashPs.colorOverLifetime;
				((ColorOverLifetimeModule)(ref colorOverLifetime)).color = new MinMaxGradient(val2);
				Gradient val3 = new Gradient();
				val3.SetKeys((GradientColorKey[])(object)new GradientColorKey[2]
				{
					new GradientColorKey(Color.white, 0f),
					new GradientColorKey(val, 1f)
				}, (GradientAlphaKey[])(object)new GradientAlphaKey[2]
				{
					new GradientAlphaKey(1f, 0f),
					new GradientAlphaKey(0f, 1f)
				});
				ColorOverLifetimeModule colorOverLifetime2 = _sparkPs.colorOverLifetime;
				((ColorOverLifetimeModule)(ref colorOverLifetime2)).color = new MinMaxGradient(val3);
				_flashGo.transform.position = pos;
				_flashPs.Play(true);
			}
		}

		private static Texture2D MakeStarTexture(int size)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(size, size, (TextureFormat)4, true)
			{
				wrapMode = (TextureWrapMode)1,
				filterMode = (FilterMode)1
			};
			Color[] array = (Color[])(object)new Color[size * size];
			float num = (float)size * 0.5f;
			for (int i = 0; i < size; i++)
			{
				for (int j = 0; j < size; j++)
				{
					float num2 = ((float)j + 0.5f - num) / num;
					float num3 = ((float)i + 0.5f - num) / num;
					float num4 = Mathf.Sqrt(num2 * num2 + num3 * num3);
					float num5 = Mathf.Atan2(num3, num2);
					float num6 = Mathf.Pow(Mathf.Abs(Mathf.Cos(2f * num5)), 12f);
					float num7 = Mathf.Pow(Mathf.Abs(Mathf.Cos(4f * num5)), 20f) * 0.45f;
					float num8 = Mathf.Clamp01((0.18f + 0.82f * Mathf.Max(num6, num7) - num4) / 0.06f);
					float num9 = Mathf.Exp((0f - num4) * num4 * 9f) * 0.8f;
					float num10 = Mathf.Clamp01(num8 + num9);
					array[i * size + j] = new Color(num10, num10, num10, num10);
				}
			}
			val.SetPixels(array);
			val.Apply(true);
			return val;
		}

		private static Texture2D MakeDotTexture(int size)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_003d: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(size, size, (TextureFormat)4, false)
			{
				wrapMode = (TextureWrapMode)1
			};
			Color[] array = (Color[])(object)new Color[size * size];
			float num = (float)size * 0.5f;
			for (int i = 0; i < size; i++)
			{
				for (int j = 0; j < size; j++)
				{
					float num2 = Vector2.Distance(new Vector2((float)j + 0.5f, (float)i + 0.5f), new Vector2(num, num)) / num;
					float num3 = Mathf.Clamp01(1f - num2 * num2);
					array[i * size + j] = new Color(num3, num3, num3, num3);
				}
			}
			val.SetPixels(array);
			val.Apply();
			return val;
		}

		internal static void DestroyAll()
		{
			CancelLinger();
			if ((Object)(object)_flashGo != (Object)null)
			{
				Object.Destroy((Object)(object)_flashGo);
			}
			if ((Object)(object)_flashMat != (Object)null)
			{
				Object.Destroy((Object)(object)_flashMat);
			}
			if ((Object)(object)_sparkMat != (Object)null)
			{
				Object.Destroy((Object)(object)_sparkMat);
			}
			if ((Object)(object)_starTex != (Object)null)
			{
				Object.Destroy((Object)(object)_starTex);
			}
			if ((Object)(object)_dotTex != (Object)null)
			{
				Object.Destroy((Object)(object)_dotTex);
			}
			_flashGo = null;
			_flashPs = null;
			_sparkPs = null;
			_flashMat = null;
			_sparkMat = null;
			_starTex = null;
			_dotTex = null;
			_armed = false;
		}
	}
	[HarmonyPatch(typeof(PlayerMovement), "LocalPlayerUpdateVisibility")]
	internal static class LocalPlayerUpdateVisibilityPatch
	{
		[HarmonyPriority(200)]
		private static bool Prefix(PlayerMovement __instance)
		{
			if (!KillZone.IsLingering)
			{
				return true;
			}
			PlayerInfo localPlayerInfo = GameManager.LocalPlayerInfo;
			if ((Object)(object)localPlayerInfo == (Object)null || __instance.PlayerInfo != localPlayerInfo)
			{
				return true;
			}
			try
			{
				if (__instance.IsVisible)
				{
					__instance.NetworkisVisible = false;
				}
			}
			catch
			{
			}
			return false;
		}
	}
	internal static class Launch
	{
		private static bool _active;

		private static bool _cloudHit;

		private static double _startedAt;

		internal static bool Active => _active;

		internal static bool IsCloudHit
		{
			get
			{
				if (_active)
				{
					return _cloudHit;
				}
				return false;
			}
		}

		internal static void Begin()
		{
			_active = true;
			_cloudHit = ShieldState.Percent >= Plugin.CloudHitMinPercent.Value;
			_startedAt = Time.timeAsDouble;
		}

		internal static void Cancel()
		{
			_active = false;
		}

		internal static void Tick(PlayerMovement mv, Rigidbody rb)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Invalid comparison between Unknown and I4
			if (_active)
			{
				double timeAsDouble = Time.timeAsDouble;
				if (mv.IsRespawningOrDrowning || KillZone.IsLingering || timeAsDouble - _startedAt > 12.0)
				{
					End("cancelled");
				}
				else if ((mv.IsGrounded || (int)mv.KnockoutState == 1) && timeAsDouble - _startedAt > 0.2)
				{
					End("landed");
				}
				else if (!mv.IsKnockedOutOrRecovering && timeAsDouble - _startedAt > 0.2)
				{
					End("recovered");
				}
			}
		}

		private static void End(string how)
		{
			_active = false;
			if (Plugin.VerboseLogging.Value)
			{
				Plugin.Log.LogInfo((object)$"Launch ended ({how}) after {Time.timeAsDouble - _startedAt:0.00}s.");
			}
		}
	}
	internal static class LaunchVfx
	{
		private class Trail
		{
			public GameObject Go;

			public ParticleSystem Ps;

			public ParticleSystemRenderer Renderer;

			public Material Material;

			public bool Emitting;

			public double StartedAt;
		}

		private static readonly Dictionary<PlayerInfo, Trail> _trails = new Dictionary<PlayerInfo, Trail>();

		private static readonly List<PlayerInfo> _scratch = new List<PlayerInfo>();

		private static readonly List<PlayerInfo> _dead = new List<PlayerInfo>();

		private static Texture2D _puffTex;

		private static Shader _shader;

		private static bool _shaderSearched;

		internal static Shader FindShader()
		{
			if (!_shaderSearched)
			{
				_shaderSearched = true;
				_shader = Shader.Find("Universal Render Pipeline/Particles/Unlit") ?? Shader.Find("Universal Render Pipeline/Unlit") ?? Shader.Find("Sprites/Default");
				if ((Object)(object)_shader != (Object)null)
				{
					Plugin.Log.LogInfo((object)("Trail shader: " + ((Object)_shader).name));
				}
				else
				{
					Plugin.Log.LogWarning((object)"No shader for the launch trail / kill flash.");
				}
			}
			return _shader;
		}

		internal static Material MakeUnlitMaterial(Texture2D tex, bool additive)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			Shader val = FindShader();
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Material val2 = new Material(val);
			if (val2.HasProperty("_Surface"))
			{
				val2.SetFloat("_Surface", 1f);
			}
			if (val2.HasProperty("_Blend"))
			{
				val2.SetFloat("_Blend", additive ? 2f : 0f);
			}
			if (val2.HasProperty("_SrcBlend"))
			{
				val2.SetInt("_SrcBlend", additive ? 1 : 5);
			}
			if (val2.HasProperty("_DstBlend"))
			{
				val2.SetInt("_DstBlend", additive ? 1 : 10);
			}
			if (val2.HasProperty("_ZWrite"))
			{
				val2.SetInt("_ZWrite", 0);
			}
			if (val2.HasProperty("_ColorMode"))
			{
				val2.SetFloat("_ColorMode", additive ? 1f : 0f);
			}
			val2.SetOverrideTag("RenderType", "Transparent");
			val2.EnableKeyword("_SURFACE_TYPE_TRANSPARENT");
			val2.DisableKeyword("_ALPHATEST_ON");
			val2.renderQueue = 3000;
			if (val2.HasProperty("_BaseMap"))
			{
				val2.SetTexture("_BaseMap", (Texture)(object)tex);
			}
			else
			{
				val2.mainTexture = (Texture)(object)tex;
			}
			if (val2.HasProperty("_BaseColor"))
			{
				val2.SetColor("_BaseColor", Color.white);
			}
			else
			{
				val2.color = Color.white;
			}
			return val2;
		}

		internal static void Tick()
		{
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.LaunchTrail.Value)
			{
				if (_trails.Count > 0)
				{
					StopAll();
				}
				return;
			}
			_scratch.Clear();
			PlayerInfo localPlayerInfo = GameManager.LocalPlayerInfo;
			if ((Object)(object)localPlayerInfo != (Object)null)
			{
				_scratch.Add(localPlayerInfo);
			}
			try
			{
				List<PlayerInfo> remotePlayers = GameManager.RemotePlayers;
				if (remotePlayers != null)
				{
					_scratch.AddRange(remotePlayers);
				}
			}
			catch
			{
			}
			_dead.Clear();
			foreach (KeyValuePair<PlayerInfo, Trail> trail in _trails)
			{
				if ((Object)(object)trail.Key == (Object)null || !_scratch.Contains(trail.Key))
				{
					_dead.Add(trail.Key);
				}
			}
			foreach (PlayerInfo item in _dead)
			{
				Destroy(_trails[item]);
				_trails.Remove(item);
			}
			double timeAsDouble = Time.timeAsDouble;
			foreach (PlayerInfo item2 in _scratch)
			{
				if ((Object)(object)item2 == (Object)null)
				{
					continue;
				}
				bool flag = false;
				float num = 0f;
				try
				{
					PlayerMovement movement = item2.Movement;
					flag = (Object)(object)movement != (Object)null && movement.IsKnockedOutOrRecovering && !movement.IsGrounded;
					float num2;
					if (!((Object)(object)movement != (Object)null))
					{
						num2 = 0f;
					}
					else
					{
						Vector3 velocity = movement.Velocity;
						num2 = ((Vector3)(ref velocity)).magnitude;
					}
					num = num2;
				}
				catch
				{
				}
				bool flag2 = item2 != localPlayerInfo || ShieldState.Percent >= Plugin.LaunchTrailMinPercent.Value || KillZone.IsArmed;
				_trails.TryGetValue(item2, out var value);
				if (value == null || !value.Emitting)
				{
					if (!(flag && flag2) || !(num >= Plugin.LaunchTrailStartSpeed.Value))
					{
						continue;
					}
					if (value == null)
					{
						value = Create(item2);
						if (value == null)
						{
							continue;
						}
						_trails[item2] = value;
					}
					Start(value, item2);
					value.StartedAt = timeAsDouble;
				}
				else
				{
					Transform val = (((Object)(object)item2.ChestBone != (Object)null) ? item2.ChestBone : ((Component)item2).transform);
					value.Go.transform.position = val.position;
					if ((!flag || !(num >= Plugin.LaunchTrailStopSpeed.Value)) && timeAsDouble - value.StartedAt > 0.15)
					{
						Stop(value);
					}
				}
			}
		}

		private static Trail Create(PlayerInfo p)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_0056: 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_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: 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)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: 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_014f: Expected O, but got Unknown
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)_puffTex == (Object)null)
				{
					_puffTex = MakePuffTexture(64);
				}
				if ((Object)(object)FindShader() == (Object)null)
				{
					return null;
				}
				GameObject val = new GameObject("SbgLaunchTrail");
				val.transform.SetParent((Transform)null, false);
				ParticleSystem val2 = val.AddComponent<ParticleSystem>();
				val2.Stop(true, (ParticleSystemStopBehavior)0);
				MainModule main = val2.main;
				((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)1;
				((MainModule)(ref main)).loop = true;
				((MainModule)(ref main)).playOnAwake = false;
				((MainModule)(ref main)).startSpeed = new MinMaxCurve(0.3f, 0.9f);
				((MainModule)(ref main)).startRotation = new MinMaxCurve(0f, MathF.PI * 2f);
				((MainModule)(ref main)).gravityModifier = MinMaxCurve.op_Implicit(-0.03f);
				((MainModule)(ref main)).maxParticles = 800;
				EmissionModule emission = val2.emission;
				((EmissionModule)(ref emission)).enabled = true;
				ShapeModule shape = val2.shape;
				((ShapeModule)(ref shape)).enabled = true;
				((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)0;
				((ShapeModule)(ref shape)).radius = 0.45f;
				SizeOverLifetimeModule sizeOverLifetime = val2.sizeOverLifetime;
				((SizeOverLifetimeModule)(ref sizeOverLifetime)).enabled = true;
				AnimationCurve val3 = new AnimationCurve((Keyframe[])(object)new Keyframe[3]
				{
					new Keyframe(0f, 0.45f),
					new Keyframe(0.25f, 0.9f),
					new Keyframe(1f, 1.25f)
				});
				((SizeOverLifetimeModule)(ref sizeOverLifetime)).size = new MinMaxCurve(1f, val3);
				ColorOverLifetimeModule colorOverLifetime = val2.colorOverLifetime;
				((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled = true;
				RotationOverLifetimeModule rotationOverLifetime = val2.rotationOverLifetime;
				((RotationOverLifetimeModule)(ref rotationOverLifetime)).enabled = true;
				((RotationOverLifetimeModule)(ref rotationOverLifetime)).z = new MinMaxCurve(-0.4f, 0.4f);
				ParticleSystemRenderer component = val.GetComponent<ParticleSystemRenderer>();
				Material val4 = MakeUnlitMaterial(_puffTex, additive: false);
				if ((Object)(object)val4 == (Object)null)
				{
					Object.Destroy((Object)(object)val);
					return null;
				}
				((Renderer)component).sharedMaterial = val4;
				component.renderMode = (ParticleSystemRenderMode)0;
				component.sortMode = (ParticleSystemSortMode)1;
				((Renderer)component).shadowCastingMode = (ShadowCastingMode)0;
				((Renderer)component).receiveShadows = false;
				return new Trail
				{
					Go = val,
					Ps = val2,
					Renderer = component,
					Material = val4
				};
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Launch trail create failed: " + ex.Message));
				return null;
			}
		}

		private static void Start(Trail t, PlayerInfo p)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: 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)
			//IL_00c3: 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_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Expected O, but got Unknown
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: 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_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			Color val = Skin.Of(p);
			Color val2 = Color.Lerp(val, Color.white, 0.5f);
			float num = Mathf.Clamp01(Plugin.LaunchTrailAlpha.Value);
			MainModule main = t.Ps.main;
			float value = Plugin.LaunchTrailLifetime.Value;
			((MainModule)(ref main)).startLifetime = new MinMaxCurve(value * 0.75f, value);
			((MainModule)(ref main)).startSize = new MinMaxCurve(Plugin.LaunchTrailSize.Value * 0.7f, Plugin.LaunchTrailSize.Value);
			((MainModule)(ref main)).startColor = new MinMaxGradient(new Color(val2.r, val2.g, val2.b, num), new Color(val.r, val.g, val.b, num));
			EmissionModule emission = t.Ps.emission;
			((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(Plugin.LaunchTrailRate.Value);
			((EmissionModule)(ref emission)).rateOverDistance = MinMaxCurve.op_Implicit(Plugin.LaunchTrailRatePerMetre.Value);
			Gradient val3 = new Gradient();
			val3.SetKeys((GradientColorKey[])(object)new GradientColorKey[3]
			{
				new GradientColorKey(val2, 0f),
				new GradientColorKey(val, 0.45f),
				new GradientColorKey(val * 0.85f, 1f)
			}, (GradientAlphaKey[])(object)new GradientAlphaKey[4]
			{
				new GradientAlphaKey(1f, 0f),
				new GradientAlphaKey(0.9f, 0.55f),
				new GradientAlphaKey(0.35f, 0.85f),
				new GradientAlphaKey(0f, 1f)
			});
			ColorOverLifetimeModule colorOverLifetime = t.Ps.colorOverLifetime;
			((ColorOverLifetimeModule)(ref colorOverLifetime)).color = new MinMaxGradient(val3);
			Transform val4 = (((Object)(object)p.ChestBone != (Object)null) ? p.ChestBone : ((Component)p).transform);
			t.Go.transform.position = val4.position;
			t.Go.SetActive(true);
			t.Ps.Play(true);
			t.Emitting = true;
		}

		private static void Stop(Trail t)
		{
			if (t == null || !t.Emitting)
			{
				return;
			}
			t.Emitting = false;
			try
			{
				t.Ps.Stop(true, (ParticleSystemStopBehavior)1);
			}
			catch
			{
			}
		}

		private static void Destroy(Trail t)
		{
			if (t != null)
			{
				if ((Object)(object)t.Material != (Object)null)
				{
					Object.Destroy((Object)(object)t.Material);
				}
				if ((Object)(object)t.Go != (Object)null)
				{
					Object.Destroy((Object)(object)t.Go);
				}
			}
		}

		internal static void StopAll()
		{
			foreach (KeyValuePair<PlayerInfo, Trail> trail in _trails)
			{
				Destroy(trail.Value);
			}
			_trails.Clear();
		}

		internal static void DestroyAll()
		{
			StopAll();
			if ((Object)(object)_puffTex != (Object)null)
			{
				Object.Destroy((Object)(object)_puffTex);
				_puffTex = null;
			}
			_shader = null;
			_shaderSearched = false;
		}

		private static Texture2D MakePuffTexture(int size)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(size, size, (TextureFormat)4, true)
			{
				wrapMode = (TextureWrapMode)1,
				filterMode = (FilterMode)1
			};
			Color[] array = (Color[])(object)new Color[size * size];
			float num = (float)size * 0.5f;
			for (int i = 0; i < size; i++)
			{
				for (int j = 0; j < size; j++)
				{
					float num2 = ((float)j + 0.5f - num) / num;
					float num3 = ((float)i + 0.5f - num) / num;
					float num4 = Mathf.Sqrt(num2 * num2 + num3 * num3);
					float num5 = Mathf.Atan2(num3, num2);
					float num6 = 0.1f * Mathf.Sin(num5 * 5f) + 0.07f * Mathf.Sin(num5 * 3f + 1.3f) + 0.04f * Mathf.Sin(num5 * 8f + 0.4f);
					float num7 = 0.9f + num6;
					float num8 = Mathf.Clamp01((num7 - num4) / (num7 * 0.55f));
					num8 = num8 * num8 * (3f - 2f * num8);
					array[i * size + j] = new Color(1f, 1f, 1f, num8);
				}
			}
			val.SetPixels(array);
			val.Apply(true);
			return val;
		}
	}
	internal static class ModHandshake
	{
		private class Peer
		{
			public string Version;

			public double FirstSeen;

			public bool Announced;

			public bool Warned;
		}

		internal const string Token = "SBGSHIELDS";

		private static readonly Dictionary<ulong, Peer> _peers = new Dictionary<ulong, Peer>();

		private static readonly List<PlayerInfo> _scratch = new List<PlayerInfo>();

		private static readonly HashSet<ulong> _present = new HashSet<ulong>();

		private static readonly List<ulong> _gone = new List<ulong>();

		private static readonly List<ulong> _forget = new List<ulong>();

		private const double MinAnnounceInterval = 3.0;

		private static double _lastAnnounce = double.MinValue;

		private static double _nextAnnounceDue = double.MaxValue;

		private static bool _announcePending = true;

		private static bool _gateOpen;

		private static bool _evaluatedOnce;

		private static string _blockReason;

		internal static bool GameplayEnabled => _gateOpen;

		internal static string BlockReason => _blockReason;

		internal static double BlockedSince { get; private set; } = double.MinValue;

		internal static void Reset(string why)
		{
			_forget.Clear();
			foreach (KeyValuePair<ulong, Peer> peer in _peers)
			{
				if (!peer.Value.Announced)
				{
					_forget.Add(peer.Key);
				}
			}
			foreach (ulong item in _forget)
			{
				_peers.Remove(item);
			}
			_gateOpen = false;
			_evaluatedOnce = false;
			_blockReason = null;
			_announcePending = true;
			_nextAnnounceDue = Time.timeAsDouble + 1.5;
			if (Plugin.VerboseLogging.Value)
			{
				Plugin.Log.LogInfo((object)("Handshake reset (" + why + ")."));
			}
		}

		private static bool Announce()
		{
			double timeAsDouble = Time.timeAsDouble;
			if (timeAsDouble - _lastAnnounce < 3.0)
			{
				return false;
			}
			string text = "SBGSHIELDS/0.7.7";
			if (!ChatBypass.Send(text))
			{
				return false;
			}
			_lastAnnounce = timeAsDouble;
			if (Plugin.VerboseLogging.Value)
			{
				Plugin.Log.LogInfo((object)("Handshake announced: " + text));
			}
			return true;
		}

		internal static bool TryConsume(string message, PlayerInfo sender)
		{
			if (message == null || (Object)(object)sender == (Object)null)
			{
				return false;
			}
			if (!message.StartsWith("SBGSHIELDS/", StringComparison.Ordinal))
			{
				return false;
			}
			string text = message.Substring("SBGSHIELDS".Length + 1).Trim();
			if (sender == GameManager.LocalPlayerInfo)
			{
				return true;
			}
			ulong num = GuidOf(sender);
			if (num == 0L)
			{
				return true;
			}
			Peer value;
			bool num2 = !_peers.TryGetValue(num, out value) || !value.Announced;
			if (value == null)
			{
				value = new Peer
				{
					FirstSeen = Time.timeAsDouble
				};
				_peers[num] = value;
			}
			value.Version = text;
			value.Announced = true;
			Plugin.Log.LogInfo((object)(NameOf(sender) + " is running SBG Shields " + text + "."));
			if (num2)
			{
				_announcePending = true;
				_nextAnnounceDue = Time.timeAsDouble + (double)Random.Range(0.3f, 1.2f);
			}
			Evaluate();
			return true;
		}

		internal static void Tick()
		{
			if (!LobbyAllowed(out var why))
			{
				_announcePending = false;
				SetGate(open: false, why);
				return;
			}
			if (!Plugin.RequireAllPlayersModded.Value)
			{
				SetGate(open: true, null);
				return;
			}
			double timeAsDouble = Time.timeAsDouble;
			if (_announcePending && timeAsDouble >= _nextAnnounceDue)
			{
				if (Announce())
				{
					_announcePending = false;
				}
				else
				{
					_nextAnnounceDue = timeAsDouble + 1.0;
				}
			}
			_scratch.Clear();
			try
			{
				List<PlayerInfo> remotePlayers = GameManager.RemotePlayers;
				if (remotePlayers != null)
				{
					_scratch.AddRange(remotePlayers);
				}
			}
			catch
			{
			}
			foreach (PlayerInfo item in _scratch)
			{
				ulong num = GuidOf(item);
				if (num != 0L && !_peers.TryGetValue(num, out var _))
				{
					_peers[num] = new Peer
					{
						FirstSeen = timeAsDouble
					};
					_announcePending = true;
					_nextAnnounceDue = timeAsDouble + (double)Random.Range(0.3f, 1.2f);
					if (Plugin.VerboseLogging.Value)
					{
						Plugin.Log.LogInfo((object)$"Handshake: new player {num}, will announce.");
					}
				}
			}
			_present.Clear();
			foreach (PlayerInfo item2 in _scratch)
			{
				ulong num2 = GuidOf(item2);
				if (num2 != 0L)
				{
					_present.Add(num2);
				}
			}
			_gone.Clear();
			foreach (KeyValuePair<ulong, Peer> peer in _peers)
			{
				if (!_present.Contains(peer.Key))
				{
					_gone.Add(peer.Key);
				}
			}
			foreach (ulong item3 in _gone)
			{
				_peers.Remove(item3);
				if (Plugin.VerboseLogging.Value)
				{
					Plugin.Log.LogInfo((object)$"Handshake: forgetting departed player {item3}.");
				}
			}
			Evaluate();
		}

		internal static LobbyMode CurrentLobbyMode()
		{
			//IL_0029: 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_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (SingletonNetworkBehaviour<MatchSetupMenu>.HasInstance)
				{
					MatchSetupMenu instance = SingletonNetworkBehaviour<MatchSetupMenu>.Instance;
					if ((Object)(object)instance != (Object)null)
					{
						return instance.lobbyMode;
					}
				}
				return BNetworkManager.LobbyMode;
			}
			catch
			{
				return (LobbyMode)0;
			}
		}

		private static bool LobbyAllowed(out string why)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			why = null;
			if ((int)CurrentLobbyMode() != 0)
			{
				return true;
			}
			why = "this is a public lobby";
			return false;
		}

		private static void Evaluate()
		{
			double timeAsDouble = Time.timeAsDouble;
			float num = Mathf.Max(2f, Plugin.HandshakeTimeout.Value);
			_scratch.Clear();
			try
			{
				List<PlayerInfo> remotePlayers = GameManager.RemotePlayers;
				if (remotePlayers != null)
				{
					_scratch.AddRange(remotePlayers);
				}
			}
			catch
			{
			}
			if (!LobbyAllowed(out var why))
			{
				SetGate(open: false, why);
				return;
			}
			foreach (PlayerInfo item in _scratch)
			{
				ulong num2 = GuidOf(item);
				if (num2 == 0L || !_peers.TryGetValue(num2, out var value))
				{
					continue;
				}
				if (value.Announced)
				{
					if (value.Version != "0.7.7")
					{
						why = NameOf(item) + " is on SBG Shields " + value.Version + ", you are on 0.7.7";
						if (!value.Warned)
						{
							value.Warned = true;
							Plugin.Log.LogWarning((object)("Version mismatch: " + why));
						}
						break;
					}
				}
				else if (timeAsDouble - value.FirstSeen > (double)num)
				{
					why = NameOf(item) + " does not have SBG Shields installed";
					if (!value.Warned)
					{
						value.Warned = true;
						Plugin.Log.LogWarning((object)(why + "; the mod is standing down."));
					}
					break;
				}
			}
			SetGate(why == null, why);
		}

		private static void SetGate(bool open, string problem)
		{
			if (open != _gateOpen || !_evaluatedOnce)
			{
				_gateOpen = open;
				if (!open)
				{
					BlockedSince = Time.timeAsDouble;
				}
				Plugin.Log.LogWarning((object)(open ? "SBG Shields is active." : ("SBG Shields is inactive: " + problem + ". Vanilla rules apply.")));
				if (!open)
				{
					Plugin.ForceReleaseForHandshake();
				}
			}
			_evaluatedOnce = true;
			_blockReason = problem;
		}

		private static ulong GuidOf(PlayerInfo p)
		{
			try
			{
				return ((Object)(object)p != (Object)null && (Object)(object)p.PlayerId != (Object)null) ? p.PlayerId.Guid : 0;
			}
			catch
			{
				return 0uL;
			}
		}

		private static string NameOf(PlayerInfo p)
		{
			try
			{
				return p.PlayerId.PlayerNameNoRichText;
			}
			catch
			{
				return "A player";
			}
		}
	}
	internal static class ChatBypass
	{
		private static MethodInfo _cmd;

		private static bool _looked;

		internal static bool Send(string message)
		{
			try
			{
				if (!SingletonNetworkBehaviour<TextChatManager>.HasInstance)
				{
					return false;
				}
				TextChatManager instance = SingletonNetworkBehaviour<TextChatManager>.Instance;
				if ((Object)(object)instance == (Object)null)
				{
					return false;
				}
				if (!_looked)
				{
					_looked = true;
					_cmd = AccessTools.Method(typeof(TextChatManager), "CmdSendMessageInternal", new Type[2]
					{
						typeof(string),
						typeof(NetworkConnectionToClient)
					}, (Type[])null);
					if (_cmd == null)
					{
						Plugin.Log.LogWarning((object)"Chat command not found; falling back to the normal send path.");
					}
				}
				if (_cmd != null)
				{
					_cmd.Invoke(instance, new object[2] { message, null });
					return true;
				}
				TextChatManager.SendChatMessage(message);
				return true;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Handshake send failed: " + ex.Message));
				return false;
			}
		}
	}
	[HarmonyPatch(typeof(TextChatManager), "UserCode_RpcMessage__String__PlayerInfo")]
	internal static class ChatHandshakePatch
	{
		[HarmonyPriority(200)]
		private static bool Prefix(string message, PlayerInfo sender)
		{
			try
			{
				return !ModHandshake.TryConsume(message, sender);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Handshake receive failed: " + ex.Message));
				return true;
			}
		}
	}
	internal static class Local
	{
		internal static bool Is(PlayerInfo p)
		{
			if ((Object)(object)p != (Object)null)
			{
				return p == GameManager.LocalPlayerInfo;
			}
			return false;
		}

		internal static bool IsRooted(PlayerInfo p)
		{
			if (Is(p) && p.IsElectromagnetShieldActive)
			{
				return Plugin.WeActivated;
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(PlayerMovement), "CanMove")]
	internal static class RootMovementPatch
	{
		private static void Postfix(PlayerMovement __instance, ref bool __result)
		{
			if (__result && Plugin.RootWhileShielded.Value && Local.IsRooted(__instance.PlayerInfo))
			{
				__result = false;
			}
		}
	}
	[HarmonyPatch(typeof(PlayerMovement), "CanJump")]
	internal static class RootJumpPatch
	{
		private static void Postfix(PlayerMovement __instance, ref bool __result)
		{
			if (__result && Plugin.BlockJumpWhileShielded.Value && Local.IsRooted(__instance.PlayerInfo))
			{
				__result = false;
			}
		}
	}
	[HarmonyPatch(typeof(PlayerMovement), "TryDive")]
	internal static class RootDivePatch
	{
		[HarmonyPriority(200)]
		private static bool Prefix(PlayerMovement __instance, ref bool __result)
		{
			if (Plugin.BlockDiveWhileShielded.Value && Local.IsRooted(__instance.PlayerInfo))
			{
				__result = false;
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(PlayerGolfer), "TryStartChargingSwing")]
	internal static class RootSwingPatch
	{
		[HarmonyPriority(200)]
		private static bool Prefix(PlayerGolfer __instance, ref bool __result)
		{
			if (Plugin.BlockSwingWhileShielded.Value && Local.IsRooted(__instance.PlayerInfo))
			{
				__result = false;
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(PlayerMovement), "TryKnockOut")]
	internal static class KnockoutEconomyPatch
	{
		[HarmonyPriority(200)]
		private static bool Prefix(PlayerMovement __instance, KnockoutType knockoutType, Vector3 localOrigin, float distance, Vector3 incomingVelocityChange, ref bool __result, ref bool isNewKnockout, ref bool blockedByTeamProtection, out bool __state)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			__state = false;
			if (!Local.Is(__instance.PlayerInfo))
			{
				return true;
			}
			__state = true;
			ShieldState.PendingHitDistance = distance;
			ShieldState.PendingHitLocalOrigin = localOrigin;
			if (!ShieldState.ResolveKnockout(__instance.PlayerInfo, knockoutType, incomingVelocityChange))
			{
				__result = false;
				isNewKnockout = false;
				blockedByTeamProtection = false;
				return false;
			}
			return true;
		}

		private static void Postfix(bool __result, bool __state)
		{
			if (__state)
			{
				ShieldState.OnKnockoutResolved(__result);
			}
		}
	}
	[HarmonyPatch(typeof(PlayerMovement), "OnLocalPlayerWillApplySwingProjectileHitPhysics")]
	internal static class ProjectileTargetingPatch
	{
		private static void Prefix(PlayerMovement __instance, Hittable hitter)
		{
			if (!Local.Is(__instance.PlayerInfo))
			{
				return;
			}
			try
			{
				Hittable val = (((Object)(object)hitter != (Object)null) ? hitter.NetworkhomingTargetHittable : null);
				ShieldState.PendingProjectileWasTargeted = (Object)(object)val != (Object)null && val == __instance.PlayerInfo.AsHittable;
			}
			catch
			{
				ShieldState.PendingProjectileWasTargeted = false;
			}
		}
	}
	[HarmonyPatch(typeof(PlayerMovement), "SetKnockOutState")]
	internal static class HitstunPatch
	{
		private static FieldRef<PlayerMovement, float> _timeUntilRecovery;

		private static bool _loggedTimeouts;

		private static bool Prepare()
		{
			try
			{
				_timeUntilRecovery = AccessTools.FieldRefAccess<PlayerMovement, float>("timeUntilKnockoutRecovery");
				return true;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("timeUntilKnockoutRecovery not found; hitstun scaling disabled. " + ex.Message));
				return false;
			}
		}

		private static void Prefix(PlayerMovement __instance, out bool __state)
		{
			__state = __instance.IsKnockedOutOrRecovering;
		}

		private static void Postfix(PlayerMovement __instance, KnockoutState state, bool __state)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			if ((int)state != 2 || !Local.Is(__instance.PlayerInfo) || __state || !__instance.IsKnockedOutOrRecovering)
			{
				return;
			}
			ref float reference = ref _timeUntilRecovery.Invoke(__instance);
			float num = reference;
			if (!_loggedTimeouts)
			{
				_loggedTimeouts = true;
				try
				{
					PlayerMovementSettings playerMovementSettings = GameManager.PlayerMovementSettings;
					Plugin.Log.LogInfo((object)$"Game knockout constants: KnockoutDuration={playerMovementSettings.KnockoutDuration:0.00}s, KnockoutTimeOutDuration={playerMovementSettings.KnockoutTimeOutDuration:0.00}s, LongImmunity={playerMovementSettings.PostKnockoutImmunityLongDuration:0.00}s");
				}
				catch
				{
				}
			}
			if (ShieldState.PendingHitstunAbsolute >= 0f)
			{
				reference = ShieldState.PendingHitstunAbsolute;
				ShieldState.BreakStunUntil = Time.timeAsDouble + (double)reference;
				ShieldState.LastKnockoutWasBreakStun = true;
				BreakTrace.Log($"stun applied: timer={reference:0.00}s, hold until +{reference:0.00}s");
			}
			else
			{
				ShieldState.BreakStunUntil = double.MinValue;
				ShieldState.LastKnockoutWasBreakStun = false;
				if (ShieldState.PendingHitstunMultiplier >= 0f)
				{
					reference *= ShieldState.PendingHitstunMultiplier;
				}
				else
				{
					reference *= ShieldState.HitstunMultiplier;
				}
			}
			ShieldState.PendingHitstunAbsolute = -1f;
			ShieldState.PendingHitstunMultiplier = -1f;
			if (Plugin.VerboseLogging.Value && Mathf.Abs(num - reference) > 0.01f)
			{
				Plugin.Log.LogInfo((object)$"Hitstun {num:0.00}s -> {reference:0.00}s");
			}
		}
	}
	internal static class BreakTrace
	{
		private static double _start = double.MinValue;

		private static double _until = double.MinValue;

		internal static bool Active => Time.timeAsDouble < _until;

		internal static void Begin(float seconds)
		{
			_start = Time.timeAsDouble;
			_until = _start + (double)seconds + 1.5;
		}

		internal static void Log(string what)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			if (Active)
			{
				PlayerMovement val = (((Object)(object)GameManager.LocalPlayerInfo != (Object)null) ? GameManager.LocalPlayerInfo.Movement : null);
				string text = (((Object)(object)val != (Object)null) ? ((object)val.KnockoutState/*cast due to .constrained prefix*/).ToString() : "?");
				double num = ShieldState.BreakStunUntil - Time.timeAsDouble;
				string text2 = ((ShieldState.BreakStunUntil == double.MinValue) ? "none" : num.ToString("0.00"));
				Plugin.Log.LogInfo((object)$"[break +{Time.timeAsDouble - _start:0.00}s] {what} | state={text} holdLeft={text2}");
			}
		}
	}
	[HarmonyPatch(typeof(PlayerMovement), "SetKnockOutState")]
	internal static class KnockoutStateTracePatch
	{
		private static void Prefix(PlayerMovement __instance, KnockoutState state)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			if (BreakTrace.Active && Local.Is(__instance.PlayerInfo) && state != __instance.KnockoutState)
			{
				BreakTrace.Log($"SetKnockOutState {__instance.KnockoutState} -> {state}");
			}
		}
	}
	[HarmonyPatch(typeof(PlayerMovement), "StartKnockoutImmunity")]
	internal static class ImmunityTracePatch
	{
		private static void Prefix(PlayerMovement __instance, bool fromPlayerAggression)
		{
			if (BreakTrace.Active && Local.Is(__instance.PlayerInfo))
			{
				BreakTrace.Log($"StartKnockoutImmunity(fromPlayerAggression={fromPlayerAggression})");
			}
		}
	}
	[HarmonyPatch(typeof(PlayerMovement), "CanBeKnockedOutBy")]
	internal static class CanBeKnockedOutTracePatch
	{
		private static void Postfix(PlayerMovement __instance, bool __result, bool suppressKnockoutImmunity, bool blockedByTeamProtection)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			if (BreakTrace.Active && Local.Is(__instance.PlayerInfo))
			{
				BreakTrace.Log($"CanBeKnockedOutBy -> {__result} (immunitySuppressed={suppressKnockoutImmunity}, team={blockedByTeamProtection}, hasImmunity={__instance.KnockoutImmunityStatus.hasImmunity}, shieldActive={__instance.PlayerInfo.IsElectromagnetShieldActive})");
			}
		}
	}
	[HarmonyPatch(typeof(PlayerMovement), "RecoverFromKnockout")]
	internal static class BreakStunHoldPatch
	{
		private static double _lastLog = double.MinValue;

		[HarmonyPriority(200)]
		private static bool Prefix(PlayerMovement __instance)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Invalid comparison between Unknown and I4
			if (!Local.Is(__instance.PlayerInfo))
			{
				return true;
			}
			double timeAsDouble = Time.timeAsDouble;
			if (timeAsDouble >= ShieldState.BreakStunUntil)
			{
				BreakTrace.Log("RecoverFromKnockout allowed (hold expired)");
				return true;
			}
			if (!__instance.IsKnockedOut)
			{
				BreakTrace.Log("RecoverFromKnockout allowed (not knocked out)");
				return true;
			}
			try
			{
				if ((int)__instance.PlayerInfo.AsHittable.FrozenState == 2)
				{
					return true;
				}
			}
			catch
			{
			}
			if (__instance.IsRespawningOrDrowning)
			{
				return true;
			}
			if (timeAsDouble - _lastLog > 0.5)
			{
				_lastLog = timeAsDouble;
				BreakTrace.Log("RecoverFromKnockout BLOCKED by hold");
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(PlayerMovement), "StartKnockoutImmunity")]
	internal static class BreakImmunityPatch
	{
		private static FieldRef<PlayerMovement, Coroutine> _routine;

		private static FieldRef<PlayerMovement, List<double>> _recent;

		private static bool Prepare()
		{
			try
			{
				_routine = AccessTools.FieldRefAccess<PlayerMovement, Coroutine>("knockoutImmunityRoutine");
				_recent = AccessTools.FieldRefAccess<PlayerMovement, List<double>>("recentKnockoutImmunityTimestamps");
				return true;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Knockout immunity fields not found; break immunity stays vanilla. " + ex.Message));
				return false;
			}
		}

		[HarmonyPriority(200)]
		private static bool Prefix(PlayerMovement __instance, bool fromPlayerAggression)
		{
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			if (!fromPlayerAggression || !Local.Is(__instance.PlayerInfo))
			{
				return true;
			}
			if (!Plugin.BreakImmunityScalesWithPercent.Value)
			{
				return true;
			}
			if (!ShieldState.ConsumeBreakStunImmunity())
			{
				return true;
			}
			float breakImmunityDuration = ShieldState.BreakImmunityDuration;
			if (Plugin.VerboseLogging.Value)
			{
				Plugin.Log.LogInfo((object)$"Break immunity: {breakImmunityDuration:0.00}s at {ShieldState.Percent:0}%.");
			}
			try
			{
				_recent.Invoke(__instance)?.Add(Time.timeAsDouble);
				ref Coroutine reference = ref _routine.Invoke(__instance);
				if (reference != null)
				{
					((MonoBehaviour)__instance).StopCoroutine(reference);
				}
				if (breakImmunityDuration <= 0.05f)
				{
					reference = null;
					__instance.NetworkknockoutImmunityStatus = KnockOutImmunity.Reset(__instance.KnockoutImmunityStatus);
					return false;
				}
				reference = ((MonoBehaviour)__instance).StartCoroutine(Immunity(__instance, breakImmunityDuration));
				return false;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Break immunity failed, falling back to vanilla: " + ex.Message));
				return true;
			}
		}

		private static IEnumerator Immunity(PlayerMovement m, float duration)
		{
			m.NetworkknockoutImmunityStatus = KnockOutImmunity.Get((KnockOutVfxColor)0);
			while ((Object)(object)m != (Object)null && ((int)m.KnockoutState == 3 || (!m.IsKnockedOutOrRecovering && Time.timeAsDouble - m.IsKnockedOutTimestamp < (double)duration)))
			{
				yield return null;
			}
			if ((Object)(object)m != (Object)null)
			{
				m.NetworkknockoutImmunityStatus = KnockOutImmunity.Reset(m.KnockoutImmunityStatus);
			}
		}
	}
	[HarmonyPatch(typeof(PlayerMovement), "FixedUpdate")]
	internal static class VelocityCorrectionPatch
	{
		private static FieldRef<PlayerMovement, Rigidbody> _rigidbody;

		private static bool Prepare()
		{
			try
			{
				_rigidbody = AccessTools.FieldRefAccess<PlayerMovement, Rigidbody>("rigidbody");
				return true;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("rigidbody field not found; knockback scaling disabled. " + ex.Message));
				return false;
			}
		}

		private static void Prefix(PlayerMovement __instance)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be