Decompiled source of Repo Kart Arena v1.1.0

EmpressRepoKartArena.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[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("Empress")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Replaces REPO's race arena track flow with a kart-style arena while preserving vanilla REPO ItemVehicle driving.")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0+5f1b735e473ca4ccf3b383128fbebd889cb564da")]
[assembly: AssemblyProduct("Empress REPO Kart Arena")]
[assembly: AssemblyTitle("EmpressRepoKartArena")]
[assembly: AssemblyVersion("0.1.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 Empress.RepoKartArena
{
	[BepInPlugin("com.empress.repo.kartarena", "Empress REPO Kart Arena", "0.1.0")]
	public sealed class EmpressRepoKartArenaPlugin : BaseUnityPlugin, IOnEventCallback
	{
		public const string PluginGuid = "com.empress.repo.kartarena";

		public const string PluginName = "Empress REPO Kart Arena";

		public const string PluginVersion = "0.1.0";

		internal ConfigEntry<bool> ModEnabled;

		internal ConfigEntry<string> PreferredMapAsset;

		internal ConfigEntry<Vector3> MapOffset;

		internal ConfigEntry<float> MapYawOffset;

		internal ConfigEntry<int> VirtualPieceBuffer;

		internal ConfigEntry<float> ItemBoxRespawnSeconds;

		internal ConfigEntry<float> ItemBoxYOffset;

		internal ConfigEntry<float> ItemBoxWorldSize;

		internal ConfigEntry<float> ItemLifetimeSeconds;

		internal ConfigEntry<float> BoostVelocity;

		internal ConfigEntry<float> ProjectileSpeed;

		internal ConfigEntry<bool> RemoveFog;

		internal ConfigEntry<bool> AddMapLight;

		internal ConfigEntry<bool> BattleMusicEnabled;

		internal ConfigEntry<float> BattleMusicVolume;

		private Harmony _harmony;

		private bool _photonCallbackRegistered;

		internal static EmpressRepoKartArenaPlugin Instance { get; private set; }

		internal static ManualLogSource Log => ((BaseUnityPlugin)Instance).Logger;

		private void Awake()
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Expected O, but got Unknown
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: 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_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Expected O, but got Unknown
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Expected O, but got Unknown
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Expected O, but got Unknown
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a2: Expected O, but got Unknown
			//IL_0339: Unknown result type (might be due to invalid IL or missing references)
			//IL_0343: Expected O, but got Unknown
			//IL_0353: Unknown result type (might be due to invalid IL or missing references)
			//IL_035d: Expected O, but got Unknown
			Instance = this;
			((Component)this).gameObject.transform.parent = null;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			ModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enables the REPO kart arena replacement.");
			PreferredMapAsset = ((BaseUnityPlugin)this).Config.Bind<string>("Map", "PreferredMapAsset", "Assets/Resources/blockfort.prefab", "Preferred prefab asset path/name inside the asset bundle.");
			MapOffset = ((BaseUnityPlugin)this).Config.Bind<Vector3>("Map", "MapOffset", Vector3.zero, "World offset from REPO's race track spawn origin.");
			MapYawOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Map", "MapYawOffset", 0f, "Extra yaw rotation in degrees after REPO's track spawn rotation.");
			VirtualPieceBuffer = ((BaseUnityPlugin)this).Config.Bind<int>("Race", "VirtualPieceBuffer", 8, new ConfigDescription("How many invisible checkpoint pieces REPO keeps buffered ahead.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(3, 32), Array.Empty<object>()));
			ItemBoxRespawnSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Items", "ItemBoxRespawnSeconds", 10f, new ConfigDescription("Seconds before an item box returns.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 30f), Array.Empty<object>()));
			if (Mathf.Approximately(ItemBoxRespawnSeconds.Value, 8f))
			{
				ItemBoxRespawnSeconds.Value = 10f;
			}
			ItemBoxYOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Items", "ItemBoxYOffset", 0.35f, new ConfigDescription("World height offset above item marker transforms.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3f), Array.Empty<object>()));
			if (Mathf.Approximately(ItemBoxYOffset.Value, 0.85f))
			{
				ItemBoxYOffset.Value = 0.35f;
			}
			ItemBoxWorldSize = ((BaseUnityPlugin)this).Config.Bind<float>("Items", "ItemBoxWorldSize", 0.85f, new ConfigDescription("Visual world size for item cubes, independent of the map prefab scale.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 3f), Array.Empty<object>()));
			ItemLifetimeSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Items", "ItemLifetimeSeconds", 8f, new ConfigDescription("Seconds after use before fired/deployed battle items despawn.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 30f), Array.Empty<object>()));
			BoostVelocity = ((BaseUnityPlugin)this).Config.Bind<float>("Items", "BoostVelocity", 16f, new ConfigDescription("Instant forward velocity added by boost pickups.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 40f), Array.Empty<object>()));
			ProjectileSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Items", "ProjectileSpeed", 32f, new ConfigDescription("Speed of shell-style projectiles.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 80f), Array.Empty<object>()));
			RemoveFog = ((BaseUnityPlugin)this).Config.Bind<bool>("Lighting", "RemoveFog", true, "Disables scene fog during battle mode.");
			AddMapLight = ((BaseUnityPlugin)this).Config.Bind<bool>("Lighting", "AddMapLight", true, "Adds a directional light to the battle map.");
			BattleMusicEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Music", "Enabled", true, "Plays bundled battle music during battle mode.");
			BattleMusicVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Music", "Volume", 0.45f, new ConfigDescription("Battle music volume.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			GameAccess.Bind();
			_harmony = new Harmony("com.empress.repo.kartarena");
			ArenaRaceHooks.Install(_harmony);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Empress REPO Kart Arena 0.1.0 loaded.");
		}

		private void OnDestroy()
		{
			DisablePhotonCallbacks();
		}

		public void OnEvent(EventData photonEvent)
		{
			if (ModEnabled.Value && RepoKartRaceRuntime.HasActiveBattle)
			{
				RepoKartBattleNetwork.HandlePhotonEvent(photonEvent);
			}
		}

		internal void EnablePhotonCallbacks()
		{
			if (!_photonCallbackRegistered)
			{
				PhotonNetwork.AddCallbackTarget((object)this);
				_photonCallbackRegistered = true;
			}
		}

		internal void DisablePhotonCallbacks()
		{
			if (_photonCallbackRegistered)
			{
				PhotonNetwork.RemoveCallbackTarget((object)this);
				_photonCallbackRegistered = false;
			}
		}
	}
	internal static class ArenaRaceHooks
	{
		internal static void Install(Harmony harmony)
		{
			Patch(harmony, GameAccess.ArenaRaceStart, "ArenaRaceStartPrefix");
			Patch(harmony, GameAccess.ArenaRaceSpawnTrackPiece, "ArenaRaceSpawnTrackPiecePrefix");
			Patch(harmony, GameAccess.ArenaRaceSpawnVehiclesForPlayers, "ArenaRaceSpawnVehiclesForPlayersPrefix");
			Patch(harmony, GameAccess.ArenaRaceUpdate, "ArenaRaceUpdatePostfix", prefixOnly: false);
			Patch(harmony, GameAccess.ArenaRaceStateRaceActive, "ArenaRaceStateRaceActivePrefix");
			Patch(harmony, GameAccess.ArenaRaceUpdatePlacements, "ArenaRaceUpdatePlacementsPrefix");
			Patch(harmony, GameAccess.ArenaRaceTimerUiOnPlacementsUpdated, "ArenaRaceTimerUiOnPlacementsUpdatedPrefix");
			Patch(harmony, GameAccess.ArenaRaceTimerUiOnPlayerEliminated, "ArenaRaceTimerUiOnPlayerEliminatedPrefix");
			Patch(harmony, GameAccess.TrackPieceStartCountdown, "TrackPieceStartCountdownPrefix");
			Patch(harmony, GameAccess.TrackPieceStartCountdownTimed, "TrackPieceStartCountdownTimedPrefix");
			Patch(harmony, GameAccess.PlayerControllerFixedUpdate, "PlayerControllerFixedUpdatePostfix", prefixOnly: false);
			Patch(harmony, GameAccess.ItemBatteryBatteryLookAt, "ItemBatteryBatteryLookAtPrefix");
		}

		private static void Patch(Harmony harmony, MethodInfo? target, string hookName, bool prefixOnly = true)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			if (target == null)
			{
				EmpressRepoKartArenaPlugin.Log.LogWarning((object)("Skipped Harmony patch '" + hookName + "' because the target method was not found."));
				return;
			}
			HarmonyMethod val = new HarmonyMethod(AccessTools.Method(typeof(ArenaRaceHooks), hookName, (Type[])null, (Type[])null));
			if (prefixOnly)
			{
				harmony.Patch((MethodBase)target, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			else
			{
				harmony.Patch((MethodBase)target, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
		}

		private static void ArenaRaceStartPrefix(ArenaRace __instance)
		{
			if (EmpressRepoKartArenaPlugin.Instance.ModEnabled.Value)
			{
				RepoKartRaceRuntime.PrepareRace(__instance);
			}
		}

		private static bool ArenaRaceSpawnTrackPiecePrefix(ArenaRace __instance)
		{
			if (!EmpressRepoKartArenaPlugin.Instance.ModEnabled.Value)
			{
				return true;
			}
			RepoKartRaceContext context = RepoKartRaceRuntime.GetContext(__instance);
			if (context == null || !context.IsReady)
			{
				return true;
			}
			context.SpawnVirtualTrackPiece();
			return false;
		}

		private static bool ArenaRaceSpawnVehiclesForPlayersPrefix(ArenaRace __instance)
		{
			if (!EmpressRepoKartArenaPlugin.Instance.ModEnabled.Value)
			{
				return true;
			}
			RepoKartRaceContext context = RepoKartRaceRuntime.GetContext(__instance);
			if (context == null || !context.IsReady)
			{
				return true;
			}
			context.SpawnBattleVehiclesForPlayers();
			return false;
		}

		private static void ArenaRaceUpdatePostfix(ArenaRace __instance)
		{
			if (EmpressRepoKartArenaPlugin.Instance.ModEnabled.Value)
			{
				RepoKartRaceRuntime.GetContext(__instance)?.TickRaceIntro();
			}
		}

		private static bool ArenaRaceStateRaceActivePrefix(ArenaRace __instance)
		{
			if (!EmpressRepoKartArenaPlugin.Instance.ModEnabled.Value)
			{
				return true;
			}
			RepoKartRaceContext context = RepoKartRaceRuntime.GetContext(__instance);
			if (context == null || !context.IsReady)
			{
				return true;
			}
			context.TickRaceActive();
			return false;
		}

		private static bool ArenaRaceUpdatePlacementsPrefix(ArenaRace __instance)
		{
			if (!EmpressRepoKartArenaPlugin.Instance.ModEnabled.Value)
			{
				return true;
			}
			RepoKartRaceContext context = RepoKartRaceRuntime.GetContext(__instance);
			if (context == null || !context.IsReady)
			{
				return true;
			}
			RepoKartVanillaLeaderboardCleaner.ClearTimerUiPlacements(force: false);
			return false;
		}

		private static bool ArenaRaceTimerUiOnPlacementsUpdatedPrefix()
		{
			if (!EmpressRepoKartArenaPlugin.Instance.ModEnabled.Value || !RepoKartRaceRuntime.HasActiveBattle)
			{
				return true;
			}
			RepoKartVanillaLeaderboardCleaner.ClearTimerUiPlacements(force: true);
			return false;
		}

		private static bool ArenaRaceTimerUiOnPlayerEliminatedPrefix()
		{
			if (!EmpressRepoKartArenaPlugin.Instance.ModEnabled.Value || !RepoKartRaceRuntime.HasActiveBattle)
			{
				return true;
			}
			RepoKartVanillaLeaderboardCleaner.ClearTimerUiPlacements(force: true);
			return false;
		}

		private static bool TrackPieceStartCountdownPrefix(ArenaRaceTrackPiece __instance)
		{
			if (!EmpressRepoKartArenaPlugin.Instance.ModEnabled.Value)
			{
				return true;
			}
			return !RepoKartVirtualTrackPiece.IsVirtualPiece(__instance);
		}

		private static bool TrackPieceStartCountdownTimedPrefix(ArenaRaceTrackPiece __instance, float _duration)
		{
			if (!EmpressRepoKartArenaPlugin.Instance.ModEnabled.Value)
			{
				return true;
			}
			return !RepoKartVirtualTrackPiece.IsVirtualPiece(__instance);
		}

		private static void PlayerControllerFixedUpdatePostfix(PlayerController __instance)
		{
			if (EmpressRepoKartArenaPlugin.Instance.ModEnabled.Value)
			{
				RepoKartRaceRuntime.SyncLocalControllerToBattleVehicle();
			}
		}

		private static bool ItemBatteryBatteryLookAtPrefix()
		{
			if (EmpressRepoKartArenaPlugin.Instance.ModEnabled.Value)
			{
				return !RepoKartRaceRuntime.HasActiveBattle;
			}
			return true;
		}
	}
	internal static class RepoKartRaceRuntime
	{
		private static readonly Dictionary<int, RepoKartRaceContext> Contexts = new Dictionary<int, RepoKartRaceContext>();

		internal static bool HasActiveBattle
		{
			get
			{
				PruneDeadContexts();
				bool num = Contexts.Values.Any((RepoKartRaceContext context) => context.IsLiveReady);
				if (!num)
				{
					EmpressRepoKartArenaPlugin.Instance.DisablePhotonCallbacks();
				}
				if (!num)
				{
					RepoKartBattleHud.Hide();
				}
				return num;
			}
		}

		internal static void PrepareRace(ArenaRace race)
		{
			EmpressRepoKartArenaPlugin.Instance.EnablePhotonCallbacks();
			PruneDeadContexts();
			int instanceID = ((Object)race).GetInstanceID();
			if (!Contexts.TryGetValue(instanceID, out RepoKartRaceContext value) || !value.IsLiveReady)
			{
				RepoKartRaceContext repoKartRaceContext = new RepoKartRaceContext(race);
				if (repoKartRaceContext.TryPrepare())
				{
					Contexts[instanceID] = repoKartRaceContext;
					RepoKartBattleHud.Ensure();
					EmpressRepoKartArenaPlugin.Log.LogInfo((object)$"Prepared battle arena with {repoKartRaceContext.CheckpointCount} virtual checkpoints, {repoKartRaceContext.StartPoseCount} drop spawn(s), and {repoKartRaceContext.ItemBoxCount} item cube(s).");
				}
			}
		}

		internal static RepoKartRaceContext? GetContext(ArenaRace race)
		{
			if ((Object)(object)race == (Object)null)
			{
				return null;
			}
			Contexts.TryGetValue(((Object)race).GetInstanceID(), out RepoKartRaceContext value);
			return value;
		}

		internal static bool IsVehicleInKartRace(ItemVehicle vehicle)
		{
			if ((Object)(object)vehicle == (Object)null)
			{
				return false;
			}
			foreach (RepoKartRaceContext value in Contexts.Values)
			{
				if (value.ContainsVehicle(vehicle))
				{
					return true;
				}
			}
			return false;
		}

		internal static bool ApplyRandomPickup(ItemVehicle vehicle, Vector3 pickupPosition, int itemBoxIndex)
		{
			return GetContextForVehicle(vehicle)?.TryGiveRandomBattleItem(vehicle, itemBoxIndex) ?? false;
		}

		internal static bool TryBattleHit(ItemVehicle owner, ItemVehicle target, Vector3 hitPosition)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			return GetContextForVehicle(target)?.TryHitBattleVehicle(owner, target, hitPosition) ?? false;
		}

		internal static bool IsLocalBattleVehicle(ItemVehicle vehicle)
		{
			if ((Object)(object)vehicle == (Object)null)
			{
				return false;
			}
			if (!GameAccess.IsMultiplayer())
			{
				return IsVehicleInKartRace(vehicle);
			}
			foreach (RepoKartRaceContext value in Contexts.Values)
			{
				if (value.IsLocalBattleVehicle(vehicle))
				{
					return true;
				}
			}
			return false;
		}

		internal static void ApplyNetworkPickup(ItemVehicle vehicle, RepoKartBattleItem item, int itemBoxIndex)
		{
			using Dictionary<int, RepoKartRaceContext>.ValueCollection.Enumerator enumerator = Contexts.Values.GetEnumerator();
			while (enumerator.MoveNext() && !enumerator.Current.ApplyNetworkPickup(vehicle, item, itemBoxIndex))
			{
			}
		}

		internal static void ApplyNetworkUseItem(ItemVehicle vehicle, RepoKartBattleItem item)
		{
			using Dictionary<int, RepoKartRaceContext>.ValueCollection.Enumerator enumerator = Contexts.Values.GetEnumerator();
			while (enumerator.MoveNext() && !enumerator.Current.ApplyNetworkUseItem(vehicle, item))
			{
			}
		}

		internal static void ApplyNetworkHit(ItemVehicle owner, ItemVehicle target, Vector3 hitPosition, int balloons, float spinDirection)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			using Dictionary<int, RepoKartRaceContext>.ValueCollection.Enumerator enumerator = Contexts.Values.GetEnumerator();
			while (enumerator.MoveNext() && !enumerator.Current.ApplyNetworkHit(owner, target, hitPosition, balloons, spinDirection))
			{
			}
		}

		internal static void SyncLocalControllerToBattleVehicle()
		{
			foreach (RepoKartRaceContext value in Contexts.Values)
			{
				value.SyncLocalControllerToBattleVehicle();
			}
		}

		internal static bool TryGetLocalHeldItem(out RepoKartBattleItem heldItem)
		{
			heldItem = RepoKartBattleItem.None;
			foreach (RepoKartRaceContext value in Contexts.Values)
			{
				if (value.TryGetLocalHeldItem(out heldItem))
				{
					return true;
				}
			}
			return false;
		}

		internal static bool TryGetBattleStandings(out List<RepoKartBattleStanding> standings)
		{
			standings = new List<RepoKartBattleStanding>();
			foreach (RepoKartRaceContext value in Contexts.Values)
			{
				if (value.TryGetBattleStandings(out standings))
				{
					return true;
				}
			}
			return false;
		}

		private static RepoKartRaceContext? GetContextForVehicle(ItemVehicle vehicle)
		{
			if ((Object)(object)vehicle == (Object)null)
			{
				return null;
			}
			foreach (RepoKartRaceContext value in Contexts.Values)
			{
				if (value.ContainsVehicle(vehicle))
				{
					return value;
				}
			}
			return null;
		}

		internal static void ResetForNonBattleScene()
		{
			Contexts.Clear();
			RepoKartBattleMusic.Stop();
			RepoKartBattleHud.Hide();
			EmpressRepoKartArenaPlugin.Instance.DisablePhotonCallbacks();
		}

		private static void PruneDeadContexts()
		{
			if (Contexts.Count == 0)
			{
				return;
			}
			List<int> list = null;
			foreach (KeyValuePair<int, RepoKartRaceContext> context in Contexts)
			{
				if (!context.Value.IsLiveReady)
				{
					if (list == null)
					{
						list = new List<int>();
					}
					list.Add(context.Key);
				}
			}
			if (list == null)
			{
				return;
			}
			foreach (int item in list)
			{
				Contexts.Remove(item);
			}
		}
	}
	internal enum RepoKartBattleItem
	{
		None,
		Shell,
		Banana,
		Boost
	}
	internal readonly struct RepoKartBattleStanding
	{
		internal string PlayerName { get; }

		internal int Balloons { get; }

		internal int Rank { get; }

		internal bool IsLocal { get; }

		internal RepoKartBattleStanding(string playerName, int balloons, int rank, bool isLocal)
		{
			PlayerName = playerName;
			Balloons = balloons;
			Rank = rank;
			IsLocal = isLocal;
		}
	}
	internal sealed class RepoKartBattleHud : MonoBehaviour
	{
		private const float PanelWidth = 350f;

		private const float PanelPadding = 16f;

		private const float StandingRowHeight = 24f;

		private const float StandingRowsTop = 35f;

		private const float StandingPanelTop = 154f;

		private static RepoKartBattleHud? _instance;

		private Text? _itemValue;

		private Text? _standingTitle;

		private RectTransform? _standingsPanel;

		private readonly List<Text> _standingRows = new List<Text>();

		private Font? _font;

		internal static void Ensure()
		{
			//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_002e: Expected O, but got Unknown
			if ((Object)(object)_instance != (Object)null)
			{
				((Component)_instance).gameObject.SetActive(true);
				return;
			}
			GameObject val = new GameObject("EmpressRepoKartArena.BattleHud");
			Object.DontDestroyOnLoad((Object)val);
			_instance = val.AddComponent<RepoKartBattleHud>();
			_instance.Build();
		}

		internal static void Hide()
		{
			if ((Object)(object)_instance != (Object)null)
			{
				((Component)_instance).gameObject.SetActive(false);
			}
		}

		private void Build()
		{
			//IL_0049: 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_0080: 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_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: 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_00cd: 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_00f8: 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_0132: 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_0149: 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_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			_font = Resources.GetBuiltinResource<Font>("Arial.ttf");
			Canvas obj = ((Component)this).gameObject.AddComponent<Canvas>();
			obj.renderMode = (RenderMode)0;
			obj.sortingOrder = 32767;
			CanvasScaler obj2 = ((Component)this).gameObject.AddComponent<CanvasScaler>();
			obj2.uiScaleMode = (ScaleMode)1;
			obj2.referenceResolution = new Vector2(1920f, 1080f);
			obj2.matchWidthOrHeight = 0.5f;
			((Component)this).gameObject.AddComponent<GraphicRaycaster>();
			RectTransform component = ((Component)this).gameObject.GetComponent<RectTransform>();
			component.anchorMin = Vector2.zero;
			component.anchorMax = Vector2.one;
			component.offsetMin = Vector2.zero;
			component.offsetMax = Vector2.zero;
			RectTransform parent = CreatePanel("ItemPanel", new Vector2(1f, 1f), new Vector2(-28f, -72f), new Vector2(350f, 72f));
			CreateText(parent, "ITEM", new Vector2(-16f, -9f), new Vector2(318f, 20f), 13, (FontStyle)1, new Color(1f, 0.92f, 0.25f, 1f), (TextAnchor)4);
			_itemValue = CreateText(parent, "NO ITEM", new Vector2(-16f, -36f), new Vector2(318f, 34f), 25, (FontStyle)1, Color.white, (TextAnchor)4);
			_standingsPanel = CreatePanel("StandingsPanel", new Vector2(1f, 1f), new Vector2(-28f, -154f), new Vector2(350f, CalculateStandingsPanelHeight(2)));
			_standingTitle = CreateText(_standingsPanel, "BALLOONS", new Vector2(-16f, -9f), new Vector2(318f, 20f), 13, (FontStyle)1, new Color(1f, 0.92f, 0.25f, 1f), (TextAnchor)4);
			EnsureStandingRows(2);
		}

		private void LateUpdate()
		{
			//IL_0106: 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)
			if (!RepoKartRaceRuntime.HasActiveBattle)
			{
				((Component)this).gameObject.SetActive(false);
				return;
			}
			if ((Object)(object)_itemValue != (Object)null)
			{
				RepoKartRaceRuntime.TryGetLocalHeldItem(out var heldItem);
				_itemValue.text = ((heldItem == RepoKartBattleItem.None) ? "NO ITEM" : heldItem.ToString().ToUpperInvariant());
			}
			if ((Object)(object)_standingTitle != (Object)null)
			{
				_standingTitle.text = "BALLOONS";
			}
			if (!RepoKartRaceRuntime.TryGetBattleStandings(out List<RepoKartBattleStanding> standings))
			{
				standings = new List<RepoKartBattleStanding>();
			}
			EnsureStandingRows(standings.Count);
			ResizeStandingsPanel(standings.Count);
			for (int i = 0; i < _standingRows.Count; i++)
			{
				Text val = _standingRows[i];
				if (i >= standings.Count)
				{
					((Component)val).gameObject.SetActive(false);
					val.text = string.Empty;
					continue;
				}
				((Component)val).gameObject.SetActive(true);
				RepoKartBattleStanding standing = standings[i];
				((Graphic)val).color = (Color)(standing.IsLocal ? new Color(0.55f, 1f, 0.55f, 1f) : Color.white);
				val.text = FormatStanding(standing);
			}
		}

		private void EnsureStandingRows(int count)
		{
			//IL_0035: 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_004c: Unknown result type (might be due to invalid IL or missing references)
			int num = Mathf.Max(1, count);
			while (_standingRows.Count < num)
			{
				int count2 = _standingRows.Count;
				Text val = CreateText(_standingsPanel, string.Empty, new Vector2(-16f, -35f - (float)count2 * 24f), new Vector2(318f, 24f), 18, (FontStyle)1, Color.white, (TextAnchor)4);
				((Component)val).gameObject.SetActive(false);
				_standingRows.Add(val);
			}
		}

		private void ResizeStandingsPanel(int rowCount)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_standingsPanel == (Object)null))
			{
				float num = CalculateStandingsPanelHeight(rowCount);
				if (!Mathf.Approximately(_standingsPanel.sizeDelta.y, num))
				{
					_standingsPanel.sizeDelta = new Vector2(350f, num);
				}
			}
		}

		private static float CalculateStandingsPanelHeight(int rowCount)
		{
			return Mathf.Max(96f, 35f + (float)Mathf.Max(1, rowCount) * 24f + 18f);
		}

		private RectTransform CreatePanel(string name, Vector2 anchor, Vector2 anchoredPosition, Vector2 size)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0020: 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_0038: 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_004a: 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)
			GameObject val = new GameObject(name);
			val.transform.SetParent(((Component)this).transform, false);
			RectTransform obj = val.AddComponent<RectTransform>();
			obj.anchorMin = anchor;
			obj.anchorMax = anchor;
			obj.pivot = new Vector2(1f, 1f);
			obj.anchoredPosition = anchoredPosition;
			obj.sizeDelta = size;
			Image obj2 = val.AddComponent<Image>();
			((Graphic)obj2).color = new Color(0f, 0f, 0f, 0.62f);
			((Graphic)obj2).raycastTarget = false;
			val.AddComponent<RectMask2D>();
			return obj;
		}

		private Text CreateText(RectTransform parent, string text, Vector2 anchoredPosition, Vector2 size, int fontSize, FontStyle style, Color color, TextAnchor anchor)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: 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_009e: 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)
			GameObject val = new GameObject(text.Replace(" ", string.Empty));
			val.transform.SetParent((Transform)(object)parent, false);
			RectTransform obj = val.AddComponent<RectTransform>();
			obj.anchorMin = new Vector2(1f, 1f);
			obj.anchorMax = new Vector2(1f, 1f);
			obj.pivot = new Vector2(1f, 1f);
			obj.anchoredPosition = anchoredPosition;
			obj.sizeDelta = size;
			Text obj2 = val.AddComponent<Text>();
			obj2.text = text;
			obj2.font = _font;
			obj2.fontSize = fontSize;
			obj2.fontStyle = style;
			((Graphic)obj2).color = color;
			obj2.alignment = anchor;
			((Graphic)obj2).raycastTarget = false;
			obj2.horizontalOverflow = (HorizontalWrapMode)1;
			obj2.verticalOverflow = (VerticalWrapMode)1;
			return obj2;
		}

		private static string FormatStanding(RepoKartBattleStanding standing)
		{
			string arg = CompactName(standing.PlayerName, 20);
			return $"{Ordinal(standing.Rank)} {arg}  x{standing.Balloons}";
		}

		private static string CompactName(string value, int maxLength)
		{
			if (string.IsNullOrWhiteSpace(value))
			{
				return "Player";
			}
			string text = value.Trim();
			if (text.Length <= maxLength)
			{
				return text;
			}
			return text[..Mathf.Max(1, maxLength - 3)].TrimEnd() + "...";
		}

		private static string Ordinal(int value)
		{
			int num = Mathf.Abs(value);
			int num2 = num % 100;
			if (num2 >= 11 && num2 <= 13)
			{
				return value + "th";
			}
			return (num % 10) switch
			{
				1 => value + "st", 
				2 => value + "nd", 
				3 => value + "rd", 
				_ => value + "th", 
			};
		}
	}
	internal static class RepoKartVanillaLeaderboardCleaner
	{
		private static int _clearedTimerUiId;

		internal static void ClearTimerUiPlacements(bool force)
		{
			ArenaRaceTimerUI arenaRaceTimerUiInstance = GameAccess.GetArenaRaceTimerUiInstance();
			if ((Object)(object)arenaRaceTimerUiInstance == (Object)null)
			{
				_clearedTimerUiId = 0;
				return;
			}
			int instanceID = ((Object)arenaRaceTimerUiInstance).GetInstanceID();
			if (force || _clearedTimerUiId != instanceID)
			{
				_clearedTimerUiId = instanceID;
				ClearTextObject(GameAccess.ArenaRaceTimerUiAllPlacementsText?.GetValue(arenaRaceTimerUiInstance));
				ClearCollection(GameAccess.ArenaRaceTimerUiPlacementCurrentOrder?.GetValue(arenaRaceTimerUiInstance));
				ClearCollection(GameAccess.ArenaRaceTimerUiPlacementPrevious?.GetValue(arenaRaceTimerUiInstance));
				ClearCollection(GameAccess.ArenaRaceTimerUiPlacementGlitchOverrides?.GetValue(arenaRaceTimerUiInstance));
				ClearCollection(GameAccess.ArenaRaceTimerUiDeathGlitchActive?.GetValue(arenaRaceTimerUiInstance));
			}
		}

		private static void ClearTextObject(object? textObject)
		{
			if (textObject == null)
			{
				return;
			}
			try
			{
				AccessTools.Property(textObject.GetType(), "text")?.SetValue(textObject, string.Empty, null);
				Behaviour val = (Behaviour)((textObject is Behaviour) ? textObject : null);
				if (val != null)
				{
					val.enabled = false;
				}
			}
			catch
			{
			}
		}

		private static void ClearCollection(object? collection)
		{
			if (collection == null)
			{
				return;
			}
			try
			{
				AccessTools.Method(collection.GetType(), "Clear", Type.EmptyTypes, (Type[])null)?.Invoke(collection, null);
			}
			catch
			{
			}
		}
	}
	internal static class RepoKartBattleNetwork
	{
		private const byte EventCode = 179;

		private const byte PickupMessage = 1;

		private const byte UseItemMessage = 2;

		private const byte HitMessage = 3;

		internal static void BroadcastPickup(ItemVehicle vehicle, RepoKartBattleItem item, int itemBoxIndex)
		{
			int viewId = GetViewId(vehicle);
			if (viewId >= 0)
			{
				Raise(new object[4]
				{
					(byte)1,
					viewId,
					(int)item,
					itemBoxIndex
				});
			}
		}

		internal static void BroadcastUseItem(ItemVehicle vehicle, RepoKartBattleItem item)
		{
			int viewId = GetViewId(vehicle);
			if (viewId >= 0)
			{
				Raise(new object[3]
				{
					(byte)2,
					viewId,
					(int)item
				});
			}
		}

		internal static void BroadcastHit(ItemVehicle owner, ItemVehicle target, Vector3 hitPosition, int balloons, float spinDirection)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			int viewId = GetViewId(owner);
			int viewId2 = GetViewId(target);
			if (viewId >= 0 && viewId2 >= 0)
			{
				Raise(new object[6]
				{
					(byte)3,
					viewId,
					viewId2,
					balloons,
					hitPosition,
					spinDirection
				});
			}
		}

		internal static void HandlePhotonEvent(EventData photonEvent)
		{
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: 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_016e: Unknown result type (might be due to invalid IL or missing references)
			if (photonEvent.Code != 179 || !(photonEvent.CustomData is object[] array) || array.Length == 0)
			{
				return;
			}
			try
			{
				switch (Convert.ToInt32(array[0], CultureInfo.InvariantCulture))
				{
				case 1:
					if (array.Length >= 4)
					{
						ItemVehicle val5 = FindVehicle(Convert.ToInt32(array[1], CultureInfo.InvariantCulture));
						RepoKartBattleItem item2 = (RepoKartBattleItem)Convert.ToInt32(array[2], CultureInfo.InvariantCulture);
						int itemBoxIndex = Convert.ToInt32(array[3], CultureInfo.InvariantCulture);
						if ((Object)(object)val5 != (Object)null)
						{
							RepoKartRaceRuntime.ApplyNetworkPickup(val5, item2, itemBoxIndex);
						}
					}
					break;
				case 2:
					if (array.Length >= 3)
					{
						ItemVehicle val4 = FindVehicle(Convert.ToInt32(array[1], CultureInfo.InvariantCulture));
						RepoKartBattleItem item = (RepoKartBattleItem)Convert.ToInt32(array[2], CultureInfo.InvariantCulture);
						if ((Object)(object)val4 != (Object)null)
						{
							RepoKartRaceRuntime.ApplyNetworkUseItem(val4, item);
						}
					}
					break;
				case 3:
					if (array.Length >= 6)
					{
						ItemVehicle val = FindVehicle(Convert.ToInt32(array[1], CultureInfo.InvariantCulture));
						ItemVehicle val2 = FindVehicle(Convert.ToInt32(array[2], CultureInfo.InvariantCulture));
						int balloons = Convert.ToInt32(array[3], CultureInfo.InvariantCulture);
						Vector3 hitPosition = ((array[4] is Vector3 val3) ? val3 : Vector3.zero);
						float spinDirection = Convert.ToSingle(array[5], CultureInfo.InvariantCulture);
						if ((Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null)
						{
							RepoKartRaceRuntime.ApplyNetworkHit(val, val2, hitPosition, balloons, spinDirection);
						}
					}
					break;
				}
			}
			catch (Exception ex)
			{
				EmpressRepoKartArenaPlugin.Log.LogWarning((object)("Ignored malformed battle sync event: " + ex.Message));
			}
		}

		private static void Raise(object[] payload)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			if (PhotonNetwork.InRoom)
			{
				RaiseEventOptions val = new RaiseEventOptions
				{
					Receivers = (ReceiverGroup)0
				};
				PhotonNetwork.RaiseEvent((byte)179, (object)payload, val, SendOptions.SendReliable);
			}
		}

		private static int GetViewId(ItemVehicle vehicle)
		{
			if (!Object.op_Implicit((Object)(object)vehicle))
			{
				return -1;
			}
			PhotonView component = ((Component)vehicle).GetComponent<PhotonView>();
			if (!((Object)(object)component != (Object)null))
			{
				return -1;
			}
			return component.ViewID;
		}

		private static ItemVehicle? FindVehicle(int viewId)
		{
			if (viewId < 0)
			{
				return null;
			}
			PhotonView val = PhotonView.Find(viewId);
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return ((Component)val).GetComponent<ItemVehicle>();
		}
	}
	internal static class RepoKartBattleAudio
	{
		private static AudioClip? _pickupClip;

		private static AudioClip? _useClip;

		private static AudioClip? _hitClip;

		internal static void PlayPickup(Vector3 position)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			if (_pickupClip == null)
			{
				_pickupClip = CreateSweepClip("EmpressRepoKartArena.PickupItem", 880f, 1560f, 0.13f);
			}
			AudioSource.PlayClipAtPoint(_pickupClip, position, 0.7f);
		}

		internal static void PlayUse(Vector3 position)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			if (_useClip == null)
			{
				_useClip = CreateSweepClip("EmpressRepoKartArena.UseItem", 740f, 1280f, 0.11f);
			}
			AudioSource.PlayClipAtPoint(_useClip, position, 0.65f);
		}

		internal static void PlayHit(Vector3 position)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			if (_hitClip == null)
			{
				_hitClip = CreateSweepClip("EmpressRepoKartArena.BalloonHit", 260f, 110f, 0.16f);
			}
			AudioSource.PlayClipAtPoint(_hitClip, position, 0.8f);
		}

		private static AudioClip CreateSweepClip(string name, float startFrequency, float endFrequency, float duration)
		{
			int num = Mathf.Max(1, Mathf.RoundToInt(22050f * duration));
			float[] array = new float[num];
			for (int i = 0; i < num; i++)
			{
				float num2 = (float)i / (float)num;
				float num3 = Mathf.Lerp(startFrequency, endFrequency, num2);
				float num4 = Mathf.Sin(num2 * MathF.PI);
				array[i] = Mathf.Sin(num2 * duration * num3 * MathF.PI * 2f) * num4 * 0.45f;
			}
			AudioClip obj = AudioClip.Create(name, num, 1, 22050, false);
			obj.SetData(array, 0);
			return obj;
		}
	}
	internal static class RepoKartBattleLighting
	{
		internal static void Apply(Transform mapRoot)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: 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)
			if (EmpressRepoKartArenaPlugin.Instance.RemoveFog.Value)
			{
				RenderSettings.fog = false;
				RenderSettings.fogDensity = 0f;
			}
			if (EmpressRepoKartArenaPlugin.Instance.AddMapLight.Value)
			{
				Transform val = mapRoot.Find("EmpressRepoKartArena.DirectionalLight");
				GameObject val2 = (GameObject)(((Object)(object)val != (Object)null) ? ((object)((Component)val).gameObject) : ((object)new GameObject("EmpressRepoKartArena.DirectionalLight")));
				val2.transform.SetParent(mapRoot, true);
				val2.transform.rotation = Quaternion.Euler(50f, -35f, 0f);
				Light val3 = val2.GetComponent<Light>();
				if ((Object)(object)val3 == (Object)null)
				{
					val3 = val2.AddComponent<Light>();
				}
				val3.type = (LightType)1;
				val3.intensity = 1.25f;
				val3.color = new Color(1f, 0.96f, 0.88f, 1f);
				val3.shadows = (LightShadows)2;
				EmpressRepoKartArenaPlugin.Log.LogInfo((object)"Applied battle map lighting and fog settings.");
			}
		}
	}
	internal sealed class RepoKartBattleMusic : MonoBehaviour
	{
		private const string XorbinFileName = "BattleMusic.xorbin";

		private static readonly byte[] XorKey = new byte[7] { 69, 77, 80, 82, 69, 83, 83 };

		private static RepoKartBattleMusic? _instance;

		private AudioSource? _source;

		private bool _loading;

		internal static void EnsurePlaying(Transform? parent)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			if (!EmpressRepoKartArenaPlugin.Instance.BattleMusicEnabled.Value)
			{
				Stop();
				return;
			}
			if ((Object)(object)_instance == (Object)null)
			{
				GameObject val = new GameObject("EmpressRepoKartArena.BattleMusic");
				if ((Object)(object)parent != (Object)null)
				{
					val.transform.SetParent(parent, false);
				}
				_instance = val.AddComponent<RepoKartBattleMusic>();
			}
			_instance.StartMusic();
		}

		internal static void Stop()
		{
			if ((Object)(object)_instance != (Object)null && (Object)(object)_instance._source != (Object)null)
			{
				_instance._source.Stop();
			}
		}

		private void StartMusic()
		{
			if ((Object)(object)_source == (Object)null)
			{
				_source = ((Component)this).gameObject.AddComponent<AudioSource>();
				_source.loop = true;
				_source.spatialBlend = 0f;
				_source.playOnAwake = false;
			}
			_source.volume = EmpressRepoKartArenaPlugin.Instance.BattleMusicVolume.Value;
			if ((Object)(object)_source.clip != (Object)null)
			{
				if (!_source.isPlaying)
				{
					_source.Play();
				}
			}
			else if (!_loading)
			{
				((MonoBehaviour)this).StartCoroutine(LoadMusicCoroutine());
			}
		}

		private IEnumerator LoadMusicCoroutine()
		{
			_loading = true;
			string text = TryDecodeMusic();
			if (string.IsNullOrWhiteSpace(text))
			{
				_loading = false;
				yield break;
			}
			UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(new Uri(text).AbsoluteUri, (AudioType)13);
			try
			{
				yield return request.SendWebRequest();
				if ((int)request.result != 1)
				{
					EmpressRepoKartArenaPlugin.Log.LogWarning((object)("Battle music load failed: " + request.error));
					_loading = false;
					yield break;
				}
				AudioClip content = DownloadHandlerAudioClip.GetContent(request);
				if ((Object)(object)_source != (Object)null && (Object)(object)content != (Object)null)
				{
					_source.clip = content;
					_source.volume = EmpressRepoKartArenaPlugin.Instance.BattleMusicVolume.Value;
					_source.Play();
					EmpressRepoKartArenaPlugin.Log.LogInfo((object)"Battle music started from XORBIN.");
				}
				_loading = false;
			}
			finally
			{
				((IDisposable)request)?.Dispose();
			}
		}

		private static string? TryDecodeMusic()
		{
			try
			{
				string text = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)EmpressRepoKartArenaPlugin.Instance).Info.Location) ?? Paths.PluginPath, "BattleMusic.xorbin");
				if (!File.Exists(text))
				{
					EmpressRepoKartArenaPlugin.Log.LogWarning((object)("Battle music XORBIN missing beside DLL: " + text));
					return null;
				}
				byte[] array = File.ReadAllBytes(text);
				for (int i = 0; i < array.Length; i++)
				{
					array[i] ^= XorKey[i % XorKey.Length];
				}
				string text2 = Path.Combine(Path.GetTempPath(), "EmpressRepoKartArena");
				Directory.CreateDirectory(text2);
				string text3 = Path.Combine(text2, "BattleMusic.mp3");
				File.WriteAllBytes(text3, array);
				return text3;
			}
			catch (Exception ex)
			{
				EmpressRepoKartArenaPlugin.Log.LogWarning((object)("Battle music decode failed: " + ex.Message));
				return null;
			}
		}
	}
	internal sealed class RepoKartBattlePlayerState
	{
		internal int Balloons = 3;

		internal RepoKartBattleItem HeldItem;

		internal float HitCooldown;

		internal float SpinTimer;

		internal float SpinDirection = 1f;

		internal readonly List<GameObject> BalloonVisuals = new List<GameObject>();
	}
	internal readonly struct RepoKartStartPose
	{
		internal Vector3 Position { get; }

		internal Quaternion Rotation { get; }

		internal RepoKartStartPose(Vector3 position, Quaternion rotation)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: 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)
			Position = position;
			Rotation = rotation;
		}
	}
	internal sealed class RepoKartRaceContext
	{
		private readonly ArenaRace _race;

		private readonly List<Vector3> _checkpoints = new List<Vector3>();

		private readonly List<RepoKartStartPose> _startPoses = new List<RepoKartStartPose>();

		private readonly List<RepoKartItemBox> _itemBoxes = new List<RepoKartItemBox>();

		private readonly Dictionary<ItemVehicle, int> _startGridVehicleIndices = new Dictionary<ItemVehicle, int>();

		private readonly Dictionary<ItemVehicle, RepoKartBattlePlayerState> _battlePlayers = new Dictionary<ItemVehicle, RepoKartBattlePlayerState>();

		private readonly Dictionary<PlayerAvatar, float> _nextPlayerSpawnSync = new Dictionary<PlayerAvatar, float>();

		private Transform? _root;

		private Transform? _virtualRoot;

		private bool _winnerSet;

		private bool _introPlacementLogged;

		private bool _battleStartLogged;

		private bool _directBattleStarted;

		private float _nextVanillaCleanupTime;

		internal bool IsReady { get; private set; }

		internal bool IsLiveReady
		{
			get
			{
				if (IsReady && Object.op_Implicit((Object)(object)_race))
				{
					return Object.op_Implicit((Object)(object)_root);
				}
				return false;
			}
		}

		internal int CheckpointCount => _checkpoints.Count;

		internal int FinishPieceIndex { get; private set; }

		internal int ItemBoxCount => _itemBoxes.Count;

		internal int StartPoseCount => _startPoses.Count;

		internal RepoKartRaceContext(ArenaRace race)
		{
			_race = race;
		}

		internal bool TryPrepare()
		{
			//IL_0028: 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_004b: 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_005b: 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_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: 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_006e: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Transform val = GameAccess.TrackSpawnOrigin.Invoke(_race);
				if ((Object)(object)val == (Object)null)
				{
					val = ((Component)_race).transform;
				}
				Quaternion val2 = val.rotation * Quaternion.Euler(0f, EmpressRepoKartArenaPlugin.Instance.MapYawOffset.Value, 0f);
				Vector3 value = EmpressRepoKartArenaPlugin.Instance.MapOffset.Value;
				GameObject val3 = RepoKartBundleMapLoader.InstantiateMap(val.position + val2 * value, val2);
				_root = val3.transform;
				LogMapBounds(_root);
				RepoKartBattleLighting.Apply(_root);
				DisableVanillaExtractorGeometry(force: true);
				_virtualRoot = new GameObject("EmpressRepoKartArena.VirtualRacePieces").transform;
				_virtualRoot.SetParent(_root, true);
				_checkpoints.AddRange(RepoKartPathDetector.DetectCheckpoints(_root));
				if (_checkpoints.Count < 4)
				{
					throw new InvalidOperationException("Bundle battle map did not produce enough checkpoint markers.");
				}
				_startPoses.AddRange(RepoKartPathDetector.DetectStartPoses(_root));
				if (_startPoses.Count == 0)
				{
					throw new InvalidOperationException("Bundle battle map did not produce start markers.");
				}
				RepoKartStartPose repoKartStartPose = _startPoses[0];
				ManualLogSource log = EmpressRepoKartArenaPlugin.Log;
				string[] obj = new string[5] { "Battle drop spawn[0] at ", null, null, null, null };
				Vector3 val4 = repoKartStartPose.Position;
				obj[1] = ((Vector3)(ref val4)).ToString("F1");
				obj[2] = " with rotation ";
				Quaternion rotation = repoKartStartPose.Rotation;
				val4 = ((Quaternion)(ref rotation)).eulerAngles;
				obj[3] = ((Vector3)(ref val4)).ToString("F1");
				obj[4] = ".";
				log.LogInfo((object)string.Concat(obj));
				FinishPieceIndex = 536870911;
				ConfigureRaceFields();
				BuildItemBoxes();
				IsReady = true;
				return true;
			}
			catch (Exception arg)
			{
				EmpressRepoKartArenaPlugin.Log.LogError((object)$"Battle arena prepare failed: {arg}");
				return false;
			}
		}

		internal void SpawnVirtualTrackPiece()
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: 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_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_0073: 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_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: 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_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Expected O, but got Unknown
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: 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_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: 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)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			if (IsReady && !((Object)(object)_virtualRoot == (Object)null) && _checkpoints.Count != 0)
			{
				int num = GameAccess.TotalPiecesSpawned.Invoke(_race);
				int num2 = Mod(num, _checkpoints.Count);
				int num3 = Mod(num - 1, _checkpoints.Count);
				Vector3 val = _checkpoints[num2];
				Vector3 val2 = ((num == 0) ? (val - SegmentForward(num3, num2) * 12f) : _checkpoints[num3]);
				Vector3 val3 = val - val2;
				val3.y = 0f;
				if (((Vector3)(ref val3)).sqrMagnitude < 0.01f)
				{
					val3 = Vector3.forward;
				}
				((Vector3)(ref val3)).Normalize();
				GameObject val4 = new GameObject($"EmpressRepoKartArena.VirtualPiece.{num:000}");
				val4.transform.SetParent(_virtualRoot, true);
				val4.transform.position = val2;
				val4.transform.rotation = Quaternion.LookRotation(val3, Vector3.up);
				ArenaRaceTrackPiece val5 = val4.AddComponent<ArenaRaceTrackPiece>();
				val4.AddComponent<RepoKartVirtualTrackPiece>();
				GameAccess.TrackPieceIndex.Invoke(val5) = num;
				GameAccess.TrackPieceMinimumClearanceTime.Invoke(val5) = 999999f;
				GameAccess.TrackPieceCountdownDuration.Invoke(val5) = 999999f;
				GameAccess.TrackPieceCountdownTimer.Invoke(val5) = 999999f;
				GameObject val6 = new GameObject("End");
				val6.transform.SetParent(val4.transform, true);
				val6.transform.position = val;
				val6.transform.rotation = Quaternion.LookRotation(val3, Vector3.up);
				val6.AddComponent<ArenaRaceTrackPieceEnd>();
				GameAccess.RegisterTrackPiece(_race, val5);
				GameAccess.TrackPieceRegistered.Invoke(val5) = true;
			}
		}

		internal bool SpawnBattleVehiclesForPlayers()
		{
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: 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_00eb: 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_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: 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_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: 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)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			if (!IsReady)
			{
				return false;
			}
			if (!GameAccess.IsMasterClientOrSingleplayer())
			{
				EmpressRepoKartArenaPlugin.Log.LogInfo((object)"Client skipped vanilla Arena Race vehicle spawning; waiting for host battle vehicles.");
				return true;
			}
			List<PlayerAvatar> list = GameAccess.PlayerGetAll();
			if (list == null || list.Count == 0)
			{
				return false;
			}
			Dictionary<PlayerAvatar, ItemVehicle> dictionary = GameAccess.PlayerVehicleMap.Invoke(_race);
			Dictionary<ItemVehicle, int> dictionary2 = GameAccess.VehicleCurrentPiece.Invoke(_race);
			List<ItemVehicle> list2 = GameAccess.RaceVehicles.Invoke(_race);
			if (dictionary == null || dictionary2 == null || list2 == null)
			{
				return false;
			}
			if (GameAccess.IsMultiplayer())
			{
				int[] array = new int[list.Count];
				int[] array2 = new int[list.Count];
				for (int i = 0; i < list.Count; i++)
				{
					PlayerAvatar val = list[i];
					RepoKartStartPose startGridPose = GetStartGridPose(i);
					Vector3 val2 = startGridPose.Position + Vector3.up * 1.2f;
					PhotonView component = PhotonNetwork.InstantiateRoomObject("Items/Item Vehicle Semiscooter Small", val2, startGridPose.Rotation, (byte)0, (object[])null).GetComponent<PhotonView>();
					array[i] = (((Object)(object)component != (Object)null) ? component.ViewID : (-1));
					PhotonView val3 = GameAccess.PlayerPhotonView.Invoke(val);
					array2[i] = (((Object)(object)val3 != (Object)null) ? val3.ViewID : (-1));
					SpawnPlayerNearVehicle(val, null, val2, startGridPose.Rotation, onlyIfFar: false);
				}
				PhotonView val4 = GameAccess.RacePhotonView.Invoke(_race);
				if ((Object)(object)val4 != (Object)null)
				{
					val4.RPC("AssignVehiclesRPC", (RpcTarget)0, new object[2] { array, array2 });
				}
				StartDirectBattleOnMap();
				EmpressRepoKartArenaPlugin.Log.LogInfo((object)$"Spawned {list.Count} REPO battle vehicle(s) directly at bundle drop spawns.");
				return true;
			}
			GameObject val5 = Resources.Load<GameObject>("Items/Item Vehicle Semiscooter Small");
			if ((Object)(object)val5 == (Object)null)
			{
				return false;
			}
			for (int j = 0; j < list.Count; j++)
			{
				PlayerAvatar val6 = list[j];
				RepoKartStartPose startGridPose2 = GetStartGridPose(j);
				Vector3 val7 = startGridPose2.Position + Vector3.up * 1.2f;
				ItemVehicle component2 = Object.Instantiate<GameObject>(val5, val7, startGridPose2.Rotation).GetComponent<ItemVehicle>();
				if (Object.op_Implicit((Object)(object)component2))
				{
					list2.Add(component2);
					dictionary[val6] = component2;
					dictionary2[component2] = 0;
					_startGridVehicleIndices[component2] = j;
					PlaceVehicleAtStartGrid(val6, component2, j, dictionary2, spawnPlayer: true);
				}
			}
			StartDirectBattleOnMap();
			EmpressRepoKartArenaPlugin.Log.LogInfo((object)$"Spawned {list.Count} singleplayer REPO battle vehicle(s) directly at bundle drop spawns.");
			return true;
		}

		internal void TickRaceActive()
		{
			EnsureAssignedBattleVehiclesRegistered();
			TryPlaceVehiclesAtStartGrid();
			if (!_winnerSet && (int)GameAccess.CurrentState.Invoke(_race) == 4)
			{
				if (!_battleStartLogged)
				{
					_battleStartLogged = true;
					EmpressRepoKartArenaPlugin.Log.LogInfo((object)"Battle mode active: 3 balloons, one held item, press X to fire.");
				}
				TickBattlePlayers();
				UpdateBattleRankingPieces();
				DisableVanillaExtractorGeometry(force: false);
				SyncStrandedPlayersToVehicles();
				HandleLocalBattleInput();
				CheckBattleWinner();
			}
		}

		private void TickBattlePlayers()
		{
			foreach (KeyValuePair<ItemVehicle, RepoKartBattlePlayerState> battlePlayer in _battlePlayers)
			{
				ItemVehicle key = battlePlayer.Key;
				RepoKartBattlePlayerState value = battlePlayer.Value;
				if (value.HitCooldown > 0f)
				{
					value.HitCooldown -= Time.deltaTime;
				}
				if (value.SpinTimer > 0f && Object.op_Implicit((Object)(object)key))
				{
					value.SpinTimer -= Time.deltaTime;
					ApplySpinTorque(key, value.SpinDirection, continuous: true);
				}
			}
		}

		private void HandleLocalBattleInput()
		{
			if (Input.GetKeyDown((KeyCode)120) && Object.op_Implicit((Object)(object)GameAccess.PlayerAvatarLocal()) && TryFindLocalBattleVehicle(out ItemVehicle vehicle) && Object.op_Implicit((Object)(object)vehicle))
			{
				FireHeldBattleItem(vehicle);
			}
		}

		private void CheckBattleWinner()
		{
			Dictionary<PlayerAvatar, ItemVehicle> dictionary = GameAccess.PlayerVehicleMap.Invoke(_race);
			if (dictionary == null || dictionary.Count <= 1)
			{
				return;
			}
			PlayerAvatar val = null;
			int num = 0;
			foreach (KeyValuePair<PlayerAvatar, ItemVehicle> item in dictionary)
			{
				if (Object.op_Implicit((Object)(object)item.Key) && !GameAccess.PlayerIsDisabled.Invoke(item.Key) && Object.op_Implicit((Object)(object)item.Value) && _battlePlayers.TryGetValue(item.Value, out RepoKartBattlePlayerState value) && value.Balloons > 0)
				{
					num++;
					val = item.Key;
				}
			}
			if (num == 1 && (Object)(object)val != (Object)null)
			{
				CrownWinner(val);
			}
		}

		internal bool TryGiveRandomBattleItem(ItemVehicle vehicle, int itemBoxIndex)
		{
			EnsureAssignedBattleVehiclesRegistered();
			if (!Object.op_Implicit((Object)(object)vehicle) || !ContainsVehicle(vehicle) || (GameAccess.IsMultiplayer() && !IsLocalBattleVehicle(vehicle)))
			{
				return false;
			}
			RepoKartBattlePlayerState repoKartBattlePlayerState = EnsureBattlePlayerState(vehicle);
			if (repoKartBattlePlayerState.Balloons <= 0)
			{
				return false;
			}
			if (repoKartBattlePlayerState.HeldItem != 0)
			{
				return false;
			}
			RepoKartBattleItem item = Random.Range(0, 3) switch
			{
				1 => RepoKartBattleItem.Banana, 
				0 => RepoKartBattleItem.Shell, 
				_ => RepoKartBattleItem.Boost, 
			};
			ApplyPickupState(vehicle, item, itemBoxIndex, playSound: true, logPickup: true);
			if (GameAccess.IsMultiplayer())
			{
				RepoKartBattleNetwork.BroadcastPickup(vehicle, item, itemBoxIndex);
			}
			return true;
		}

		internal bool TryGetLocalHeldItem(out RepoKartBattleItem heldItem)
		{
			heldItem = RepoKartBattleItem.None;
			if (!IsReady)
			{
				return false;
			}
			if (!TryFindLocalBattleVehicle(out ItemVehicle vehicle) || !Object.op_Implicit((Object)(object)vehicle))
			{
				return false;
			}
			RepoKartBattlePlayerState repoKartBattlePlayerState = EnsureBattlePlayerState(vehicle);
			heldItem = repoKartBattlePlayerState.HeldItem;
			return true;
		}

		internal bool TryGetBattleStandings(out List<RepoKartBattleStanding> standings)
		{
			standings = new List<RepoKartBattleStanding>();
			if (!IsReady)
			{
				return false;
			}
			EnsureAssignedBattleVehiclesRegistered();
			Dictionary<PlayerAvatar, ItemVehicle> dictionary = GameAccess.PlayerVehicleMap.Invoke(_race);
			if (dictionary == null || dictionary.Count == 0)
			{
				return false;
			}
			PlayerAvatar val = GameAccess.PlayerAvatarLocal();
			List<(string, int, bool)> list = new List<(string, int, bool)>();
			foreach (KeyValuePair<PlayerAvatar, ItemVehicle> item2 in dictionary)
			{
				PlayerAvatar key = item2.Key;
				ItemVehicle value = item2.Value;
				if (Object.op_Implicit((Object)(object)key) && Object.op_Implicit((Object)(object)value))
				{
					RepoKartBattlePlayerState repoKartBattlePlayerState = EnsureBattlePlayerState(value);
					string playerDisplayName = GameAccess.GetPlayerDisplayName(key);
					bool item = Object.op_Implicit((Object)(object)val) && (Object)(object)key == (Object)(object)val;
					list.Add((playerDisplayName, Mathf.Clamp(repoKartBattlePlayerState.Balloons, 0, 3), item));
				}
			}
			if (list.Count == 0)
			{
				return false;
			}
			List<(string, int, bool)> list2 = list.OrderByDescending<(string, int, bool), int>(((string Name, int Balloons, bool IsLocal) row) => row.Balloons).ThenBy<(string, int, bool), string>(((string Name, int Balloons, bool IsLocal) row) => row.Name, StringComparer.OrdinalIgnoreCase).ToList();
			int num = int.MinValue;
			int rank = 0;
			for (int i = 0; i < list2.Count; i++)
			{
				if (list2[i].Item2 != num)
				{
					rank = i + 1;
					num = list2[i].Item2;
				}
				standings.Add(new RepoKartBattleStanding(list2[i].Item1, list2[i].Item2, rank, list2[i].Item3));
			}
			return true;
		}

		private void FireHeldBattleItem(ItemVehicle vehicle)
		{
			if ((!GameAccess.IsMultiplayer() || IsLocalBattleVehicle(vehicle)) && _battlePlayers.TryGetValue(vehicle, out RepoKartBattlePlayerState value) && value.HeldItem != 0)
			{
				RepoKartBattleItem heldItem = value.HeldItem;
				ApplyUseItemState(vehicle, heldItem, playSound: true);
				if (GameAccess.IsMultiplayer())
				{
					RepoKartBattleNetwork.BroadcastUseItem(vehicle, heldItem);
				}
			}
		}

		internal bool TryHitBattleVehicle(ItemVehicle owner, ItemVehicle target, Vector3 hitPosition)
		{
			//IL_0073: 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)
			if (!Object.op_Implicit((Object)(object)target) || (Object)(object)target == (Object)(object)owner || (GameAccess.IsMultiplayer() && !IsLocalBattleVehicle(owner)))
			{
				return false;
			}
			RepoKartBattlePlayerState repoKartBattlePlayerState = EnsureBattlePlayerState(target);
			if (repoKartBattlePlayerState.Balloons <= 0 || repoKartBattlePlayerState.HitCooldown > 0f)
			{
				return false;
			}
			float spinDirection = ((Random.value < 0.5f) ? (-1f) : 1f);
			int balloons = Mathf.Max(0, repoKartBattlePlayerState.Balloons - 1);
			ApplyHitState(owner, target, hitPosition, balloons, spinDirection, playSound: true, logHit: true);
			if (GameAccess.IsMultiplayer())
			{
				RepoKartBattleNetwork.BroadcastHit(owner, target, hitPosition, balloons, spinDirection);
			}
			return true;
		}

		internal bool ApplyNetworkPickup(ItemVehicle vehicle, RepoKartBattleItem item, int itemBoxIndex)
		{
			EnsureAssignedBattleVehiclesRegistered();
			if (!Object.op_Implicit((Object)(object)vehicle) || !ContainsVehicle(vehicle))
			{
				return false;
			}
			ApplyPickupState(vehicle, item, itemBoxIndex, playSound: true, logPickup: false);
			return true;
		}

		internal bool ApplyNetworkUseItem(ItemVehicle vehicle, RepoKartBattleItem item)
		{
			EnsureAssignedBattleVehiclesRegistered();
			if (!Object.op_Implicit((Object)(object)vehicle) || !ContainsVehicle(vehicle))
			{
				return false;
			}
			ApplyUseItemState(vehicle, item, playSound: true);
			return true;
		}

		internal bool ApplyNetworkHit(ItemVehicle owner, ItemVehicle target, Vector3 hitPosition, int balloons, float spinDirection)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			EnsureAssignedBattleVehiclesRegistered();
			if (!Object.op_Implicit((Object)(object)target) || !ContainsVehicle(target))
			{
				return false;
			}
			ApplyHitState(owner, target, hitPosition, Mathf.Clamp(balloons, 0, 3), spinDirection, playSound: true, logHit: false);
			return true;
		}

		internal bool IsLocalBattleVehicle(ItemVehicle vehicle)
		{
			if (!Object.op_Implicit((Object)(object)vehicle))
			{
				return false;
			}
			PlayerAvatar val = GameAccess.PlayerAvatarLocal();
			Dictionary<PlayerAvatar, ItemVehicle> dictionary = GameAccess.PlayerVehicleMap.Invoke(_race);
			if (Object.op_Implicit((Object)(object)val) && dictionary != null && dictionary.TryGetValue(val, out var value) && (Object)(object)value == (Object)(object)vehicle)
			{
				return true;
			}
			PhotonView component = ((Component)vehicle).GetComponent<PhotonView>();
			if ((Object)(object)component != (Object)null && component.IsMine)
			{
				return true;
			}
			return IsLocalControllerNearVehicle(vehicle, 5.5f);
		}

		private bool TryFindLocalBattleVehicle(out ItemVehicle vehicle)
		{
			//IL_00f3: 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)
			vehicle = null;
			EnsureAssignedBattleVehiclesRegistered();
			PlayerAvatar val = GameAccess.PlayerAvatarLocal();
			Dictionary<PlayerAvatar, ItemVehicle> dictionary = GameAccess.PlayerVehicleMap.Invoke(_race);
			if (Object.op_Implicit((Object)(object)val) && dictionary != null && dictionary.TryGetValue(val, out var value) && Object.op_Implicit((Object)(object)value))
			{
				vehicle = value;
				return true;
			}
			foreach (ItemVehicle key in _battlePlayers.Keys)
			{
				if (Object.op_Implicit((Object)(object)key) && IsLocalBattleVehicle(key))
				{
					vehicle = key;
					return true;
				}
			}
			PlayerController playerControllerInstance = GameAccess.GetPlayerControllerInstance();
			if ((Object)(object)playerControllerInstance == (Object)null || _battlePlayers.Count == 0)
			{
				return false;
			}
			ItemVehicle val2 = null;
			float num = float.MaxValue;
			foreach (ItemVehicle key2 in _battlePlayers.Keys)
			{
				if (Object.op_Implicit((Object)(object)key2))
				{
					float num2 = Vector3.Distance(((Component)playerControllerInstance).transform.position, ((Component)key2).transform.position);
					if (num2 < num)
					{
						num = num2;
						val2 = key2;
					}
				}
			}
			if ((Object)(object)val2 != (Object)null && num <= 10f)
			{
				vehicle = val2;
				return true;
			}
			return false;
		}

		private static bool IsLocalControllerNearVehicle(ItemVehicle vehicle, float maxDistance)
		{
			//IL_001d: 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)
			PlayerController playerControllerInstance = GameAccess.GetPlayerControllerInstance();
			if ((Object)(object)playerControllerInstance != (Object)null && Object.op_Implicit((Object)(object)vehicle))
			{
				return Vector3.Distance(((Component)playerControllerInstance).transform.position, ((Component)vehicle).transform.position) <= maxDistance;
			}
			return false;
		}

		private void ApplyPickupState(ItemVehicle vehicle, RepoKartBattleItem item, int itemBoxIndex, bool playSound, bool logPickup)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			RepoKartBattlePlayerState repoKartBattlePlayerState = EnsureBattlePlayerState(vehicle);
			if (repoKartBattlePlayerState.Balloons > 0)
			{
				repoKartBattlePlayerState.HeldItem = item;
				ApplyItemBoxCooldown(itemBoxIndex);
				if (playSound)
				{
					RepoKartBattleAudio.PlayPickup(((Component)vehicle).transform.position);
				}
			}
		}

		private void ApplyUseItemState(ItemVehicle vehicle, RepoKartBattleItem item, bool playSound)
		{
			//IL_0016: 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_004e: Unknown result type (might be due to invalid IL or missing references)
			EnsureBattlePlayerState(vehicle).HeldItem = RepoKartBattleItem.None;
			if (playSound)
			{
				RepoKartBattleAudio.PlayUse(((Component)vehicle).transform.position);
			}
			switch (item)
			{
			case RepoKartBattleItem.Shell:
				RepoKartProjectile.Spawn(vehicle, ((Component)vehicle).transform.position);
				break;
			case RepoKartBattleItem.Banana:
				RepoKartBananaHazard.Spawn(vehicle, ((Component)vehicle).transform.position);
				break;
			case RepoKartBattleItem.Boost:
				GameAccess.ApplyBoost(vehicle, EmpressRepoKartArenaPlugin.Instance.BoostVelocity.Value * 1.25f);
				break;
			}
		}

		private void ApplyHitState(ItemVehicle owner, ItemVehicle target, Vector3 hitPosition, int balloons, float spinDirection, bool playSound, bool logHit)
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: 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_00f4: 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_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: 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_00ad: Unknown result type (might be due to invalid IL or missing references)
			RepoKartBattlePlayerState repoKartBattlePlayerState = EnsureBattlePlayerState(target);
			int balloons2 = repoKartBattlePlayerState.Balloons;
			repoKartBattlePlayerState.HitCooldown = 2f;
			repoKartBattlePlayerState.SpinTimer = 1.35f;
			repoKartBattlePlayerState.SpinDirection = ((spinDirection == 0f) ? 1f : Mathf.Sign(spinDirection));
			repoKartBattlePlayerState.Balloons = Mathf.Clamp(balloons, 0, 3);
			UpdateBalloonVisuals(target, repoKartBattlePlayerState);
			Vector3 val = ((Component)target).transform.position - hitPosition;
			val.y = 0f;
			if (((Vector3)(ref val)).sqrMagnitude < 0.01f)
			{
				val = (Object.op_Implicit((Object)(object)owner) ? (-((Component)owner).transform.forward) : (-((Component)target).transform.forward));
			}
			((Vector3)(ref val)).Normalize();
			if (playSound)
			{
				RepoKartBattleAudio.PlayHit(((Component)target).transform.position);
			}
			GameAccess.TumbleVehicle(target, 2.3f);
			GameAccess.VehicleAddForce(target, val * 22f + Vector3.up * 8f, (ForceMode)2);
			ApplySpinTorque(target, repoKartBattlePlayerState.SpinDirection, continuous: false);
			PlayerAvatar playerForVehicle = GetPlayerForVehicle(target);
			if (balloons2 > 0 && repoKartBattlePlayerState.Balloons <= 0 && (Object)(object)playerForVehicle != (Object)null)
			{
				GameAccess.PlayerDeath(playerForVehicle, -1);
			}
		}

		private void ApplyItemBoxCooldown(int itemBoxIndex)
		{
			if (itemBoxIndex >= 0 && itemBoxIndex < _itemBoxes.Count)
			{
				_itemBoxes[itemBoxIndex].StartCooldown();
			}
		}

		private void UpdateBattleRankingPieces()
		{
			Dictionary<PlayerAvatar, ItemVehicle> dictionary = GameAccess.PlayerVehicleMap.Invoke(_race);
			Dictionary<ItemVehicle, int> dictionary2 = GameAccess.VehicleCurrentPiece.Invoke(_race);
			if (dictionary == null || dictionary2 == null)
			{
				return;
			}
			foreach (KeyValuePair<PlayerAvatar, ItemVehicle> item in dictionary)
			{
				ItemVehicle value = item.Value;
				if (!Object.op_Implicit((Object)(object)item.Key) || !Object.op_Implicit((Object)(object)value))
				{
					continue;
				}
				int num = Mathf.Clamp(EnsureBattlePlayerState(value).Balloons, 0, 3) * 100;
				if (!dictionary2.TryGetValue(value, out var value2) || value2 != num)
				{
					dictionary2[value] = num;
					if (GameAccess.IsMasterClientOrSingleplayer())
					{
						GameAccess.SyncVehiclePiece(_race, value, num);
					}
				}
			}
		}

		private static void ApplySpinTorque(ItemVehicle vehicle, float direction, bool continuous)
		{
			//IL_0020: 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_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: 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_0069: 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_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			Rigidbody component = ((Component)vehicle).GetComponent<Rigidbody>();
			if (!((Object)(object)component == (Object)null) && !component.isKinematic)
			{
				ForceMode val = (ForceMode)(continuous ? 5 : 2);
				float num = (continuous ? 28f : 11f);
				float num2 = (continuous ? 8f : 5f);
				component.AddTorque((Vector3.up * num + ((Component)vehicle).transform.forward * num2) * direction, val);
				if (!continuous)
				{
					component.angularVelocity = new Vector3(component.angularVelocity.x, direction * Mathf.Max(Mathf.Abs(component.angularVelocity.y), 8f), component.angularVelocity.z);
				}
			}
		}

		internal void TickRaceIntro()
		{
			//IL_0028: 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_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Invalid comparison between Unknown and I4
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Invalid comparison between Unknown and I4
			if (!IsReady)
			{
				return;
			}
			DisableVanillaExtractorGeometry(force: false);
			EnsureAssignedBattleVehiclesRegistered();
			States val = GameAccess.CurrentState.Invoke(_race);
			if ((int)val == 0 || (int)val == 1 || (int)val == 2 || (int)val == 3)
			{
				int num = TryPlaceVehiclesAtStartGrid(pinPlaced: true);
				StartDirectBattleOnMap();
				if (num > 0 && !_introPlacementLogged)
				{
					_introPlacementLogged = true;
					EmpressRepoKartArenaPlugin.Log.LogInfo((object)"Pinned REPO battle vehicle(s) to the bundle map spawn and skipped the vanilla extractor drop.");
				}
			}
		}

		private void StartDirectBattleOnMap()
		{
			if (_directBattleStarted || !IsReady)
			{
				return;
			}
			int num = (GameAccess.IsMasterClientOrSingleplayer() ? TryPlaceVehiclesAtStartGrid(pinPlaced: true) : 0);
			int num2 = EnsureAssignedBattleVehiclesRegistered();
			Dictionary<PlayerAvatar, ItemVehicle> dictionary = GameAccess.PlayerVehicleMap.Invoke(_race);
			if (num != 0 || num2 != 0 || (dictionary != null && dictionary.Count != 0))
			{
				_directBattleStarted = true;
				if (GameAccess.IsMasterClientOrSingleplayer())
				{
					GameAccess.StateSet(_race, (States)4);
				}
				DisableVanillaExtractorGeometry(force: true);
				RepoKartBattleMusic.EnsurePlaying(_root);
				if (GameAccess.IsMasterClientOrSingleplayer())
				{
					SyncStrandedPlayersToVehicles();
				}
				else
				{
					SyncLocalControllerToBattleVehicle();
				}
				EmpressRepoKartArenaPlugin.Log.LogInfo((object)(GameAccess.IsMasterClientOrSingleplayer() ? "Battle mode direct-started on the bundle map; vanilla extractor drop bypassed." : "Client battle mode attached to host vehicles on the bundle map; vanilla spawn bypassed."));
			}
		}

		private void DisableVanillaExtractorGeometry(bool force)
		{
			if (force || !(Time.time < _nextVanillaCleanupTime))
			{
				_nextVanillaCleanupTime = Time.time + 1f;
				RepoKartVanillaArenaCleaner.DisableExtractorGeometry(_root);
			}
		}

		internal void SyncLocalControllerToBattleVehicle()
		{
			//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_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Invalid comparison between Unknown and I4
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Invalid comparison between Unknown and I4
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Invalid comparison between Unknown and I4
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Invalid comparison between Unknown and I4
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Invalid comparison between Unknown and I4
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: 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)
			if (!IsReady)
			{
				return;
			}
			States val = GameAccess.CurrentState.Invoke(_race);
			if ((int)val != 0 && (int)val != 1 && (int)val != 2 && (int)val != 3 && (int)val != 4)
			{
				return;
			}
			Dictionary<PlayerAvatar, ItemVehicle> dictionary = GameAccess.PlayerVehicleMap.Invoke(_race);
			if (dictionary == null)
			{
				return;
			}
			foreach (KeyValuePair<PlayerAvatar, ItemVehicle> item in dictionary)
			{
				PlayerAvatar key = item.Key;
				ItemVehicle value = item.Value;
				if (Object.op_Implicit((Object)(object)key) && Object.op_Implicit((Object)(object)value) && GameAccess.PlayerIsLocal.Invoke(key) && !GameAccess.PlayerIsDisabled.Invoke(key))
				{
					float num = (((int)val == 4) ? 12f : 2f);
					PlayerController playerControllerInstance = GameAccess.GetPlayerControllerInstance();
					if ((Object)(object)playerControllerInstance != (Object)null && Vector3.Distance(((Component)playerControllerInstance).transform.position, ((Component)value).transform.position) > num)
					{
						GameAccess.TeleportLocalPlayerController(((Component)value).transform.position + Vector3.up * 2.2f, ((Component)value).transform.rotation);
					}
					break;
				}
			}
		}

		internal bool ContainsVehicle(ItemVehicle vehicle)
		{
			ItemVehicle vehicle2 = vehicle;
			Dictionary<ItemVehicle, int> dictionary = GameAccess.VehicleCurrentPiece.Invoke(_race);
			if (dictionary != null && dictionary.ContainsKey(vehicle2))
			{
				return true;
			}
			if (_battlePlayers.ContainsKey(vehicle2))
			{
				return true;
			}
			return GameAccess.PlayerVehicleMap.Invoke(_race)?.Values.Any((ItemVehicle mappedVehicle) => (Object)(object)mappedVehicle == (Object)(object)vehicle2) ?? false;
		}

		private int EnsureAssignedBattleVehiclesRegistered()
		{
			if (!IsReady)
			{
				return 0;
			}
			Dictionary<PlayerAvatar, ItemVehicle> dictionary = GameAccess.PlayerVehicleMap.Invoke(_race);
			if (dictionary == null || dictionary.Count == 0)
			{
				return 0;
			}
			int num = 0;
			foreach (KeyValuePair<PlayerAvatar, ItemVehicle> item in dictionary)
			{
				ItemVehicle value = item.Value;
				if (Object.op_Implicit((Object)(object)item.Key) && Object.op_Implicit((Object)(object)value))
				{
					if (!_startGridVehicleIndices.TryGetValue(value, out var value2))
					{
						value2 = _startGridVehicleIndices.Count;
						_startGridVehicleIndices[value] = value2;
					}
					EnsureBattlePlayerState(value, value2);
					num++;
				}
			}
			return num;
		}

		private int TryPlaceVehiclesAtStartGrid(bool pinPlaced = false)
		{
			if (!IsReady || _checkpoints.Count < 2 || !GameAccess.IsMasterClientOrSingleplayer())
			{
				return 0;
			}
			Dictionary<PlayerAvatar, ItemVehicle> dictionary = GameAccess.PlayerVehicleMap.Invoke(_race);
			Dictionary<ItemVehicle, int> dictionary2 = GameAccess.VehicleCurrentPiece.Invoke(_race);
			if (dictionary == null || dictionary2 == null || dictionary.Count == 0)
			{
				return 0;
			}
			int num = 0;
			foreach (KeyValuePair<PlayerAvatar, ItemVehicle> item in dictionary)
			{
				PlayerAvatar key = item.Key;
				ItemVehicle value = item.Value;
				if (Object.op_Implicit((Object)(object)key) && !GameAccess.PlayerIsDisabled.Invoke(key) && Object.op_Implicit((Object)(object)value))
				{
					int value2;
					bool flag = _startGridVehicleIndices.TryGetValue(value, out value2);
					if (!flag)
					{
						value2 = _startGridVehicleIndices.Count;
						_startGridVehicleIndices[value] = value2;
						num++;
					}
					if (!flag || pinPlaced)
					{
						PlaceVehicleAtStartGrid(key, value, value2, dictionary2, !flag || pinPlaced);
					}
				}
			}
			if (num > 0)
			{
				EmpressRepoKartArenaPlugin.Log.LogInfo((object)$"Placed {num} REPO vehicle(s) on the kart start grid.");
			}
			return num;
		}

		private void PlaceVehicleAtStartGrid(PlayerAvatar player, ItemVehicle vehicle, int gridIndex, Dictionary<ItemVehicle, int> vehicleCurrentPiece, bool spawnPlayer)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: 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_0023: 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_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: 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_003c: Unknown result type (might be due to invalid IL or missing references)
			RepoKartStartPose startGridPose = GetStartGridPose(gridIndex);
			Vector3 val = startGridPose.Position + Vector3.up * 1.2f;
			Quaternion rotation = startGridPose.Rotation;
			TeleportVehicle(vehicle, val, rotation);
			if (spawnPlayer)
			{
				SpawnPlayerNearVehicle(player, vehicle, val, rotation, onlyIfFar: false);
			}
			GameAccess.ForceSeatPlayer(vehicle, 0, player);
			EnsureBattlePlayerState(vehicle, gridIndex);
			vehicleCurrentPiece[vehicle] = 0;
			GameAccess.SyncVehiclePiece(_race, vehicle, 0);
		}

		private void SyncStrandedPlayersToVehicles()
		{
			//IL_0070: 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_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_0090: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<PlayerAvatar, ItemVehicle> dictionary = GameAccess.PlayerVehicleMap.Invoke(_race);
			if (dictionary == null)
			{
				return;
			}
			foreach (KeyValuePair<PlayerAvatar, ItemVehicle> item in dictionary)
			{
				PlayerAvatar key = item.Key;
				ItemVehicle value = item.Value;
				if (Object.op_Implicit((Object)(object)key) && !GameAccess.PlayerIsDisabled.Invoke(key) && Object.op_Implicit((Object)(object)value))
				{
					GameAccess.ForceSeatPlayer(value, 0, key);
					SpawnPlayerNearVehicle(key, value, ((Component)value).transform.position + Vector3.up * 0.8f, ((Component)value).transform.rotation, onlyIfFar: true);
				}
			}
		}

		private void SpawnPlayerNearVehicle(PlayerAvatar player, ItemVehicle? vehicle, Vector3 basePosition, Quaternion rotation, bool onlyIfFar)
		{
			//IL_0069: 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_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)player) && (!onlyIfFar || !((Object)(object)vehicle != (Object)null) || !(Vector3.Distance(((Component)player).transform.position, ((Component)vehicle).transform.position) < 8f)) && (!_nextPlayerSpawnSync.TryGetValue(player, out var value) || !(Time.time < value)))
			{
				_nextPlayerSpawnSync[player] = Time.time + 0.2f;
				Vector3 val = basePosition + Vector3.up * 1.4f;
				GameAccess.PlayerSpawn(player, val, rotation);
				if (GameAccess.PlayerIsLocal.Invoke(player))
				{
					GameAccess.TeleportLocalPlayerController(val, rotation);
				}
			}
		}

		private void EnsureBattlePlayerState(ItemVehicle vehicle, int gridIndex)
		{
			if (!_battlePlayers.ContainsKey(vehicle))
			{
				RepoKartBattlePlayerState repoKartBattlePlayerState = new RepoKartBattlePlayerState();
				_battlePlayers[vehicle] = repoKartBattlePlayerState;
				CreateBalloonVisuals(vehicle, repoKartBattlePlayerState, gridIndex);
			}
		}

		private RepoKartBattlePlayerState EnsureBattlePlayerState(ItemVehicle vehicle)
		{
			if (_battlePlayers.TryGetValue(vehicle, out RepoKartBattlePlayerState value))
			{
				return value;
			}
			if (!_startGridVehicleIndices.TryGetValue(vehicle, out var value2))
			{
				value2 = _startGridVehicleIndices.Count;
				_startGridVehicleIndices[vehicle] = value2;
			}
			EnsureBattlePlayerState(vehicle, value2);
			return _battlePlayers[vehicle];
		}

		private void CreateBalloonVisuals(ItemVehicle vehicle, RepoKartBattlePlayerState state, int gridIndex)
		{
			//IL_001c: 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_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_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//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_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: 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_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Expected O, but got Unknown
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Expected O, but got Unknown
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Expected O, but got Unknown
			//IL_0137: 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_017c: 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_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			Color[] array = (Color[])(object)new Color[4]
			{
				new Color(1f, 0.08f, 0.08f, 1f),
				new Color(1f, 0.9f, 0.05f, 1f),
				new Color(0.1f, 0.45f, 1f, 1f),
				new Color(0.1f, 0.9f, 0.25f, 1f)
			};
			Color color = array[Mathf.Abs(gridIndex) % array.Length];
			Material sharedMaterial = new Material(Shader.Find("Standard"))
			{
				color = color
			};
			Material sharedMaterial2 = new Material(Shader.Find("Standard"))
			{
				color = new Color(0.92f, 0.92f, 0.85f, 1f)
			};
			for (int i = 0; i < 3; i++)
			{
				GameObject val = new GameObject($"EmpressRepoKartArena.BalloonLife.{i}");
				val.transform.SetParent(((Component)vehicle).transform, false);
				val.transform.localPosition = new Vector3((float)(i - 1) * 0.75f, 2.8f + (float)i * 0.12f, -0.65f);
				val.transform.localRotation = Quaternion.identity;
				GameObject obj = GameObject.CreatePrimitive((PrimitiveType)0);
				((Object)obj).name = "Balloon";
				obj.transform.SetParent(val.transform, false);
				obj.transform.localPosition = Vector3.zero;
				obj.transform.localScale = new Vector3(0.45f, 0.55f, 0.45f);
				obj.GetComponent<Renderer>().sharedMaterial = sharedMaterial;
				Collider component = obj.GetComponent<Collider>();
				if ((Object)(object)component != (Object)null)
				{
					component.enabled = false;
				}
				GameObject obj2 = GameObject.CreatePrimitive((PrimitiveType)2);
				((Object)obj2).name = "Tether";
				obj2.transform.SetParent(val.transform, false);
				obj2.transform.localPosition = new Vector3(0f, -0.65f, 0f);
				obj2.transform.localRotation = Quaternion.identity;
				obj2.transform.localScale = new Vector3(0.025f, 0.65f, 0.025f);
				obj2.GetComponent<Renderer>().sharedMaterial = sharedMaterial2;
				Collider component2 = obj2.GetComponent<Collider>();
				if ((Object)(object)component2 != (Object)null)
				{
					component2.enabled = false;
				}
				state.BalloonVisuals.Add(val);
			}
		}

		private static void UpdateBalloonVisuals(ItemVehicle vehicle, RepoKartBattlePlayerState state)
		{
			for (int i = 0; i < state.BalloonVisuals.Count; i++)
			{
				GameObject val = state.BalloonVisuals[i];
				if ((Object)(object)val != (Object)null)
				{
					val.SetActive(i < state.Balloons);
				}
			}
		}

		private PlayerAvatar? GetPlayerForVehicle(ItemVehicle vehicle)
		{
			Dictionary<PlayerAvatar, ItemVehicle> dictionary = GameAccess.PlayerVehicleMap.Invoke(_race);
			if (dictionary == null)
			{
				return null;
			}
			foreach (KeyValuePair<PlayerAvatar, ItemVehicle> item in dictionary)
			{
				if ((Object)(object)item.Value == (Object)(object)vehicle)
				{
					return item.Key;
				}
			}
			return null;
		}

		private RepoKartStartPose GetStartGridPose(int gridIndex)
		{
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: 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_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: 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_00fd: 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_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_004e: 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_0052: 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_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: 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)
			//IL_009e: 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_00a7: 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)
			if (_startPoses.Count > 0)
			{
				RepoKartStartPose result = _startPoses[Mathf.Min(gridIndex, _startPoses.Count - 1)];
				if (gridIndex < _startPoses.Count)
				{
					return result;
				}
				Vector3 val = ForwardFromRotation(result.Rotation);
				Vector3 val2 = RightFromForward(val);
				int num = gridIndex - _startPoses.Count;
				int num2 = num % 4;
				int num3 = num / 4 + 1;
				float num4 = ((float)num2 - 1.5f) * 2.75f;
				return new RepoKartStartPose(result.Position - val * ((float)num3 * 5f) + val2 * num4, result.Rotation);
			}
			Vector3 val3 = _checkpoints[0];
			Vector3 val4 = _checkpoints[1] - _checkpoints[0];
			val4.y = 0f;
			if (((Vector3)(ref val4)).sqrMagnitude < 0.01f)
			{
				val4 = Vector3.forward;
			}
			((Vector3)(ref val4)).Normalize();
			Vector3 val5 = RightFromForward(val4);
			int num5 = gridIndex % 4;
			int num6 = gridIndex / 4;
			float num7 = ((float)num5 - 1.5f) * 2.75f;
			return new RepoKartStartPose(val3 - val4 * (5f + (float)num6 * 5f) + val5 * num7 + Vector3.up * 2f, Quaternion.LookRotation(val4, Vector3.up));
		}

		private static void TeleportVehicle(ItemVehicle vehicle, Vector3 position, Quaternion rotation)
		{
			//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_001d: 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_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: 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)
			((Component)vehicle).transform.SetPositionAndRotation(position, rotation);
			Rigidbody component = ((Component)vehicle).GetComponent<Rigidbody>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.position = position;
				component.rotation = rotation;
				if (!component.isKinematic)
				{
					component.velocity = Vector3.zero;
					component.angularVelocity = Vector3.zero;
				}
			}
			PhysGrabObject component2 = ((Component)vehicle).GetComponent<PhysGrabObject>();
			if ((Object)(object)component2 != (Object)null)
			{
				GameAccess.PhysGrabTeleport(component2, position, rotation);
			}
		}

		private void ConfigureRaceFields()
		{
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (