Decompiled source of SpectatePlus v1.0.1

SpectatePlus.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using InControl;
using Photon.Pun;
using Photon.Realtime;
using TMPro;
using UnboundLib;
using UnboundLib.Extensions;
using UnboundLib.Utils.UI;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = "")]
[assembly: AssemblyVersion("0.0.0.0")]
namespace SpectatePlus;

internal static class MapsExtBridge
{
	internal const string MapsExtendedGuid = "io.olavim.rounds.mapsextended";

	private const float UnitRatio = 1f / 27f;

	private static MethodInfo s_getCurrentCustomMap;

	private static PropertyInfo s_settingsProp;

	private static PropertyInfo s_mapSizeProp;

	private static PropertyInfo s_viewportHeightProp;

	internal static bool TryPatch(Harmony harmony)
	{
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Expected O, but got Unknown
		Type type = AccessTools.TypeByName("MapsExt.CameraHandler");
		Type type2 = AccessTools.TypeByName("MapsExt.MapManagerExtensions");
		if (type == null || type2 == null)
		{
			return false;
		}
		s_getCurrentCustomMap = AccessTools.Method(type2, "GetCurrentCustomMap", (Type[])null, (Type[])null);
		MethodInfo methodInfo = AccessTools.Method(type, "UpdateTargets", (Type[])null, (Type[])null);
		if (s_getCurrentCustomMap == null || methodInfo == null)
		{
			return false;
		}
		harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(MapsExtBridge), "UpdateTargetsPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		SpectatePlus.Log.LogInfo((object)"Patched MapsExtended CameraHandler.UpdateTargets");
		return true;
	}

	private static void UpdateTargetsPostfix(ref Vector2 ____targetPosition, ref float ____targetSize, bool ____isPickPhase, bool ____playersHaveSpawned)
	{
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		SpectateController instance = SpectateController.Instance;
		if (!((Object)(object)instance == (Object)null))
		{
			if (!SpectatePlus.Enabled.Value || ____isPickPhase || !____playersHaveSpawned || !TryGetMapInfo(out var mapSizeWorld, out var viewportHeightWorld))
			{
				instance.Deactivate();
			}
			else
			{
				instance.Apply(ref ____targetPosition, ref ____targetSize, mapSizeWorld, viewportHeightWorld);
			}
		}
	}

	internal static bool TryGetMapInfo(out Vector2 mapSizeWorld, out float viewportHeightWorld)
	{
		//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_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_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0102: Unknown result type (might be due to invalid IL or missing references)
		//IL_0107: Unknown result type (might be due to invalid IL or missing references)
		mapSizeWorld = Vector2.zero;
		viewportHeightWorld = 0f;
		try
		{
			if ((Object)(object)MapManager.instance == (Object)null || MapManager.instance.currentMap == null)
			{
				return false;
			}
			object obj = s_getCurrentCustomMap?.Invoke(null, new object[1] { MapManager.instance });
			if (obj == null)
			{
				return false;
			}
			if (s_settingsProp == null)
			{
				s_settingsProp = AccessTools.Property(obj.GetType(), "Settings");
			}
			object obj2 = s_settingsProp?.GetValue(obj, null);
			if (obj2 == null)
			{
				return false;
			}
			if (s_mapSizeProp == null)
			{
				s_mapSizeProp = AccessTools.Property(obj2.GetType(), "MapSize");
				s_viewportHeightProp = AccessTools.Property(obj2.GetType(), "ViewportHeight");
			}
			Vector2 val = (Vector2)s_mapSizeProp.GetValue(obj2, null);
			float num = Convert.ToSingle(s_viewportHeightProp.GetValue(obj2, null));
			mapSizeWorld = val * (1f / 27f);
			viewportHeightWorld = num * (1f / 27f);
			return mapSizeWorld.x > 0f && mapSizeWorld.y > 0f && viewportHeightWorld > 0f;
		}
		catch (Exception arg)
		{
			SpectatePlus.Log.LogError((object)$"Failed to read map settings: {arg}");
			return false;
		}
	}
}
internal static class PlayerUtil
{
	private static readonly Dictionary<int, bool> s_botCache = new Dictionary<int, bool>();

	private static bool s_rwbLookedUp;

	private static MethodInfo s_rwbGetData;

	private static PropertyInfo s_rwbIsBot;

	internal static bool IsMine(Player p)
	{
		if ((Object)(object)p != (Object)null && (Object)(object)p.data != (Object)null && (Object)(object)p.data.view != (Object)null)
		{
			return p.data.view.IsMine;
		}
		return false;
	}

	internal static bool IsAlive(Player p)
	{
		if ((Object)(object)p != (Object)null && (Object)(object)p.data != (Object)null && !p.data.dead)
		{
			return ((Component)p).gameObject.activeInHierarchy;
		}
		return false;
	}

	internal static bool IsLocalHuman(Player p)
	{
		if (IsMine(p))
		{
			return !IsBot(p);
		}
		return false;
	}

	internal static bool IsBot(Player p)
	{
		if ((Object)(object)p == (Object)null || (Object)(object)p.data == (Object)null)
		{
			return false;
		}
		int instanceID = ((Object)p).GetInstanceID();
		if (s_botCache.TryGetValue(instanceID, out var value) && value)
		{
			return true;
		}
		int num;
		if (!HasRwbBotFlag(p))
		{
			num = (HasAiComponent(p) ? 1 : 0);
			if (num == 0)
			{
				goto IL_0053;
			}
		}
		else
		{
			num = 1;
		}
		s_botCache[instanceID] = true;
		goto IL_0053;
		IL_0053:
		return (byte)num != 0;
	}

	private static bool HasAiComponent(Player p)
	{
		MonoBehaviour[] componentsInChildren = ((Component)p).GetComponentsInChildren<MonoBehaviour>(true);
		foreach (MonoBehaviour val in componentsInChildren)
		{
			if ((Object)(object)val != (Object)null && ((object)val).GetType().Name.StartsWith("PlayerAI", StringComparison.Ordinal))
			{
				return true;
			}
		}
		return false;
	}

	private static bool HasRwbBotFlag(Player p)
	{
		if (!s_rwbLookedUp)
		{
			s_rwbLookedUp = true;
			Type type = AccessTools.TypeByName("RoundsWithBots.Extensions.CharacterDataExtension");
			s_rwbGetData = ((type != null) ? AccessTools.Method(type, "GetAdditionalData", (Type[])null, (Type[])null) : null);
			Type type2 = AccessTools.TypeByName("RoundsWithBots.Extensions.CharacterDataAdditionalData");
			s_rwbIsBot = ((type2 != null) ? AccessTools.Property(type2, "IsBot") : null);
		}
		if (s_rwbGetData == null || s_rwbIsBot == null)
		{
			return false;
		}
		try
		{
			object obj = s_rwbGetData.Invoke(null, new object[1] { p.data });
			return obj != null && (bool)s_rwbIsBot.GetValue(obj, null);
		}
		catch
		{
			return false;
		}
	}
}
internal static class SettingsMenu
{
	private const int HeaderSize = 45;

	private const int ToggleSize = 40;

	private const int SliderSize = 30;

	private const int ButtonSize = 35;

	private static readonly KeyCode[] s_bindableKeys = ((KeyCode[])Enum.GetValues(typeof(KeyCode))).Where((KeyCode k) => (int)k != 0 && (int)k != 323 && (int)k != 324 && (int)k != 27).Distinct().ToArray();

	private static ConfigEntry<KeyCode> s_pendingRebind;

	private static TextMeshProUGUI s_pendingLabel;

	private static string s_pendingLabelPrefix;

	private static readonly List<Action> s_refreshers = new List<Action>();

	internal static void Build(GameObject menu)
	{
		//IL_003a: 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_01b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ce: Expected O, but got Unknown
		//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
		s_refreshers.Clear();
		TextMeshProUGUI val = default(TextMeshProUGUI);
		MenuHandler.CreateText("Spectate+", menu, ref val, 60, false, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
		MenuHandler.CreateText("Better spectating on big maps", menu, ref val, 25, false, (Color?)Color.gray, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
		Blank(menu);
		Header(menu, "General");
		Toggle(menu, SpectatePlus.Enabled, "Enable Spectate+");
		Toggle(menu, SpectatePlus.ShowHud, "Show spectator hint bar");
		Toggle(menu, SpectatePlus.ControllerSupport, "Controller support");
		Toggle(menu, SpectatePlus.IgnoreBotsCamera, "Camera ignores bots while alive");
		Blank(menu);
		Header(menu, "Edge panning");
		Toggle(menu, SpectatePlus.EdgePanEnabled, "Pan with mouse at screen edge");
		Slider(menu, SpectatePlus.EdgePanSpeed, "Pan speed", 0.25f, 5f);
		PercentSlider(menu, SpectatePlus.EdgePanMargin, "Edge size (% of screen)", 1, 20);
		Blank(menu);
		Header(menu, "Zoom");
		Toggle(menu, SpectatePlus.ScrollZoomEnabled, "Scroll wheel zoom");
		Slider(menu, SpectatePlus.ScrollZoomSpeed, "Scroll zoom speed", 0.25f, 3f);
		Slider(menu, SpectatePlus.FollowZoom, "Follow camera size (1 = normal view)", 0.5f, 3f);
		Blank(menu);
		Header(menu, "Keybinds (click, then press a key)");
		KeyButton(menu, SpectatePlus.FollowPrevKey, "Follow previous player");
		KeyButton(menu, SpectatePlus.FollowNextKey, "Follow next player");
		KeyButton(menu, SpectatePlus.OverviewKey, "Full map / unfollow");
		Blank(menu);
		MenuHandler.CreateButton("Reset to defaults", menu, new UnityAction(ResetDefaults), 35, false, (Color?)new Color(1f, 0.55f, 0.55f), (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
		Blank(menu);
		MenuHandler.CreateText("Made by Zen", menu, ref val, 20, false, (Color?)Color.gray, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
	}

	private static void Header(GameObject menu, string text)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		TextMeshProUGUI val = default(TextMeshProUGUI);
		MenuHandler.CreateText(text, menu, ref val, 45, false, (Color?)new Color(0.55f, 0.85f, 1f), (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
	}

	private static void Blank(GameObject menu)
	{
		TextMeshProUGUI val = default(TextMeshProUGUI);
		MenuHandler.CreateText(" ", menu, ref val, 15, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
	}

	private static void Toggle(GameObject menu, ConfigEntry<bool> entry, string label)
	{
		GameObject val = MenuHandler.CreateToggle(entry.Value, label, menu, (UnityAction<bool>)delegate(bool v)
		{
			entry.Value = v;
		}, 40, false, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
		Toggle toggle = val.GetComponent<Toggle>();
		s_refreshers.Add(delegate
		{
			if ((Object)(object)toggle != (Object)null)
			{
				toggle.isOn = entry.Value;
			}
		});
	}

	private static void Slider(GameObject menu, ConfigEntry<float> entry, string label, float min, float max)
	{
		Slider slider = default(Slider);
		MenuHandler.CreateSlider(label, menu, 30, min, max, entry.Value, (UnityAction<float>)delegate(float v)
		{
			entry.Value = (float)Math.Round(v, 2);
		}, ref slider, false, (Color?)null, (Direction)0, false, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
		s_refreshers.Add(delegate
		{
			if ((Object)(object)slider != (Object)null)
			{
				slider.value = entry.Value;
			}
		});
	}

	private static void PercentSlider(GameObject menu, ConfigEntry<float> entry, string label, int min, int max)
	{
		Slider slider = default(Slider);
		MenuHandler.CreateSlider(label, menu, 30, (float)min, (float)max, Mathf.Round(entry.Value * 100f), (UnityAction<float>)delegate(float v)
		{
			entry.Value = v / 100f;
		}, ref slider, true, (Color?)null, (Direction)0, false, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
		s_refreshers.Add(delegate
		{
			if ((Object)(object)slider != (Object)null)
			{
				slider.value = Mathf.Round(entry.Value * 100f);
			}
		});
	}

	private static void KeyButton(GameObject menu, ConfigEntry<KeyCode> entry, string label)
	{
		//IL_0031: 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_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Expected O, but got Unknown
		TextMeshProUGUI text = null;
		string prefix = label + ": ";
		GameObject val = MenuHandler.CreateButton(prefix + ((object)entry.Value/*cast due to .constrained prefix*/).ToString(), menu, (UnityAction)delegate
		{
			CancelRebind();
			s_pendingRebind = entry;
			s_pendingLabel = text;
			s_pendingLabelPrefix = prefix;
			if ((Object)(object)text != (Object)null)
			{
				((TMP_Text)text).text = prefix + "press a key...";
			}
		}, 35, false, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
		text = val.GetComponentInChildren<TextMeshProUGUI>();
		s_refreshers.Add(delegate
		{
			//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)
			if ((Object)(object)text != (Object)null)
			{
				((TMP_Text)text).text = prefix + ((object)entry.Value/*cast due to .constrained prefix*/).ToString();
			}
		});
	}

	private static void ResetDefaults()
	{
		//IL_010e: 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_0140: Unknown result type (might be due to invalid IL or missing references)
		CancelRebind();
		SpectatePlus.Enabled.Value = (bool)((ConfigEntryBase)SpectatePlus.Enabled).DefaultValue;
		SpectatePlus.ShowHud.Value = (bool)((ConfigEntryBase)SpectatePlus.ShowHud).DefaultValue;
		SpectatePlus.ControllerSupport.Value = (bool)((ConfigEntryBase)SpectatePlus.ControllerSupport).DefaultValue;
		SpectatePlus.IgnoreBotsCamera.Value = (bool)((ConfigEntryBase)SpectatePlus.IgnoreBotsCamera).DefaultValue;
		SpectatePlus.EdgePanEnabled.Value = (bool)((ConfigEntryBase)SpectatePlus.EdgePanEnabled).DefaultValue;
		SpectatePlus.EdgePanSpeed.Value = (float)((ConfigEntryBase)SpectatePlus.EdgePanSpeed).DefaultValue;
		SpectatePlus.EdgePanMargin.Value = (float)((ConfigEntryBase)SpectatePlus.EdgePanMargin).DefaultValue;
		SpectatePlus.ScrollZoomEnabled.Value = (bool)((ConfigEntryBase)SpectatePlus.ScrollZoomEnabled).DefaultValue;
		SpectatePlus.ScrollZoomSpeed.Value = (float)((ConfigEntryBase)SpectatePlus.ScrollZoomSpeed).DefaultValue;
		SpectatePlus.FollowZoom.Value = (float)((ConfigEntryBase)SpectatePlus.FollowZoom).DefaultValue;
		SpectatePlus.FollowPrevKey.Value = (KeyCode)((ConfigEntryBase)SpectatePlus.FollowPrevKey).DefaultValue;
		SpectatePlus.FollowNextKey.Value = (KeyCode)((ConfigEntryBase)SpectatePlus.FollowNextKey).DefaultValue;
		SpectatePlus.OverviewKey.Value = (KeyCode)((ConfigEntryBase)SpectatePlus.OverviewKey).DefaultValue;
		foreach (Action s_refresher in s_refreshers)
		{
			try
			{
				s_refresher();
			}
			catch
			{
			}
		}
	}

	private static void CancelRebind()
	{
		//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)
		if (s_pendingRebind != null && (Object)(object)s_pendingLabel != (Object)null)
		{
			((TMP_Text)s_pendingLabel).text = s_pendingLabelPrefix + ((object)s_pendingRebind.Value/*cast due to .constrained prefix*/).ToString();
		}
		s_pendingRebind = null;
		s_pendingLabel = null;
	}

	internal static bool HandleRebind()
	{
		//IL_0033: 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_0041: Unknown result type (might be due to invalid IL or missing references)
		if (s_pendingRebind == null)
		{
			return false;
		}
		if (Input.GetKeyDown((KeyCode)27) || (Object)(object)s_pendingLabel == (Object)null)
		{
			CancelRebind();
			return true;
		}
		KeyCode[] array = s_bindableKeys;
		foreach (KeyCode val in array)
		{
			if (Input.GetKeyDown(val))
			{
				s_pendingRebind.Value = val;
				CancelRebind();
				break;
			}
		}
		return true;
	}
}
public class SpectateController : MonoBehaviour
{
	private const float MinZoomFraction = 0.5f;

	private const float LargeMapThreshold = 1.02f;

	private bool _active;

	private Player _followTarget;

	private float _overviewSize;

	private Vector2 _overviewCenter;

	private float _followMultiplier;

	private Vector2 _mapSize;

	private float _fullSize;

	private float _normalSize;

	private float _aspect = 1.7777778f;

	private Vector2 _lastLoggedMapSize;

	internal static SpectateController Instance { get; private set; }

	internal bool IsActive => _active;

	internal Player FollowTarget => _followTarget;

	private float MinSize => _normalSize * 0.5f;

	private void Awake()
	{
		Instance = this;
	}

	internal void Deactivate()
	{
		if (_active)
		{
			_active = false;
			_followTarget = null;
		}
	}

	internal void Apply(ref Vector2 targetPosition, ref float targetSize, Vector2 mapSize, float viewportHeight)
	{
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: 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)
		//IL_013b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0140: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b5: 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_014a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0159: Unknown result type (might be due to invalid IL or missing references)
		//IL_0294: Unknown result type (might be due to invalid IL or missing references)
		//IL_029f: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_025e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0263: 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_026e: Unknown result type (might be due to invalid IL or missing references)
		List<Player> list = PlayerManager.instance.players.Where(PlayerUtil.IsLocalHuman).ToList();
		if (list.Count == 0)
		{
			Deactivate();
			return;
		}
		_aspect = (((Object)(object)MainCam.instance != (Object)null && (Object)(object)MainCam.instance.cam != (Object)null) ? MainCam.instance.cam.aspect : 1.7777778f);
		_mapSize = mapSize;
		_normalSize = viewportHeight * 0.5f;
		_fullSize = Mathf.Max(mapSize.y, mapSize.x / _aspect) * 0.5f;
		List<Player> list2 = list.Where((Player p) => !p.data.dead).ToList();
		if (list2.Count > 0)
		{
			Deactivate();
			if (SpectatePlus.IgnoreBotsCamera.Value && PlayerManager.instance.players.Any((Player p) => PlayerUtil.IsMine(p) && PlayerUtil.IsBot(p)))
			{
				FollowHumans(list2, viewportHeight, ref targetPosition, ref targetSize);
			}
			return;
		}
		if (_fullSize <= _normalSize * 1.02f)
		{
			if (_lastLoggedMapSize != mapSize)
			{
				_lastLoggedMapSize = mapSize;
				SpectatePlus.Log.LogInfo((object)$"Map fits on screen (map {mapSize}, view height {viewportHeight}); not needed here.");
			}
			Deactivate();
			return;
		}
		if (!_active)
		{
			_active = true;
			_followTarget = null;
			ResetOverview();
			_followMultiplier = SpectatePlus.FollowZoom.Value;
			SpectatePlus.Log.LogInfo((object)$"Spectating: map {mapSize}, normal size {_normalSize:0.0}, full-map size {_fullSize:0.0}, {LivingPlayers().Count} players to follow.");
		}
		if ((Object)(object)_followTarget != (Object)null && !PlayerUtil.IsAlive(_followTarget))
		{
			_followTarget = NextLiving(_followTarget, 1);
		}
		if ((Object)(object)_followTarget != (Object)null)
		{
			targetPosition = ClampCenter(size: targetSize = Mathf.Clamp(_normalSize * _followMultiplier, MinSize, _fullSize), center: Vector2.op_Implicit(((Component)_followTarget).transform.position));
			return;
		}
		_overviewSize = Mathf.Clamp(_overviewSize, MinSize, _fullSize);
		_overviewCenter = ClampCenter(_overviewCenter, _overviewSize);
		targetSize = _overviewSize;
		targetPosition = _overviewCenter;
	}

	private void FollowHumans(List<Player> players, float viewportHeight, ref Vector2 targetPosition, ref float targetSize)
	{
		//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_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: 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_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: 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_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f7: 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)
		Vector2 val = default(Vector2);
		((Vector2)(ref val))..ctor(viewportHeight * _aspect, viewportHeight);
		Bounds? val2 = null;
		Bounds val4 = default(Bounds);
		foreach (Player player in players)
		{
			Vector2 val3 = ClampCenter(Vector2.op_Implicit(((Component)player).transform.position), viewportHeight * 0.5f);
			((Bounds)(ref val4))..ctor(Vector2.op_Implicit(val3), Vector2.op_Implicit(val));
			if (val2.HasValue)
			{
				Bounds value = val2.Value;
				((Bounds)(ref value)).Encapsulate(val4);
				val2 = value;
			}
			else
			{
				val2 = val4;
			}
		}
		if (val2.HasValue)
		{
			Bounds value2 = val2.Value;
			float num = Mathf.Max(((Bounds)(ref value2)).size.y, ((Bounds)(ref value2)).size.x / _aspect);
			targetSize = num * 0.5f;
			targetPosition = ClampCenter(Vector2.op_Implicit(((Bounds)(ref value2)).center), targetSize);
		}
	}

	private void ResetOverview()
	{
		//IL_000d: 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)
		_overviewSize = _fullSize;
		_overviewCenter = Vector2.zero;
	}

	private void Update()
	{
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0103: Unknown result type (might be due to invalid IL or missing references)
		//IL_0165: Unknown result type (might be due to invalid IL or missing references)
		//IL_016a: 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_019b: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a5: 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_01ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01db: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ed: 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_01fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0185: Unknown result type (might be due to invalid IL or missing references)
		//IL_0186: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)
		if (SettingsMenu.HandleRebind() || !_active || GameManager.lockInput || DevConsole.isTyping)
		{
			return;
		}
		float unscaledDeltaTime = Time.unscaledDeltaTime;
		InputDevice val = (SpectatePlus.ControllerSupport.Value ? InputManager.ActiveDevice : null);
		if (Input.GetKeyDown(SpectatePlus.FollowNextKey.Value) || (val != null && ((OneAxisInputControl)val.DPadRight).WasPressed))
		{
			_followTarget = NextLiving(_followTarget, 1);
		}
		else if (Input.GetKeyDown(SpectatePlus.FollowPrevKey.Value) || (val != null && ((OneAxisInputControl)val.DPadLeft).WasPressed))
		{
			_followTarget = NextLiving(_followTarget, -1);
		}
		else if (Input.GetKeyDown(SpectatePlus.OverviewKey.Value) || (val != null && ((OneAxisInputControl)val.DPadDown).WasPressed))
		{
			_followTarget = null;
			ResetOverview();
			_followMultiplier = SpectatePlus.FollowZoom.Value;
		}
		float num = 0f;
		if (SpectatePlus.ScrollZoomEnabled.Value && Application.isFocused && MouseInsideWindow())
		{
			num += Input.mouseScrollDelta.y;
		}
		if (val != null)
		{
			if (((OneAxisInputControl)val.RightBumper).IsPressed)
			{
				num += 6f * unscaledDeltaTime;
			}
			if (((OneAxisInputControl)val.LeftBumper).IsPressed)
			{
				num -= 6f * unscaledDeltaTime;
			}
		}
		if (Mathf.Abs(num) > 0.0001f)
		{
			ApplyZoom(num);
		}
		if ((Object)(object)_followTarget == (Object)null)
		{
			Vector2 val2 = Vector2.zero;
			if (SpectatePlus.EdgePanEnabled.Value && Application.isFocused && MouseInsideWindow())
			{
				val2 += EdgePanDirection();
			}
			if (val != null)
			{
				val2 += val.RightStick.Vector;
			}
			if (((Vector2)(ref val2)).sqrMagnitude > 0.0001f)
			{
				val2 = Vector2.ClampMagnitude(val2, 1f);
				_overviewCenter += val2 * (SpectatePlus.EdgePanSpeed.Value * _overviewSize * unscaledDeltaTime);
				_overviewCenter = ClampCenter(_overviewCenter, _overviewSize);
			}
		}
	}

	private void ApplyZoom(float steps)
	{
		//IL_010e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0119: 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_007f: 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_00c0: 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_00db: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fa: 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)
		float num = Mathf.Pow(0.88f, steps * SpectatePlus.ScrollZoomSpeed.Value);
		if ((Object)(object)_followTarget != (Object)null)
		{
			float num2 = _fullSize / _normalSize;
			_followMultiplier = Mathf.Clamp(_followMultiplier * num, 0.5f, num2);
			return;
		}
		float overviewSize = _overviewSize;
		float num3 = Mathf.Clamp(overviewSize * num, MinSize, _fullSize);
		if (!Mathf.Approximately(overviewSize, num3))
		{
			if (MouseInsideWindow())
			{
				Vector2 val = default(Vector2);
				((Vector2)(ref val))..ctor(Input.mousePosition.x / (float)Screen.width - 0.5f, Input.mousePosition.y / (float)Screen.height - 0.5f);
				Vector2 val2 = default(Vector2);
				((Vector2)(ref val2))..ctor(2f * _aspect * val.x, 2f * val.y);
				Vector2 val3 = _overviewCenter + val2 * overviewSize;
				_overviewCenter = val3 - val2 * num3;
			}
			_overviewSize = num3;
			_overviewCenter = ClampCenter(_overviewCenter, _overviewSize);
		}
	}

	private static Vector2 EdgePanDirection()
	{
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		float num = Screen.width;
		float num2 = Screen.height;
		float margin = Mathf.Max(4f, SpectatePlus.EdgePanMargin.Value * Mathf.Min(num, num2));
		Vector3 mousePosition = Input.mousePosition;
		return new Vector2(EdgeAxis(mousePosition.x, num, margin), EdgeAxis(mousePosition.y, num2, margin));
	}

	private static float EdgeAxis(float pos, float length, float margin)
	{
		if (pos < margin)
		{
			return 0f - Mathf.Lerp(0.35f, 1f, 1f - pos / margin);
		}
		if (pos > length - margin)
		{
			return Mathf.Lerp(0.35f, 1f, (pos - (length - margin)) / margin);
		}
		return 0f;
	}

	private static bool MouseInsideWindow()
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: 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_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		Vector3 mousePosition = Input.mousePosition;
		if (mousePosition.x >= 0f && mousePosition.y >= 0f && mousePosition.x <= (float)Screen.width)
		{
			return mousePosition.y <= (float)Screen.height;
		}
		return false;
	}

	private Vector2 ClampCenter(Vector2 center, float size)
	{
		//IL_0011: 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_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: 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_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0099: Unknown result type (might be due to invalid IL or missing references)
		Vector2 val = default(Vector2);
		((Vector2)(ref val))..ctor(size * _aspect, size);
		Vector2 val2 = _mapSize * 0.5f;
		float num = ((val.x >= val2.x) ? 0f : Mathf.Clamp(center.x, 0f - val2.x + val.x, val2.x - val.x));
		float num2 = ((val.y >= val2.y) ? 0f : Mathf.Clamp(center.y, 0f - val2.y + val.y, val2.y - val.y));
		return new Vector2(num, num2);
	}

	private static List<Player> LivingPlayers()
	{
		return (from p in PlayerManager.instance.players
			where PlayerUtil.IsAlive(p) && !PlayerUtil.IsLocalHuman(p)
			orderby p.playerID
			select p).ToList();
	}

	private static Player NextLiving(Player current, int direction)
	{
		List<Player> list = LivingPlayers();
		if (list.Count == 0)
		{
			return null;
		}
		if ((Object)(object)current == (Object)null)
		{
			if (direction <= 0)
			{
				return list[list.Count - 1];
			}
			return list[0];
		}
		int num = list.IndexOf(current);
		if (num < 0)
		{
			int id = current.playerID;
			object obj;
			if (direction <= 0)
			{
				obj = ((IEnumerable<Player>)list).LastOrDefault((Func<Player, bool>)((Player p) => p.playerID < id));
				if (obj == null)
				{
					return list[list.Count - 1];
				}
			}
			else
			{
				obj = ((IEnumerable<Player>)list).FirstOrDefault((Func<Player, bool>)((Player p) => p.playerID > id)) ?? list[0];
			}
			return (Player)obj;
		}
		int index = ((num + direction) % list.Count + list.Count) % list.Count;
		return list[index];
	}

	internal static string DisplayName(Player p)
	{
		if (PlayerUtil.IsBot(p))
		{
			return $"Bot {p.playerID + 1}";
		}
		string text = null;
		try
		{
			Player owner = p.data.view.Owner;
			if (!PhotonNetwork.OfflineMode && owner != null && !string.IsNullOrEmpty(owner.NickName))
			{
				text = owner.NickName;
				int num = (from o in PlayerManager.instance.players
					where (Object)(object)o != (Object)null && (Object)(object)o.data != (Object)null && (Object)(object)o.data.view != (Object)null && o.data.view.Owner == owner && !PlayerUtil.IsBot(o)
					orderby o.playerID
					select o).ToList().IndexOf(p);
				if (num > 0)
				{
					text += $" ({num + 1})";
				}
			}
		}
		catch
		{
			text = null;
		}
		if (!string.IsNullOrEmpty(text))
		{
			return text;
		}
		return $"Player {p.playerID + 1}";
	}
}
public class SpectateHud : MonoBehaviour
{
	private static readonly Color CardColor = new Color(0.06f, 0.07f, 0.1f, 0.86f);

	private static readonly Color CardBorder = new Color(1f, 1f, 1f, 0.09f);

	private static readonly Color LabelColor = new Color(0.62f, 0.67f, 0.78f, 1f);

	private static readonly Color HintColor = new Color(0.8f, 0.83f, 0.9f, 1f);

	private static readonly Color KeyFill = new Color(1f, 1f, 1f, 0.12f);

	private static readonly Color KeyBorder = new Color(1f, 1f, 1f, 0.22f);

	private static readonly Color OverviewAccent = new Color(0.45f, 0.78f, 1f, 1f);

	private readonly Dictionary<int, GUIStyle> _roundedStyles = new Dictionary<int, GUIStyle>();

	private GUIStyle _labelStyle;

	private GUIStyle _nameStyle;

	private GUIStyle _hintStyle;

	private GUIStyle _keyStyle;

	private float _builtForScale = -1f;

	private float _alpha;

	private Color _accent = OverviewAccent;

	private Player _shownTarget;

	private void Update()
	{
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		SpectateController instance = SpectateController.Instance;
		bool flag = (Object)(object)instance != (Object)null && instance.IsActive && SpectatePlus.ShowHud.Value;
		_alpha = Mathf.MoveTowards(_alpha, flag ? 1f : 0f, Time.unscaledDeltaTime * 5f);
		if (flag)
		{
			Player val = (_shownTarget = instance.FollowTarget);
			Color val2 = (((Object)(object)val != (Object)null) ? PlayerColor(val) : OverviewAccent);
			_accent = Color.Lerp(_accent, val2, Time.unscaledDeltaTime * 10f);
		}
	}

	private void OnGUI()
	{
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d1: Expected O, but got Unknown
		//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01db: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e5: Expected O, but got Unknown
		//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0206: Unknown result type (might be due to invalid IL or missing references)
		//IL_020d: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02db: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_02eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_030a: Unknown result type (might be due to invalid IL or missing references)
		//IL_035b: Unknown result type (might be due to invalid IL or missing references)
		//IL_038b: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_03df: 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_03f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_041e: Unknown result type (might be due to invalid IL or missing references)
		//IL_042c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0447: Unknown result type (might be due to invalid IL or missing references)
		//IL_0456: Unknown result type (might be due to invalid IL or missing references)
		//IL_045d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0464: Unknown result type (might be due to invalid IL or missing references)
		//IL_0471: Unknown result type (might be due to invalid IL or missing references)
		//IL_0477: Unknown result type (might be due to invalid IL or missing references)
		//IL_0481: Unknown result type (might be due to invalid IL or missing references)
		//IL_0661: Unknown result type (might be due to invalid IL or missing references)
		//IL_04e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0507: Unknown result type (might be due to invalid IL or missing references)
		//IL_05fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_0604: Expected O, but got Unknown
		//IL_05ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0604: Unknown result type (might be due to invalid IL or missing references)
		//IL_060d: Unknown result type (might be due to invalid IL or missing references)
		//IL_061c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0623: Unknown result type (might be due to invalid IL or missing references)
		//IL_062a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0637: Unknown result type (might be due to invalid IL or missing references)
		//IL_0643: Unknown result type (might be due to invalid IL or missing references)
		//IL_0552: Unknown result type (might be due to invalid IL or missing references)
		//IL_055c: Expected O, but got Unknown
		//IL_0557: Unknown result type (might be due to invalid IL or missing references)
		//IL_055c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0560: Unknown result type (might be due to invalid IL or missing references)
		//IL_0587: Unknown result type (might be due to invalid IL or missing references)
		//IL_0590: Unknown result type (might be due to invalid IL or missing references)
		//IL_059b: Unknown result type (might be due to invalid IL or missing references)
		//IL_05a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_05ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_05b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_05c3: Unknown result type (might be due to invalid IL or missing references)
		SpectateController instance = SpectateController.Instance;
		if (_alpha <= 0.001f || (Object)(object)instance == (Object)null)
		{
			return;
		}
		float num = Mathf.Clamp((float)Screen.height / 1080f, 0.6f, 2.5f);
		BuildStyles(num);
		Player val = (instance.IsActive ? instance.FollowTarget : _shownTarget);
		string text = "SPECTATING";
		string text2 = (((Object)(object)val != (Object)null) ? SpectateController.DisplayName(val) : "Full Map");
		List<(string[], string)> list = new List<(string[], string)>();
		string text3 = KeyLabel(SpectatePlus.FollowPrevKey.Value);
		string text4 = KeyLabel(SpectatePlus.FollowNextKey.Value);
		if ((Object)(object)val != (Object)null)
		{
			list.Add((new string[2] { text3, text4 }, "Switch"));
			list.Add((new string[1] { KeyLabel(SpectatePlus.OverviewKey.Value) }, "Full map"));
		}
		else
		{
			list.Add((new string[2] { text3, text4 }, "Follow player"));
			if (SpectatePlus.EdgePanEnabled.Value)
			{
				list.Add((null, "Mouse to edge to pan"));
			}
		}
		if (SpectatePlus.ScrollZoomEnabled.Value)
		{
			list.Add((new string[1] { "Scroll" }, "Zoom"));
		}
		float num2 = 22f * num;
		float num3 = 12f * num;
		float num4 = 19f * num;
		float num5 = 9f * num;
		float num6 = 8f * num;
		float num7 = 7f * num;
		float num8 = 24f * num;
		float num9 = 8f * num;
		float num10 = 4f * num;
		float num11 = 7f * num;
		float num12 = 20f * num;
		Vector2 val2 = _labelStyle.CalcSize(new GUIContent(text));
		Vector2 val3 = _nameStyle.CalcSize(new GUIContent(text2));
		float num13 = val2.x + 12f * num + num6 + num7 + val3.x;
		float num14 = Mathf.Max(val2.y, val3.y);
		float num15 = 0f;
		for (int i = 0; i < list.Count; i++)
		{
			num15 += GroupWidth(list[i], num9, num10, num11, num);
			if (i > 0)
			{
				num15 += num12;
			}
		}
		float num16 = Mathf.Max(num13, num15) + num2 * 2f;
		float num17 = num3 + num14 + num5 + num8 + num4;
		float num18 = (1f - EaseOut(_alpha)) * -12f * num;
		Rect r = default(Rect);
		((Rect)(ref r))..ctor(Mathf.Round(((float)Screen.width - num16) * 0.5f), Mathf.Round(22f * num + num18), Mathf.Round(num16), Mathf.Round(num17));
		Color color = GUI.color;
		float num19 = 14f * num;
		DrawRounded(r, num19, CardBorder);
		DrawRounded(Inset(r, 1f), num19 - 1f, CardColor);
		float num20 = Mathf.Max(2f, 3f * num);
		Rect r2 = default(Rect);
		((Rect)(ref r2))..ctor(((Rect)(ref r)).x + num19, ((Rect)(ref r)).yMax - num20 - 1f, ((Rect)(ref r)).width - num19 * 2f, num20);
		DrawRounded(r2, num20 * 0.5f, new Color(_accent.r, _accent.g, _accent.b, 0.85f));
		float num21 = ((Rect)(ref r)).x + (((Rect)(ref r)).width - num13) * 0.5f;
		float num22 = ((Rect)(ref r)).y + num3;
		DrawText(new Rect(num21, num22 + (num14 - val2.y) * 0.5f, val2.x, val2.y), text, _labelStyle, LabelColor);
		num21 += val2.x + 12f * num;
		DrawRounded(new Rect(num21, num22 + (num14 - num6) * 0.5f, num6, num6), num6 * 0.5f, _accent);
		num21 += num6 + num7;
		DrawText(new Rect(num21, num22 + (num14 - val3.y) * 0.5f, val3.x, val3.y), text2, _nameStyle, Color.Lerp(Color.white, _accent, 0.35f));
		float num23 = ((Rect)(ref r)).x + (((Rect)(ref r)).width - num15) * 0.5f;
		float num24 = num22 + num14 + num5;
		Rect r3 = default(Rect);
		for (int j = 0; j < list.Count; j++)
		{
			if (j > 0)
			{
				float num25 = 3f * num;
				DrawRounded(new Rect(num23 + (num12 - num25) * 0.5f, num24 + (num8 - num25) * 0.5f, num25, num25), num25 * 0.5f, new Color(1f, 1f, 1f, 0.25f));
				num23 += num12;
			}
			var (array, text5) = list[j];
			if (array != null)
			{
				string[] array2 = array;
				foreach (string text6 in array2)
				{
					Vector2 val4 = _keyStyle.CalcSize(new GUIContent(text6));
					float num26 = Mathf.Max(num8, val4.x + num9 * 2f);
					((Rect)(ref r3))..ctor(num23, num24, num26, num8);
					DrawRounded(r3, 5f * num, KeyBorder);
					DrawRounded(Inset(r3, 1f), 4f * num, KeyFill);
					DrawText(r3, text6, _keyStyle, Color.white);
					num23 += num26 + num10;
				}
				num23 += num11 - num10;
			}
			Vector2 val5 = _hintStyle.CalcSize(new GUIContent(text5));
			DrawText(new Rect(num23, num24 + (num8 - val5.y) * 0.5f, val5.x, val5.y), text5, _hintStyle, HintColor);
			num23 += val5.x;
		}
		GUI.color = color;
	}

	private float GroupWidth((string[] keys, string text) group, float keyPadX, float keyGap, float keyTextGap, float s)
	{
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Expected O, but got Unknown
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Expected O, but got Unknown
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		float num = 0f;
		float num2 = 24f * s;
		if (group.keys != null)
		{
			string[] item = group.keys;
			foreach (string text in item)
			{
				num += Mathf.Max(num2, _keyStyle.CalcSize(new GUIContent(text)).x + keyPadX * 2f) + keyGap;
			}
			num += keyTextGap - keyGap;
		}
		return num + _hintStyle.CalcSize(new GUIContent(group.text)).x;
	}

	private void DrawText(Rect r, string text, GUIStyle style, Color color)
	{
		//IL_0000: 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_000e: 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_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		GUI.color = new Color(color.r, color.g, color.b, color.a * _alpha);
		GUI.Label(r, text, style);
	}

	private void DrawRounded(Rect r, float radius, Color color)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Invalid comparison between Unknown and I4
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: 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_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		if ((int)Event.current.type == 7)
		{
			int radius2 = Mathf.Clamp(Mathf.RoundToInt(radius), 1, 64);
			GUI.color = new Color(color.r, color.g, color.b, color.a * _alpha);
			RoundedStyle(radius2).Draw(r, false, false, false, false);
		}
	}

	private GUIStyle RoundedStyle(int radius)
	{
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Expected O, but got Unknown
		//IL_011f: 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_0131: Unknown result type (might be due to invalid IL or missing references)
		//IL_013b: Expected O, but got Unknown
		//IL_013c: Expected O, but got Unknown
		//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
		if (_roundedStyles.TryGetValue(radius, out var value) && (Object)(object)value.normal.background != (Object)null)
		{
			return value;
		}
		int num = radius * 2 + 2;
		Texture2D val = new Texture2D(num, num, (TextureFormat)4, false)
		{
			wrapMode = (TextureWrapMode)1,
			filterMode = (FilterMode)1,
			hideFlags = (HideFlags)61
		};
		Color[] array = (Color[])(object)new Color[num * num];
		float num2 = (float)num * 0.5f;
		for (int i = 0; i < num; i++)
		{
			for (int j = 0; j < num; j++)
			{
				float num3 = Mathf.Max(Mathf.Abs((float)j + 0.5f - num2) - (num2 - (float)radius), 0f);
				float num4 = Mathf.Max(Mathf.Abs((float)i + 0.5f - num2) - (num2 - (float)radius), 0f);
				float num5 = Mathf.Sqrt(num3 * num3 + num4 * num4);
				float num6 = Mathf.Clamp01((float)radius - num5 + 0.5f);
				array[i * num + j] = new Color(1f, 1f, 1f, num6);
			}
		}
		val.SetPixels(array);
		val.Apply();
		value = new GUIStyle
		{
			border = new RectOffset(radius + 1, radius + 1, radius + 1, radius + 1)
		};
		value.normal.background = val;
		_roundedStyles[radius] = value;
		return value;
	}

	private void BuildStyles(float s)
	{
		//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_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: 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_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Expected O, but got Unknown
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Expected O, but got Unknown
		//IL_0078: Expected O, but got Unknown
		//IL_007f: 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_009b: Expected O, but got Unknown
		//IL_00a2: 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_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: Expected O, but got Unknown
		//IL_00cc: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ef: Expected O, but got Unknown
		//IL_0126: Unknown result type (might be due to invalid IL or missing references)
		if (_labelStyle == null || !Mathf.Approximately(s, _builtForScale))
		{
			_builtForScale = s;
			_labelStyle = new GUIStyle(GUI.skin.label)
			{
				fontSize = Mathf.RoundToInt(13f * s),
				fontStyle = (FontStyle)1,
				alignment = (TextAnchor)3,
				wordWrap = false,
				padding = new RectOffset(0, 0, 0, 0),
				margin = new RectOffset(0, 0, 0, 0)
			};
			_nameStyle = new GUIStyle(_labelStyle)
			{
				fontSize = Mathf.RoundToInt(13f * s)
			};
			_hintStyle = new GUIStyle(_labelStyle)
			{
				fontSize = Mathf.RoundToInt(15f * s),
				fontStyle = (FontStyle)0
			};
			_keyStyle = new GUIStyle(_labelStyle)
			{
				fontSize = Mathf.RoundToInt(13f * s),
				alignment = (TextAnchor)4
			};
			GUIStyle[] array = (GUIStyle[])(object)new GUIStyle[4] { _labelStyle, _nameStyle, _hintStyle, _keyStyle };
			for (int i = 0; i < array.Length; i++)
			{
				array[i].normal.textColor = Color.white;
			}
		}
	}

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

	private static float EaseOut(float t)
	{
		return 1f - (1f - t) * (1f - t);
	}

	private static Color PlayerColor(Player p)
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: 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_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			float num = default(float);
			float num2 = default(float);
			float num3 = default(float);
			Color.RGBToHSV(PlayerSkinBank.GetPlayerSkinColors(PlayerExtensions.colorID(p)).winText, ref num, ref num2, ref num3);
			return Color.HSVToRGB(num, Mathf.Min(num2, 0.85f), Mathf.Max(num3, 0.85f));
		}
		catch
		{
			return OverviewAccent;
		}
	}

	private unsafe static string KeyLabel(KeyCode key)
	{
		//IL_0000: 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_001c: Expected I4, but got Unknown
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Expected I4, but got Unknown
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Expected I4, but got Unknown
		switch (key - 273)
		{
		default:
			switch (key - 303)
			{
			default:
				switch (key - 325)
				{
				case 0:
					return "M3";
				case 1:
					return "M4";
				case 2:
					return "M5";
				case 3:
					return "M6";
				case 4:
					return "M7";
				default:
				{
					string text = ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString();
					if (text.StartsWith("Alpha"))
					{
						return text.Substring(5);
					}
					if (text.StartsWith("Keypad"))
					{
						return "Num " + text.Substring(6);
					}
					return text;
				}
				}
			case 1:
				return "L-Shift";
			case 0:
				return "R-Shift";
			case 3:
				return "L-Ctrl";
			case 2:
				return "R-Ctrl";
			}
		case 3:
			return "←";
		case 2:
			return "→";
		case 0:
			return "↑";
		case 1:
			return "↓";
		}
	}
}
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInPlugin("com.zen.rounds.spectateplus", "Spectate+", "1.0.1")]
[BepInProcess("Rounds.exe")]
public class SpectatePlus : BaseUnityPlugin
{
	[Serializable]
	[CompilerGenerated]
	private sealed class <>c
	{
		public static readonly <>c <>9 = new <>c();

		public static UnityAction <>9__26_0;

		internal void <Start>b__26_0()
		{
		}
	}

	public const string ModId = "com.zen.rounds.spectateplus";

	public const string ModName = "Spectate+";

	public const string Version = "1.0.1";

	public const string ModInitials = "Zen";

	internal static ConfigEntry<bool> Enabled;

	internal static ConfigEntry<bool> ShowHud;

	internal static ConfigEntry<bool> ControllerSupport;

	internal static ConfigEntry<bool> IgnoreBotsCamera;

	internal static ConfigEntry<bool> EdgePanEnabled;

	internal static ConfigEntry<float> EdgePanSpeed;

	internal static ConfigEntry<float> EdgePanMargin;

	internal static ConfigEntry<bool> ScrollZoomEnabled;

	internal static ConfigEntry<float> ScrollZoomSpeed;

	internal static ConfigEntry<float> FollowZoom;

	internal static ConfigEntry<KeyCode> FollowPrevKey;

	internal static ConfigEntry<KeyCode> FollowNextKey;

	internal static ConfigEntry<KeyCode> OverviewKey;

	internal static SpectatePlus Instance { get; private set; }

	internal static ManualLogSource Log { get; private set; }

	private void Awake()
	{
		//IL_00df: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Expected O, but got Unknown
		//IL_011c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0126: Expected O, but got Unknown
		//IL_0179: Unknown result type (might be due to invalid IL or missing references)
		//IL_0183: Expected O, but got Unknown
		//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c0: Expected O, but got Unknown
		//IL_0245: Unknown result type (might be due to invalid IL or missing references)
		//IL_024f: Expected O, but got Unknown
		Instance = this;
		Log = ((BaseUnityPlugin)this).Logger;
		Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Turn Spectate+ on or off.");
		ShowHud = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowHud", true, "Show the spectator hint bar at the top of the screen while dead.");
		ControllerSupport = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ControllerSupport", true, "D-pad left/right = follow, D-pad down = full map, right stick = pan, bumpers = zoom.");
		IgnoreBotsCamera = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "IgnoreBotsCamera", true, "When you host bots, the camera follows only you while alive instead of zooming out to fit the bots too.");
		EdgePanEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Panning", "EdgePanEnabled", true, "Pan the camera by moving the mouse to the edge of the screen.");
		EdgePanSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Panning", "EdgePanSpeed", 1.5f, new ConfigDescription("How fast edge panning moves.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 5f), Array.Empty<object>()));
		EdgePanMargin = ((BaseUnityPlugin)this).Config.Bind<float>("Panning", "EdgePanMargin", 0.04f, new ConfigDescription("How close to the edge (fraction of screen) the mouse must be to pan.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 0.2f), Array.Empty<object>()));
		ScrollZoomEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Zoom", "ScrollZoomEnabled", true, "Use the scroll wheel to zoom in and out while spectating.");
		ScrollZoomSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Zoom", "ScrollZoomSpeed", 1f, new ConfigDescription("How fast the scroll wheel zooms.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 3f), Array.Empty<object>()));
		FollowZoom = ((BaseUnityPlugin)this).Config.Bind<float>("Zoom", "FollowZoom", 1.25f, new ConfigDescription("Camera size when following a player, relative to the normal in-game camera (1 = same as when alive).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 3f), Array.Empty<object>()));
		FollowPrevKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keys", "FollowPrevious", (KeyCode)97, "Follow the previous living player.");
		FollowNextKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keys", "FollowNext", (KeyCode)100, "Follow the next living player.");
		OverviewKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keys", "FullMap", (KeyCode)115, "Stop following and zoom out to the full map.");
		((Component)this).gameObject.AddComponent<SpectateController>();
		((Component)this).gameObject.AddComponent<SpectateHud>();
		if (!MapsExtBridge.TryPatch(new Harmony("com.zen.rounds.spectateplus")))
		{
			Log.LogWarning((object)"MapsExtended CameraHandler not found. Spectate+ only works on MapsExtended custom maps.");
		}
	}

	private void Start()
	{
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Expected O, but got Unknown
		Unbound.RegisterClientSideMod("com.zen.rounds.spectateplus");
		Unbound.RegisterCredits("Spectate+", new string[2] { "Zen", "Built on MapsExtended by olavim" }, new string[1] { "Thunderstore" }, new string[1] { "https://thunderstore.io/c/rounds/p/Zenith/" });
		object obj = <>c.<>9__26_0;
		if (obj == null)
		{
			UnityAction val = delegate
			{
			};
			<>c.<>9__26_0 = val;
			obj = (object)val;
		}
		Unbound.RegisterMenu("Spectate+", (UnityAction)obj, (Action<GameObject>)SettingsMenu.Build, (GameObject)null, true);
	}
}