Decompiled source of Hamilton v0.1.9

BepInEx\plugins\HamiltonMod.dll

Decompiled 15 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mirror;
using Steamworks;
using Steamworks.Data;
using TMPro;
using UnityEngine;
using UnityEngine.Localization.Components;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("HamiltonMod")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("HamiltonMod")]
[assembly: AssemblyTitle("HamiltonMod")]
[assembly: AssemblyVersion("1.0.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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace HamiltonMod
{
	[BepInPlugin("codex.superbattlegolf.hamilton", "Hamilton", "0.1.9")]
	public sealed class HamiltonPlugin : BaseUnityPlugin
	{
		private enum ShotOutcome
		{
			Normal,
			Misfire,
			Backfire,
			OrbitalStrike
		}

		[HarmonyPatch(typeof(PlayerInventory), "DecrementUseFromSlotAt")]
		private static class KeepPistolLoadedPatch
		{
			private static bool Prefix(PlayerInventory __instance, int index)
			{
				return !IsReservedPistolSlot(__instance, index);
			}
		}

		[HarmonyPatch(typeof(PlayerInventory), "RemoveIfOutOfUses")]
		private static class PreventLoadedPistolRemovalPatch
		{
			private static bool Prefix(PlayerInventory __instance, int index)
			{
				return !IsReservedPistolSlot(__instance, index);
			}
		}

		[HarmonyPatch(typeof(PlayerInventorySettings), "get_MaxItems")]
		private static class MaxInventorySlotsPatch
		{
			private static void Postfix(ref int __result)
			{
				if (IsHamiltonEnabled())
				{
					__result = Mathf.Max(__result, 4);
				}
			}
		}

		[HarmonyPatch(typeof(PlayerInventory), "OnStartServer")]
		private static class ServerStartReservedPistolPatch
		{
			private static void Postfix(PlayerInventory __instance)
			{
				if (IsHamiltonEnabled() && NetworkServer.active)
				{
					EnsureReservedPistol(__instance);
				}
			}
		}

		[HarmonyPatch(typeof(PlayerInventory), "OnStartClient")]
		private static class ClientStartReservedPistolPatch
		{
			private static void Postfix(PlayerInventory __instance)
			{
			}
		}

		[HarmonyPatch(typeof(PlayerInventory), "OnStartLocalPlayer")]
		private static class LocalPlayerStartReservedPistolPatch
		{
			private static void Postfix(PlayerInventory __instance)
			{
				if (IsHamiltonEnabled() && NetworkServer.active)
				{
					EnsureReservedPistol(__instance);
				}
			}
		}

		[HarmonyPatch(typeof(PlayerInventory), "OnBUpdate")]
		private static class InventoryUpdateReservedPistolPatch
		{
			private static void Postfix(PlayerInventory __instance)
			{
				if (IsHamiltonEnabled() && NetworkServer.active)
				{
					EnsureReservedPistol(__instance);
				}
			}
		}

		[HarmonyPatch(typeof(PlayerInventory), "ServerTryAddItem")]
		private static class ReservedSlotItemGrantPatch
		{
			private static bool Prefix(PlayerInventory __instance, ItemType itemToAdd, int remainingUses, ref bool __result)
			{
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				//IL_0012: Invalid comparison between Unknown and I4
				if (!IsHamiltonEnabled() || !NetworkServer.active)
				{
					return true;
				}
				if ((int)itemToAdd == 2)
				{
					EnsureReservedPistol(__instance);
					__result = true;
					return false;
				}
				EnsureReservedPistol(__instance);
				return true;
			}
		}

		[HarmonyPatch(typeof(PlayerInventory), "DropItem")]
		private static class PreventDroppingReservedPistolPatch
		{
			private static bool Prefix(PlayerInventory __instance)
			{
				if (IsHamiltonEnabled())
				{
					return __instance.EquippedItemIndex != 0;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(MatchSetupRules), "Initialize")]
		private static class MatchSetupRulesInitializePatch
		{
			private static void Postfix()
			{
				instance?.TryInstallHamiltonRulesToggle();
			}
		}

		[HarmonyPatch(typeof(MatchSetupRules), "OnStartClient")]
		private static class MatchSetupRulesStartClientPatch
		{
			private static void Postfix()
			{
				instance?.TryInstallHamiltonRulesToggle();
			}
		}

		[HarmonyPatch(typeof(ItemPool), "GetWeightedRandomItem")]
		private static class RemovePistolFromItemPoolsPatch
		{
			private static bool Prefix(ItemPool __instance, ref ItemType __result)
			{
				if (!IsHamiltonEnabled())
				{
					return true;
				}
				return !TryGetWeightedRandomNonPistolItem(__instance, out __result);
			}
		}

		[HarmonyPatch]
		private static class DuelingPistolShotPatch
		{
			private static MethodBase TargetMethod()
			{
				return AccessTools.Method(typeof(PlayerInventory), "<ShootDuelingPistolRoutine>g__Shoot|164_0", (Type[])null, (Type[])null);
			}

			private static bool Prefix(PlayerInventory __instance)
			{
				if (!IsHamiltonEnabled() || (Object)(object)__instance == (Object)null || !((NetworkBehaviour)__instance).isLocalPlayer)
				{
					return true;
				}
				switch (RollShotOutcome())
				{
				case ShotOutcome.Misfire:
					Misfire();
					return false;
				case ShotOutcome.Backfire:
					Backfire(__instance);
					return false;
				case ShotOutcome.OrbitalStrike:
					OrbitalStrikeMisfire(__instance);
					return false;
				default:
					return true;
				}
			}
		}

		private const string PluginGuid = "codex.superbattlegolf.hamilton";

		private const string PluginName = "Hamilton";

		private const string PluginVersion = "0.1.9";

		private const string LobbyEnabledStateKey = "codex_hamilton_enabled";

		private const string LobbyEnabledVersionKey = "codex_hamilton_enabled_version";

		private const string LobbyRequiredVersionKey = "codex_hamilton_required_version";

		private const string LobbyMemberVersionKey = "codex_hamilton_member_version";

		private const int ReservedPistolSlotIndex = 0;

		private const int TotalInventorySlots = 4;

		private static HamiltonPlugin instance;

		private static FieldInfo inventorySlotsField;

		private static FieldInfo itemPoolSpawnChancesField;

		private static MethodInfo giveItemToLocalPlayerMethod;

		private static MethodInfo cmdActivateOrbitalLaserMethod;

		private static int syntheticItemUseIndex;

		private static bool hasLobbyEnabledState;

		private static bool lobbyEnabledState = true;

		private static string lastObservedLobbyEnabledVersion = string.Empty;

		private static float nextLobbyPollTime;

		private static bool allLobbyMembersCompatible = true;

		private static string incompatibleLobbyMembers = string.Empty;

		private static float nextCompatibilityWarningTime;

		private Harmony harmony;

		private ConfigEntry<bool> enabledConfig;

		private ConfigEntry<float> grantCheckIntervalConfig;

		private ConfigEntry<float> misfireChanceConfig;

		private ConfigEntry<float> backfireChanceConfig;

		private ConfigEntry<float> orbitalStrikeOnMisfireChanceConfig;

		private ConfigEntry<bool> autoSelectPistolConfig;

		private float nextGrantCheckTime;

		private float nextRulesUiCheckTime;

		private DropdownOption hamiltonRulesDropdown;

		private bool suppressHamiltonDropdownChanged;

		private void Awake()
		{
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Expected O, but got Unknown
			instance = this;
			enabledConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable Hamilton.");
			grantCheckIntervalConfig = ((BaseUnityPlugin)this).Config.Bind<float>("General", "GrantCheckIntervalSeconds", 1f, "How often the mod checks whether the local player needs a pistol.");
			misfireChanceConfig = ((BaseUnityPlugin)this).Config.Bind<float>("Chaos", "MisfireChance", 0.15f, "Chance from 0 to 1 that a pistol shot does not fire.");
			backfireChanceConfig = ((BaseUnityPlugin)this).Config.Bind<float>("Chaos", "BackfireChance", 0.1f, "Chance from 0 to 1 that a pistol shot hits the shooter instead.");
			orbitalStrikeOnMisfireChanceConfig = ((BaseUnityPlugin)this).Config.Bind<float>("Chaos", "OrbitalStrikeOnMisfireChance", 0.01f, "Chance from 0 to 1 that a misfire calls an orbital strike on the shooter.");
			autoSelectPistolConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AutoSelectPistol", false, "Automatically select the permanent pistol slot when the mod grants one.");
			inventorySlotsField = AccessTools.Field(typeof(PlayerInventory), "slots");
			itemPoolSpawnChancesField = AccessTools.Field(typeof(ItemPool), "spawnChances");
			giveItemToLocalPlayerMethod = AccessTools.Method(typeof(PlayerInventory), "GiveItemToLocalPlayer", (Type[])null, (Type[])null);
			cmdActivateOrbitalLaserMethod = AccessTools.Method(typeof(PlayerInventory), "CmdActivateOrbitalLaser", (Type[])null, (Type[])null);
			harmony = new Harmony("codex.superbattlegolf.hamilton");
			harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Hamilton 0.1.9 loaded.");
		}

		private void OnDestroy()
		{
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			if (instance == this)
			{
				instance = null;
			}
		}

		private void Update()
		{
			PollSteamLobbyEnabledState();
			TryInstallHamiltonRulesToggle();
			RefreshHamiltonRulesToggle();
			if (IsHamiltonEnabled() && !(Time.unscaledTime < nextGrantCheckTime))
			{
				nextGrantCheckTime = Time.unscaledTime + Mathf.Max(0.25f, grantCheckIntervalConfig.Value);
				TryEnsureLocalPlayerHasPistol();
			}
		}

		private static bool IsHamiltonEnabled()
		{
			if (NetworkServer.active && !allLobbyMembersCompatible)
			{
				return false;
			}
			if (hasLobbyEnabledState)
			{
				return lobbyEnabledState;
			}
			return instance?.enabledConfig.Value ?? true;
		}

		private static int DropdownValueFromEnabled(bool enabled)
		{
			return (!enabled) ? 1 : 0;
		}

		private static bool EnabledFromDropdownValue(int value)
		{
			return value == 0;
		}

		private static void PollSteamLobbyEnabledState()
		{
			//IL_0055: 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)
			if (Time.unscaledTime < nextLobbyPollTime)
			{
				return;
			}
			nextLobbyPollTime = Time.unscaledTime + 0.5f;
			Lobby lobby = default(Lobby);
			if (!BNetworkManager.TryGetSteamLobby(ref lobby))
			{
				if (!NetworkServer.active && !NetworkClient.active)
				{
					hasLobbyEnabledState = false;
					lastObservedLobbyEnabledVersion = string.Empty;
					allLobbyMembersCompatible = true;
					incompatibleLobbyMembers = string.Empty;
				}
				return;
			}
			PublishLocalMemberVersion(lobby);
			if (NetworkServer.active)
			{
				UpdateLobbyCompatibility(lobby);
			}
			string data = ((Lobby)(ref lobby)).GetData("codex_hamilton_enabled");
			if (string.IsNullOrEmpty(data))
			{
				if (NetworkServer.active)
				{
					PublishSteamLobbyEnabledState(instance?.enabledConfig.Value ?? true);
				}
				return;
			}
			string data2 = ((Lobby)(ref lobby)).GetData("codex_hamilton_enabled_version");
			bool flag = data == "1";
			bool num = !hasLobbyEnabledState || lobbyEnabledState != flag || data2 != lastObservedLobbyEnabledVersion;
			hasLobbyEnabledState = true;
			lobbyEnabledState = flag;
			lastObservedLobbyEnabledVersion = data2;
			if (num)
			{
				if (NetworkServer.active)
				{
					ApplyServerEnabledState(flag);
				}
				instance?.RefreshHamiltonRulesToggle();
			}
		}

		private static void PublishLocalMemberVersion(Lobby lobby)
		{
			if (SteamClient.IsValid)
			{
				((Lobby)(ref lobby)).SetMemberData("codex_hamilton_member_version", "0.1.9");
			}
		}

		private static void UpdateLobbyCompatibility(Lobby lobby)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: 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_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active)
			{
				return;
			}
			((Lobby)(ref lobby)).SetData("codex_hamilton_required_version", "0.1.9");
			List<string> list = new List<string>();
			foreach (Friend member in ((Lobby)(ref lobby)).Members)
			{
				Friend current = member;
				string memberData = ((Lobby)(ref lobby)).GetMemberData(current, "codex_hamilton_member_version");
				if (!string.Equals(memberData, "0.1.9", StringComparison.Ordinal))
				{
					string? text;
					if (!string.IsNullOrEmpty(((Friend)(ref current)).Name))
					{
						text = ((Friend)(ref current)).Name;
					}
					else
					{
						SteamId id = current.Id;
						text = ((object)(SteamId)(ref id)).ToString();
					}
					string text2 = text;
					list.Add(string.IsNullOrEmpty(memberData) ? (text2 + " (missing Hamilton 0.1.9)") : (text2 + " (Hamilton " + memberData + ", needs 0.1.9)"));
				}
			}
			allLobbyMembersCompatible = list.Count == 0;
			incompatibleLobbyMembers = string.Join(", ", list);
			if (allLobbyMembersCompatible)
			{
				return;
			}
			if (hasLobbyEnabledState && lobbyEnabledState)
			{
				PublishSteamLobbyEnabledState(enabled: false);
			}
			if (Time.unscaledTime >= nextCompatibilityWarningTime)
			{
				nextCompatibilityWarningTime = Time.unscaledTime + 10f;
				HamiltonPlugin hamiltonPlugin = instance;
				if (hamiltonPlugin != null)
				{
					((BaseUnityPlugin)hamiltonPlugin).Logger.LogWarning((object)("Hamilton disabled until every lobby member is running Hamilton 0.1.9: " + incompatibleLobbyMembers));
				}
			}
		}

		private static void PublishSteamLobbyEnabledState(bool enabled)
		{
			if (enabled && NetworkServer.active && !allLobbyMembersCompatible)
			{
				enabled = false;
				HamiltonPlugin hamiltonPlugin = instance;
				if (hamiltonPlugin != null)
				{
					((BaseUnityPlugin)hamiltonPlugin).Logger.LogWarning((object)("Hamilton cannot be enabled yet. Waiting for: " + incompatibleLobbyMembers));
				}
			}
			hasLobbyEnabledState = true;
			lobbyEnabledState = enabled;
			lastObservedLobbyEnabledVersion = Time.unscaledTime.ToString("R");
			Lobby val = default(Lobby);
			if (BNetworkManager.TryGetSteamLobby(ref val))
			{
				((Lobby)(ref val)).SetData("codex_hamilton_enabled", enabled ? "1" : "0");
				((Lobby)(ref val)).SetData("codex_hamilton_enabled_version", lastObservedLobbyEnabledVersion);
			}
			ApplyServerEnabledState(enabled);
			instance?.RefreshHamiltonRulesToggle();
		}

		private static void ApplyServerEnabledState(bool enabled)
		{
			if (!NetworkServer.active)
			{
				return;
			}
			PlayerInventory[] array = Object.FindObjectsByType<PlayerInventory>((FindObjectsSortMode)0);
			foreach (PlayerInventory val in array)
			{
				if (!((Object)(object)val == (Object)null))
				{
					if (enabled)
					{
						EnsureReservedPistol(val);
					}
					else
					{
						RemoveReservedPistol(val);
					}
				}
			}
		}

		private void TryInstallHamiltonRulesToggle()
		{
			if ((Object)(object)hamiltonRulesDropdown != (Object)null || Time.unscaledTime < nextRulesUiCheckTime)
			{
				return;
			}
			nextRulesUiCheckTime = Time.unscaledTime + 1f;
			MatchSetupRules val = FindMatchSetupRules();
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			DropdownOption val2 = (((Object)(object)val.hitOtherPlayers != (Object)null) ? val.hitOtherPlayers : val.homingShots);
			if (!((Object)(object)val2 == (Object)null) && !((Object)(object)((Component)val2).transform == (Object)null) && !((Object)(object)((Component)val2).transform.parent == (Object)null))
			{
				GameObject val3 = Object.Instantiate<GameObject>(((Component)val2).gameObject, ((Component)val2).transform.parent);
				((Object)val3).name = "HamiltonRulesDropdown";
				val3.transform.SetSiblingIndex(((Component)val2).transform.GetSiblingIndex() + 1);
				LocalizeStringEvent[] componentsInChildren = val3.GetComponentsInChildren<LocalizeStringEvent>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					((Behaviour)componentsInChildren[i]).enabled = false;
				}
				hamiltonRulesDropdown = val3.GetComponent<DropdownOption>();
				if ((Object)(object)hamiltonRulesDropdown == (Object)null)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)"Could not create Hamilton custom rules dropdown.");
					Object.Destroy((Object)(object)val3);
					return;
				}
				hamiltonRulesDropdown.SetOptions(new List<string> { "On", "Off" });
				hamiltonRulesDropdown.Initialize((Action)OnHamiltonRulesDropdownChanged, DropdownValueFromEnabled(IsHamiltonEnabled()));
				SetHamiltonRulesRowText();
				RefreshHamiltonRulesToggle();
				RebuildRulesLayout(((Component)val2).transform.parent);
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Added Hamilton toggle to custom rules.");
			}
		}

		private static MatchSetupRules FindMatchSetupRules()
		{
			if (SingletonNetworkBehaviour<MatchSetupRules>.HasInstance)
			{
				return SingletonNetworkBehaviour<MatchSetupRules>.Instance;
			}
			if (SingletonBehaviour<MatchSetupRules>.HasInstance)
			{
				return SingletonBehaviour<MatchSetupRules>.Instance;
			}
			return Object.FindFirstObjectByType<MatchSetupRules>((FindObjectsInactive)1);
		}

		private static void RebuildRulesLayout(Transform parent)
		{
			RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null);
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)parent).GetComponent<RectTransform>();
			}
			if ((Object)(object)val != (Object)null)
			{
				LayoutRebuilder.ForceRebuildLayoutImmediate(val);
			}
		}

		private void SetHamiltonRulesRowText()
		{
			if ((Object)(object)hamiltonRulesDropdown == (Object)null)
			{
				return;
			}
			TMP_Text captionText = hamiltonRulesDropdown.captionText;
			TMP_Text[] componentsInChildren = ((Component)hamiltonRulesDropdown).GetComponentsInChildren<TMP_Text>(true);
			foreach (TMP_Text val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)captionText) && !val.text.Equals("On", StringComparison.OrdinalIgnoreCase) && !val.text.Equals("Off", StringComparison.OrdinalIgnoreCase))
				{
					val.text = GetHamiltonRulesLabel();
					break;
				}
			}
		}

		private static string GetHamiltonRulesLabel()
		{
			if (NetworkServer.active && !allLobbyMembersCompatible)
			{
				return "Hamilton Needs Update";
			}
			return "Hamilton";
		}

		private void RefreshHamiltonRulesToggle()
		{
			if (!((Object)(object)hamiltonRulesDropdown == (Object)null))
			{
				suppressHamiltonDropdownChanged = true;
				hamiltonRulesDropdown.valueWithoutNotify = DropdownValueFromEnabled(IsHamiltonEnabled());
				suppressHamiltonDropdownChanged = false;
				hamiltonRulesDropdown.Interactable = NetworkServer.active && allLobbyMembersCompatible;
				SetHamiltonRulesRowText();
			}
		}

		private void OnHamiltonRulesDropdownChanged()
		{
			if (!suppressHamiltonDropdownChanged && !((Object)(object)hamiltonRulesDropdown == (Object)null))
			{
				if (!NetworkServer.active)
				{
					RefreshHamiltonRulesToggle();
				}
				else
				{
					PublishSteamLobbyEnabledState(EnabledFromDropdownValue(hamiltonRulesDropdown.value));
				}
			}
		}

		private void TryEnsureLocalPlayerHasPistol()
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active)
			{
				return;
			}
			PlayerInventory localPlayerInventory = GameManager.LocalPlayerInventory;
			if ((Object)(object)localPlayerInventory == (Object)null || !((NetworkBehaviour)localPlayerInventory).isLocalPlayer)
			{
				return;
			}
			EnsureSlotCount(localPlayerInventory);
			int index;
			if (TryGetSlot(localPlayerInventory, 0, out var slot) && IsPistol(slot))
			{
				if (autoSelectPistolConfig.Value && localPlayerInventory.EquippedItemIndex != 0 && localPlayerInventory.CanSelectItemAt(0))
				{
					localPlayerInventory.TrySelectItemSlot(0);
				}
			}
			else if (TryFindPistolSlot(localPlayerInventory, out index) && index != 0)
			{
				MovePistolToReservedSlot(localPlayerInventory, index);
			}
			else
			{
				giveItemToLocalPlayerMethod?.Invoke(localPlayerInventory, new object[1] { (object)(ItemType)2 });
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Granted local player a dueling pistol.");
			}
		}

		private static bool TryFindPistolSlot(PlayerInventory inventory, out int index)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			index = -1;
			SyncList<InventorySlot> slots = GetSlots(inventory);
			if (slots == null)
			{
				return false;
			}
			for (int i = 0; i < slots.Count; i++)
			{
				if (IsPistol(slots[i]))
				{
					index = i;
					return true;
				}
			}
			return false;
		}

		private static bool TryGetSlot(PlayerInventory inventory, int index, out InventorySlot slot)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			slot = InventorySlot.Empty;
			SyncList<InventorySlot> slots = GetSlots(inventory);
			if (slots == null || index < 0 || index >= slots.Count)
			{
				return false;
			}
			slot = slots[index];
			return true;
		}

		private static bool IsPistol(InventorySlot slot)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			if ((int)slot.itemType == 2)
			{
				return slot.remainingUses > 0;
			}
			return false;
		}

		private static bool IsEmpty(InventorySlot slot)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: 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)
			if ((int)slot.itemType != 0)
			{
				return slot.remainingUses <= 0;
			}
			return true;
		}

		private static bool IsReservedPistolSlot(PlayerInventory inventory, int index)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			if (IsHamiltonEnabled() && index == 0 && TryGetSlot(inventory, index, out var slot))
			{
				return IsPistol(slot);
			}
			return false;
		}

		private static SyncList<InventorySlot> GetSlots(PlayerInventory inventory)
		{
			return inventorySlotsField?.GetValue(inventory) as SyncList<InventorySlot>;
		}

		private static void EnsureSlotCount(PlayerInventory inventory)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			SyncList<InventorySlot> slots = GetSlots(inventory);
			if (slots != null)
			{
				while (slots.Count < 4)
				{
					slots.Add(InventorySlot.Empty);
				}
			}
		}

		private static void MovePistolToReservedSlot(PlayerInventory inventory, int existingPistolIndex)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: 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)
			SyncList<InventorySlot> slots = GetSlots(inventory);
			if (slots != null && existingPistolIndex >= 0 && existingPistolIndex < slots.Count)
			{
				EnsureSlotCount(inventory);
				InventorySlot val = slots[0];
				slots[0] = new InventorySlot((ItemType)2, 1);
				if (existingPistolIndex != 0)
				{
					slots[existingPistolIndex] = (IsEmpty(val) ? InventorySlot.Empty : val);
				}
			}
		}

		private static void EnsureReservedPistol(PlayerInventory inventory)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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_0048: Unknown result type (might be due to invalid IL or missing references)
			if (!IsHamiltonEnabled())
			{
				return;
			}
			SyncList<InventorySlot> slots = GetSlots(inventory);
			if (slots == null)
			{
				return;
			}
			EnsureSlotCount(inventory);
			InventorySlot val = slots[0];
			if (IsPistol(val))
			{
				return;
			}
			if (TryFindPistolSlot(inventory, out var index) && index != 0)
			{
				MovePistolToReservedSlot(inventory, index);
				return;
			}
			if (!IsEmpty(val))
			{
				MoveReservedItemToFirstNormalSlot(slots, val);
			}
			slots[0] = new InventorySlot((ItemType)2, 1);
		}

		private static void RemoveReservedPistol(PlayerInventory inventory)
		{
			//IL_0016: 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)
			SyncList<InventorySlot> slots = GetSlots(inventory);
			if (slots != null && 0 < slots.Count && IsPistol(slots[0]))
			{
				slots[0] = InventorySlot.Empty;
			}
		}

		private static void MoveReservedItemToFirstNormalSlot(SyncList<InventorySlot> slots, InventorySlot reservedSlot)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 1; i < 4; i++)
			{
				if (IsEmpty(slots[i]))
				{
					slots[i] = reservedSlot;
					break;
				}
			}
		}

		private static bool TryGetWeightedRandomNonPistolItem(ItemPool pool, out ItemType item)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Invalid comparison between Unknown and I4
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Invalid comparison between Unknown and I4
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Expected I4, but got Unknown
			item = (ItemType)0;
			if (!(itemPoolSpawnChancesField?.GetValue(pool) is Array array) || array.Length == 0)
			{
				return false;
			}
			float num = 0f;
			foreach (object item2 in array)
			{
				ItemType val = (ItemType)AccessTools.Field(item2.GetType(), "item").GetValue(item2);
				float num2 = (float)AccessTools.Field(item2.GetType(), "spawnChanceWeight").GetValue(item2);
				if ((int)val != 2 && (int)val != 0 && num2 > 0f)
				{
					num += num2;
				}
			}
			if (num <= 0f)
			{
				item = (ItemType)1;
				return true;
			}
			float num3 = Random.value * num;
			foreach (object item3 in array)
			{
				ItemType val2 = (ItemType)AccessTools.Field(item3.GetType(), "item").GetValue(item3);
				float num4 = (float)AccessTools.Field(item3.GetType(), "spawnChanceWeight").GetValue(item3);
				if ((int)val2 != 2 && (int)val2 != 0 && !(num4 <= 0f))
				{
					num3 -= num4;
					if (num3 <= 0f)
					{
						item = (ItemType)(int)val2;
						return true;
					}
				}
			}
			item = (ItemType)1;
			return true;
		}

		private static ShotOutcome RollShotOutcome()
		{
			float num = Mathf.Clamp01(instance?.backfireChanceConfig.Value ?? 0f);
			float num2 = Mathf.Clamp01(instance?.misfireChanceConfig.Value ?? 0f);
			float value = Random.value;
			if (value < num)
			{
				return ShotOutcome.Backfire;
			}
			if (value < num + num2)
			{
				if (Random.value < Mathf.Clamp01(instance?.orbitalStrikeOnMisfireChanceConfig.Value ?? 0f))
				{
					return ShotOutcome.OrbitalStrike;
				}
				return ShotOutcome.Misfire;
			}
			return ShotOutcome.Normal;
		}

		private static void Backfire(PlayerInventory inventory)
		{
			//IL_0043: 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_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: 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_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: 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_009e: Unknown result type (might be due to invalid IL or missing references)
			PlayerInfo playerInfo = inventory.PlayerInfo;
			PlayerMovement val = ((playerInfo != null) ? playerInfo.Movement : null);
			Hittable val2 = ((playerInfo != null) ? playerInfo.AsHittable : null);
			if (!((Object)(object)playerInfo == (Object)null) && !((Object)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null))
			{
				Vector3 val3 = -((Component)playerInfo).transform.forward + Vector3.up * 0.35f;
				Vector3 normalized = ((Vector3)(ref val3)).normalized;
				Vector3 val4 = ((Component)val2).transform.InverseTransformPoint(inventory.GetDuelingPistolBarrelEndPosition());
				Vector3 val5 = normalized * 12f;
				ItemUseId val6 = CreateSyntheticItemUseId(playerInfo, (ItemType)2);
				bool flag = default(bool);
				val.TryKnockOut(playerInfo, (KnockoutType)4, false, val4, 0f, val5, false, val6, true, true, ref flag);
				HamiltonPlugin hamiltonPlugin = instance;
				if (hamiltonPlugin != null)
				{
					((BaseUnityPlugin)hamiltonPlugin).Logger.LogInfo((object)"Dueling pistol backfired.");
				}
			}
		}

		private static void OrbitalStrikeMisfire(PlayerInventory inventory)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: 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_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			PlayerInfo playerInfo = inventory.PlayerInfo;
			Hittable val = ((playerInfo != null) ? playerInfo.AsHittable : null);
			if (!((Object)(object)playerInfo == (Object)null) && !((Object)(object)val == (Object)null))
			{
				ItemUseId val2 = CreateSyntheticItemUseId(playerInfo, (ItemType)10);
				Vector3 position = ((Component)playerInfo).transform.position;
				if (NetworkServer.active)
				{
					OrbitalLaserManager.ServerActivateLaser(val, position, inventory, val2);
				}
				else
				{
					cmdActivateOrbitalLaserMethod?.Invoke(inventory, new object[3] { val, position, val2 });
				}
				HamiltonPlugin hamiltonPlugin = instance;
				if (hamiltonPlugin != null)
				{
					((BaseUnityPlugin)hamiltonPlugin).Logger.LogInfo((object)"Dueling pistol misfire called an orbital strike.");
				}
			}
		}

		private static ItemUseId CreateSyntheticItemUseId(PlayerInfo player, ItemType itemType)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			return new ItemUseId(((Object)(object)((player != null) ? player.PlayerId : null) != (Object)null) ? player.PlayerId.Guid : 0, ++syntheticItemUseIndex, itemType);
		}

		private static void Misfire()
		{
			HamiltonPlugin hamiltonPlugin = instance;
			if (hamiltonPlugin != null)
			{
				((BaseUnityPlugin)hamiltonPlugin).Logger.LogInfo((object)"Dueling pistol misfired.");
			}
		}
	}
}