Decompiled source of BoneHunt v0.5.8

BONELAB/BonelabPropHunt.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BoneLib;
using BoneLib.BoneMenu;
using BonelabPropHunt;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSLZ.Bonelab;
using Il2CppSLZ.Marrow;
using Il2CppSLZ.Marrow.Combat;
using Il2CppSLZ.Marrow.Data;
using Il2CppSLZ.Marrow.Interaction;
using Il2CppSLZ.Marrow.Pool;
using Il2CppSystem;
using Il2CppTMPro;
using LabFusion.Entities;
using LabFusion.Menu.Data;
using LabFusion.Network;
using LabFusion.Player;
using LabFusion.SDK.Gamemodes;
using LabFusion.SDK.Metadata;
using LabFusion.UI.Popups;
using MelonLoader;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Main), "BoneHunt", "0.1.0", "crispy_Baconman", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("BonelabPropHunt")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("BonelabPropHunt")]
[assembly: AssemblyTitle("BonelabPropHunt")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace BonelabPropHunt
{
	public class BoneHuntGamemode : Gamemode
	{
		private readonly TeamManager _teamManager = new TeamManager();

		private readonly Team _hiderTeam = new Team("Hiders");

		private readonly Team _seekerTeam = new Team("Seekers");

		private readonly Team _spectatorTeam = new Team("Spectators");

		private float _seekerDelaySeconds = 40f;

		private float _hiderSurvivalSeconds = 300f;

		private bool _seekerBlackout = true;

		private float _currentTimer;

		private bool _isHidingPhase;

		private bool _roundActive;

		private GameObject _blackoutOverlay;

		private readonly MetadataPlayerDictionary<MetadataBool> _hidingStateKeeper = new MetadataPlayerDictionary<MetadataBool>();

		public override string Title => "BoneHunt";

		public override string Author => "crispy_Baconman";

		public override string Description => "Hide as physics props, or hunt down the hiders. Get caught and you're out!";

		public TeamManager TeamManager => _teamManager;

		public Team HiderTeam => _hiderTeam;

		public Team SeekerTeam => _seekerTeam;

		public Team SpectatorTeam => _spectatorTeam;

		public override GroupElementData CreateSettingsGroup()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0018: 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_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			//IL_006f: 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_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Expected O, but got Unknown
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: 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_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Expected O, but got Unknown
			GroupElementData obj = ((Gamemode)this).CreateSettingsGroup();
			GroupElementData val = new GroupElementData("Round Settings");
			obj.AddElement<GroupElementData>(val);
			FloatElementData val2 = new FloatElementData
			{
				Title = "How long until seekers can see again? (seconds)",
				Value = _seekerDelaySeconds,
				Increment = 5f,
				MinValue = 5f,
				MaxValue = 300f,
				OnValueChanged = delegate(float v)
				{
					_seekerDelaySeconds = v;
				}
			};
			val.AddElement<FloatElementData>(val2);
			FloatElementData val3 = new FloatElementData
			{
				Title = "How long before hiders win? (seconds)",
				Value = _hiderSurvivalSeconds,
				Increment = 15f,
				MinValue = 30f,
				MaxValue = 1800f,
				OnValueChanged = delegate(float v)
				{
					_hiderSurvivalSeconds = v;
				}
			};
			val.AddElement<FloatElementData>(val3);
			BoolElementData val4 = new BoolElementData
			{
				Title = "Blackout seekers while props go hide?",
				Value = _seekerBlackout,
				OnValueChanged = delegate(bool v)
				{
					_seekerBlackout = v;
				}
			};
			val.AddElement<BoolElementData>(val4);
			return obj;
		}

		public override bool CheckReadyConditions()
		{
			return PlayerIDManager.PlayerCount >= 2;
		}

		public override void OnGamemodeRegistered()
		{
			TeamManager.Register((Gamemode)(object)this);
			TeamManager.AddTeam(_hiderTeam);
			TeamManager.AddTeam(_seekerTeam);
			TeamManager.AddTeam(_spectatorTeam);
			TeamManager.OnAssignedToTeam += OnAssignedToTeam;
			TeamManager.OnRemovedFromTeam += OnRemovedFromTeam;
			((MetadataDictionary<byte, MetadataBool>)(object)_hidingStateKeeper).Register(((Gamemode)this).Metadata, "IsHiding");
			_hidingStateKeeper.OnPlayerVariableChanged += OnHidingStateChanged;
			LocalHealth.OnAttackedByPlayer += OnAttackedByPlayer;
			MelonCoroutines.Start(GameLoopRoutine());
		}

		public override void OnGamemodeUnregistered()
		{
			TeamManager.Unregister();
			TeamManager.OnAssignedToTeam -= OnAssignedToTeam;
			TeamManager.OnRemovedFromTeam -= OnRemovedFromTeam;
			((MetadataDictionary<byte, MetadataBool>)(object)_hidingStateKeeper).Unregister();
			_hidingStateKeeper.OnPlayerVariableChanged -= OnHidingStateChanged;
			LocalHealth.OnAttackedByPlayer -= OnAttackedByPlayer;
			SetBlackout(enable: false);
		}

		public override void OnGamemodeStarted()
		{
			AssignRandomTeams();
			StartRound();
		}

		public override void OnGamemodeStopped()
		{
			_roundActive = false;
			_isHidingPhase = false;
			SetBlackout(enable: false);
			if (PropifyController.IsActive)
			{
				PropifyController.EndPossession();
			}
		}

		private void StartRound()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: 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_006b: 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_0085: Expected O, but got Unknown
			_isHidingPhase = true;
			_roundActive = true;
			_currentTimer = _seekerDelaySeconds;
			Notifier.Send(new Notification
			{
				Title = NotificationText.op_Implicit("BoneHunt"),
				Message = NotificationText.op_Implicit($"Hiders, you guys go hide because you only have {Mathf.Ceil(_seekerDelaySeconds)} seconds before the seekers can see again!!"),
				PopupLength = 4f
			});
			Main.Log.Msg("Round started: Hiding Phase active.");
			if (_seekerBlackout && TeamManager.GetPlayerTeam(PlayerIDManager.LocalID) == _seekerTeam)
			{
				SetBlackout(enable: true);
			}
		}

		private IEnumerator GameLoopRoutine()
		{
			while (true)
			{
				if (_roundActive && ((Gamemode)this).IsStarted)
				{
					if (_currentTimer > 0f)
					{
						_currentTimer -= 1f;
						if (_currentTimer <= 0f && _isHidingPhase)
						{
							_isHidingPhase = false;
							_currentTimer = _hiderSurvivalSeconds;
							SetBlackout(enable: false);
							Notifier.Send(new Notification
							{
								Title = NotificationText.op_Implicit("BoneHunt"),
								Message = NotificationText.op_Implicit("Who let the seekers out? Me! Me! Me! Me!"),
								PopupLength = 4f
							});
							Main.Log.Msg("Yo you're cooked i just let the seekers out!!");
							if (TeamManager.GetPlayerTeam(PlayerIDManager.LocalID) == _seekerTeam)
							{
								EquipSeekerShotgun();
							}
						}
					}
					else if (!_isHidingPhase)
					{
						EndRound(seekersWon: false);
					}
					CheckWinConditions();
				}
				yield return (object)new WaitForSeconds(1f);
			}
		}

		private void CheckWinConditions()
		{
			if (_roundActive && !_isHidingPhase)
			{
				List<PlayerID> list = PlayerIDManager.PlayerIDs.Where((PlayerID id) => TeamManager.GetPlayerTeam(id) == _hiderTeam).ToList();
				if (list == null || list.Count == 0)
				{
					EndRound(seekersWon: true);
				}
			}
		}

		private void EndRound(bool seekersWon)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Expected O, but got Unknown
			if (_roundActive)
			{
				_roundActive = false;
				_isHidingPhase = false;
				SetBlackout(enable: false);
				string text = (seekersWon ? "The SabreLake Seekers found all the props! Seekers win!" : "The LavaGang Lurkers didn't get caught! Props win! ");
				Notifier.Send(new Notification
				{
					Title = NotificationText.op_Implicit("BoneHunt"),
					Message = NotificationText.op_Implicit(text),
					PopupLength = 5f
				});
				Main.Log.Msg(text);
				MelonCoroutines.Start(RestartRoundRoutine());
			}
		}

		private IEnumerator RestartRoundRoutine()
		{
			yield return (object)new WaitForSeconds(5f);
			if (((Gamemode)this).IsStarted && NetworkInfo.HasServer)
			{
				AssignRandomTeams();
				StartRound();
			}
		}

		private void AssignRandomTeams()
		{
			List<PlayerID> list = PlayerIDManager.PlayerIDs.ToList();
			int num = Mathf.Max(1, list.Count / 4);
			for (int i = 0; i < list.Count; i++)
			{
				Team val = ((i < num) ? _seekerTeam : _hiderTeam);
				TeamManager.TryAssignTeam(list[i], val);
			}
		}

		private void OnAssignedToTeam(PlayerID player, Team team)
		{
			if (player.IsMe)
			{
				OnSelfAssignedToTeam(team);
			}
		}

		private void OnRemovedFromTeam(PlayerID player, Team team)
		{
		}

		private void OnSelfAssignedToTeam(Team team)
		{
			//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_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: 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_0051: Expected O, but got Unknown
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Expected O, but got Unknown
			//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_0087: 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_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Expected O, but got Unknown
			string text = "None";
			if (team == _hiderTeam)
			{
				text = "Hider";
				SetBlackout(enable: false);
				Notifier.Send(new Notification
				{
					Title = NotificationText.op_Implicit("BoneHunt"),
					Message = NotificationText.op_Implicit("You have been chosen as a prop. Go find a traffic cone or smth I don't care what as long as you hide!"),
					PopupLength = 4f
				});
			}
			else if (team == _seekerTeam)
			{
				text = "Seeker";
				if (_isHidingPhase && _seekerBlackout)
				{
					SetBlackout(enable: true);
				}
				Notifier.Send(new Notification
				{
					Title = NotificationText.op_Implicit("BoneHunt"),
					Message = NotificationText.op_Implicit("You have been chosen as a seeker. You have 6 shots to find a prop, good luck dont die or whatever!"),
					PopupLength = 4f
				});
				if (!_isHidingPhase)
				{
					EquipSeekerShotgun();
				}
			}
			else if (team == _spectatorTeam)
			{
				text = "Spectator";
				SetBlackout(enable: false);
				Notifier.Send(new Notification
				{
					Title = NotificationText.op_Implicit("BoneHunt"),
					Message = NotificationText.op_Implicit("Waa waa wa waaaaaaaaa(sad trombone)! You died! That means: YOU LOSE!!"),
					PopupLength = 4f
				});
			}
			Main.Log.Msg("Whaddup son! It's me, Ford, to tell you your team: " + text);
		}

		private void SetBlackout(bool enable)
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Expected O, but got Unknown
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			if (enable)
			{
				if (!((Object)(object)_blackoutOverlay != (Object)null))
				{
					_blackoutOverlay = GameObject.CreatePrimitive((PrimitiveType)0);
					((Object)_blackoutOverlay).name = "BoneHunt_SeekerBlackout";
					Collider component = _blackoutOverlay.GetComponent<Collider>();
					if ((Object)(object)component != (Object)null)
					{
						Object.Destroy((Object)(object)component);
					}
					Transform head = Player.Head;
					if ((Object)(object)head != (Object)null)
					{
						_blackoutOverlay.transform.SetParent(head);
						_blackoutOverlay.transform.localPosition = Vector3.zero;
						_blackoutOverlay.transform.localRotation = Quaternion.identity;
						_blackoutOverlay.transform.localScale = new Vector3(0.15f, 0.15f, 0.15f);
					}
					Renderer component2 = _blackoutOverlay.GetComponent<Renderer>();
					if ((Object)(object)component2 != (Object)null)
					{
						Material val = new Material(Shader.Find("Universal Render Pipeline/Unlit") ?? Shader.Find("Unlit/Color"));
						val.color = Color.black;
						component2.material = val;
						component2.shadowCastingMode = (ShadowCastingMode)0;
						component2.receiveShadows = false;
					}
				}
			}
			else if ((Object)(object)_blackoutOverlay != (Object)null)
			{
				Object.Destroy((Object)(object)_blackoutOverlay);
				_blackoutOverlay = null;
			}
		}

		private void EquipSeekerShotgun()
		{
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: 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_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			Main.Log.Msg("Get that shotty, get them cartridges!");
			AmmoInventory instance = AmmoInventory.Instance;
			if ((Object)(object)instance != (Object)null)
			{
				AmmoGroup lightAmmoGroup = instance.lightAmmoGroup;
				CartridgeData val = ((lightAmmoGroup == null) ? null : ((IEnumerable<CartridgeData>)lightAmmoGroup.cartridges)?.FirstOrDefault());
				AmmoGroup mediumAmmoGroup = instance.mediumAmmoGroup;
				CartridgeData val2 = ((mediumAmmoGroup == null) ? null : ((IEnumerable<CartridgeData>)mediumAmmoGroup.cartridges)?.FirstOrDefault());
				AmmoGroup heavyAmmoGroup = instance.heavyAmmoGroup;
				CartridgeData val3 = ((heavyAmmoGroup == null) ? null : ((IEnumerable<CartridgeData>)heavyAmmoGroup.cartridges)?.FirstOrDefault());
				if ((Object)(object)val != (Object)null)
				{
					instance.AddCartridge(val, 6);
				}
				if ((Object)(object)val2 != (Object)null)
				{
					instance.AddCartridge(val2, 6);
				}
				if ((Object)(object)val3 != (Object)null)
				{
					instance.AddCartridge(val3, 6);
				}
			}
			RigManager rigManager = Player.RigManager;
			Vector3 val4 = (((Object)(object)rigManager != (Object)null && (Object)(object)rigManager.physicsRig != (Object)null && (Object)(object)((Rig)rigManager.physicsRig).m_head != (Object)null) ? (((Rig)rigManager.physicsRig).m_head.position + ((Rig)rigManager.physicsRig).m_head.forward * 1f) : (PropSelector.GetPlayerPosition() + Vector3.up));
			Quaternion val5 = (((Object)(object)rigManager != (Object)null && (Object)(object)rigManager.physicsRig != (Object)null && (Object)(object)((Rig)rigManager.physicsRig).m_head != (Object)null) ? ((Rig)rigManager.physicsRig).m_head.rotation : Quaternion.identity);
			HelperMethods.SpawnCrate("c1534c5a-7f05-402f-9320-609647756e35", val4, val5, Vector3.one, false, (Action<GameObject>)delegate(GameObject spawnedObject)
			{
				if (!((Object)(object)spawnedObject == (Object)null))
				{
					MelonCoroutines.Start(DelayedLoadShells(spawnedObject));
				}
			}, (Action<GameObject>)null);
		}

		private IEnumerator DelayedLoadShells(GameObject spawnedObject)
		{
			yield return (object)new WaitForSeconds(0.2f);
			if (!((Object)(object)spawnedObject == (Object)null))
			{
				Gun componentInChildren = spawnedObject.GetComponentInChildren<Gun>();
				if (!((Object)(object)componentInChildren == (Object)null) && componentInChildren._magState != null)
				{
					componentInChildren._magState.SetCartridge(6);
				}
			}
		}

		private void OnHidingStateChanged(PlayerID player, MetadataBool isHiding)
		{
			NetworkPlayer val = default(NetworkPlayer);
			if (NetworkPlayerManager.TryGetPlayer(PlayerID.op_Implicit(player), ref val))
			{
				bool forceHide = ((MetadataVariableT<bool>)(object)isHiding).GetValue() && TeamManager.GetPlayerTeam(player) == _hiderTeam;
				val.ForceHide = forceHide;
			}
		}

		public void SetLocalHidingState(bool isHiding)
		{
			((MetadataVariableT<bool>)(object)_hidingStateKeeper.GetVariable(PlayerIDManager.LocalID)).SetValue(isHiding);
		}

		public void CatchHider()
		{
			if (((Gamemode)this).IsStarted && _roundActive && TeamManager.GetPlayerTeam(PlayerIDManager.LocalID) == _hiderTeam)
			{
				if (PropifyController.IsActive)
				{
					PropifyController.EndPossession();
				}
				SetLocalHidingState(isHiding: false);
				TeamManager.TryAssignTeam(PlayerIDManager.LocalID, _spectatorTeam);
				Main.Log.Msg("Get rekt loser! Btw, no one can see or hear you cuz you're a spectator.");
				CheckWinConditions();
			}
		}

		private void OnAttackedByPlayer(Attack attack, BodyPart bodyPart, PlayerID attacker)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			if (!_isHidingPhase)
			{
				Main.Log.Msg($"[PropHunt Log] Shot propped player! Attacker ID: {((attacker != null) ? attacker.SmallID : 0)}, BodyPart: {bodyPart}");
				CatchHider();
			}
		}
	}
	public class Main : MelonMod
	{
		public static Instance Log;

		public override void OnInitializeMelon()
		{
			Log = ((MelonBase)this).LoggerInstance;
			Log.Msg("BonelabPropHunt loading...");
			PropSelector.Init();
			PropifyController.Init();
			GamemodeRegistration.LoadGamemodes(typeof(Main).Assembly);
			Log.Msg("BonelabPropHunt ready.");
		}

		public override void OnSceneWasLoaded(int buildIndex, string sceneName)
		{
			Log.Msg("Scene loaded ('" + sceneName + "') refreshing prop list.");
			if (PropifyController.IsActive)
			{
				Log.Msg("Level changed while possessing a prop. ejecting.");
				PropifyController.EndPossession();
			}
			PropSelector.RefreshMenu();
		}

		public override void OnUpdate()
		{
			PropifyController.Tick();
			PreferencesPanelButton.TryInject();
		}

		public override void OnLateUpdate()
		{
			PropifyController.LateTick();
		}

		public override void OnFixedUpdate()
		{
			PropifyController.FixedTick();
			TouchPossess.FixedTick();
		}
	}
	public static class PreferencesPanelButton
	{
		private static bool _injected;

		private static GameObject _transformButton;

		public static void TryInject()
		{
			if (_injected)
			{
				return;
			}
			try
			{
				UIRig uIRig = Player.UIRig;
				object obj;
				if (uIRig == null)
				{
					obj = null;
				}
				else
				{
					PopUpMenuView popUpMenu = uIRig.popUpMenu;
					obj = ((popUpMenu != null) ? popUpMenu.preferencesPanelView : null);
				}
				PreferencesPanelView val = (PreferencesPanelView)obj;
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				Il2CppReferenceArray<GameObject> pages = val.pages;
				if (pages == null || val.defaultPage < 0 || val.defaultPage >= ((Il2CppArrayBase<GameObject>)(object)pages).Length)
				{
					return;
				}
				GameObject val2 = ((Il2CppArrayBase<GameObject>)(object)pages)[val.defaultPage];
				if ((Object)(object)val2 == (Object)null)
				{
					return;
				}
				Transform val3 = val2.transform.Find("grid_Options");
				if ((Object)(object)val3 == (Object)null)
				{
					Main.Log.Warning(" Couldn't find 'grid_Options' under the Options panel. Skipping injection.");
					_injected = true;
					return;
				}
				Button componentInChildren = ((Component)val3).GetComponentInChildren<Button>(true);
				if ((Object)(object)componentInChildren == (Object)null)
				{
					Main.Log.Warning(" No existing button found in the Options grid to clone. Skipping injection.");
					_injected = true;
					return;
				}
				_transformButton = Object.Instantiate<GameObject>(((Component)componentInChildren).gameObject, val3);
				((Object)_transformButton).name = "BoneHunt_TransformToPropButton";
				TextMeshProUGUI componentInChildren2 = _transformButton.GetComponentInChildren<TextMeshProUGUI>(true);
				if ((Object)(object)componentInChildren2 != (Object)null)
				{
					((TMP_Text)componentInChildren2).text = "Transform to Prop";
				}
				else
				{
					Text componentInChildren3 = _transformButton.GetComponentInChildren<Text>(true);
					if ((Object)(object)componentInChildren3 != (Object)null)
					{
						componentInChildren3.text = "Transform to Prop";
					}
				}
				StripNonEssentialComponents(_transformButton);
				Button component = _transformButton.GetComponent<Button>();
				((UnityEventBase)component.onClick).RemoveAllListeners();
				((UnityEvent)component.onClick).AddListener(UnityAction.op_Implicit((Action)OnButtonClicked));
				LayoutRebuilder.ForceRebuildLayoutImmediate(((Component)val3).GetComponent<RectTransform>());
				_injected = true;
				Main.Log.Msg(" Injected 'Transform to Prop' button into native Preferences panel.");
			}
			catch (Exception ex)
			{
				Main.Log.Warning(" Preferences panel injection failed: " + ex.Message + ". Falling back to BoneMenu-only.");
				_injected = true;
			}
		}

		private static void StripNonEssentialComponents(GameObject root)
		{
			foreach (Component componentsInChild in root.GetComponentsInChildren<Component>(true))
			{
				if (!((Object)(object)componentsInChild == (Object)null) && !(componentsInChild is RectTransform) && !(componentsInChild is CanvasRenderer) && !(componentsInChild is Image) && !(componentsInChild is Button) && !(componentsInChild is Text) && !(componentsInChild is TextMeshProUGUI) && !(componentsInChild is ButtonHoverClick) && !(componentsInChild is Transform))
				{
					Object.Destroy((Object)(object)componentsInChild);
				}
			}
		}

		private static void OnButtonClicked()
		{
			Main.Log.Msg(" 'Transform to Prop' clicked via native Preferences button. Arming TouchPossess.");
			TouchPossess.Arm();
			ClosePopup();
		}

		private static void ClosePopup()
		{
			try
			{
				UIRig uIRig = Player.UIRig;
				object obj;
				if (uIRig == null)
				{
					obj = null;
				}
				else
				{
					PopUpMenuView popUpMenu = uIRig.popUpMenu;
					obj = ((popUpMenu != null) ? popUpMenu.preferencesPanelView : null);
				}
				PreferencesPanelView val = (PreferencesPanelView)obj;
				if (!((Object)(object)val == (Object)null))
				{
					Transform val2 = ((Component)val).transform.Find("image_bgFade");
					if ((Object)(object)val2 != (Object)null)
					{
						((Component)val2).gameObject.SetActive(false);
					}
				}
			}
			catch (Exception ex)
			{
				Main.Log.Warning(" Couldn't auto-close preferences popup: " + ex.Message);
			}
		}
	}
	public static class PropifyController
	{
		private static readonly Type MarrowEntityType = Il2CppType.Of<MarrowEntity>();

		private static Rigidbody _possessed;

		private static bool _active;

		private static bool _isDebugPossession;

		private static float _lastJumpTime;

		private static float _lastBTapTime;

		private static Vector3 _lastKnownPos;

		private static NetworkEntity _currentEntity;

		private static Transform _camTransform;

		private const float CamDistance = 2.5f;

		private const float CamHeight = 1.2f;

		private const float MaxSpeed = 5f;

		private const float JumpVelocity = 5f;

		private const float JumpCooldown = 0.2f;

		private static bool _wantsToJump;

		private static bool _wantsToSnapUpright;

		private static readonly List<Rigidbody> _frozenRigBodies = new List<Rigidbody>();

		private static readonly List<Collider> _frozenColliders = new List<Collider>();

		private static readonly List<CharacterController> _frozenCharControllers = new List<CharacterController>();

		private static readonly List<CharacterController> _pendingCharControllerReenable = new List<CharacterController>();

		private static int _charControllerReenableDelayFrames;

		private static readonly Dictionary<Transform, Vector3> _originalScales = new Dictionary<Transform, Vector3>();

		private static int _ownershipReclaimCooldown;

		public static bool IsActive => _active;

		public static void Init()
		{
		}

		public static bool IsFakePlayer(GameObject obj)
		{
			if ((Object)(object)obj != (Object)null)
			{
				return ((Object)obj).name.Contains("Fake_Propped_Player_Dummy");
			}
			return false;
		}

		public static bool IsTargetProppedPlayer(GameObject obj)
		{
			if ((Object)(object)obj == (Object)null)
			{
				return false;
			}
			if (IsFakePlayer(obj))
			{
				return true;
			}
			if (_active && (Object)(object)_possessed != (Object)null)
			{
				return obj.transform.IsChildOf(((Component)_possessed).transform);
			}
			return false;
		}

		public static void BeginPossession(Rigidbody target)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			if (_active || (Object)(object)target == (Object)null)
			{
				return;
			}
			_possessed = target;
			_possessed.isKinematic = false;
			_possessed.WakeUp();
			_lastKnownPos = _possessed.position;
			_isDebugPossession = PropSelector.DebugMode;
			if (!_isDebugPossession)
			{
				SetPlayerAvatarVisibility(hide: true);
				FreezePlayerRig(freeze: true);
				Main.Log.Msg("Rigidly attached to '" + ((Object)((Component)_possessed).gameObject).name + "'. VR Rig Frozen.");
			}
			else
			{
				Main.Log.Msg("Controlling '" + ((Object)((Component)_possessed).gameObject).name + "' without freezing or moving VR Rig!");
			}
			_active = true;
			if (!NetworkInfo.HasServer)
			{
				return;
			}
			Component componentInParent = ((Component)_possessed).GetComponentInParent(MarrowEntityType);
			MarrowEntity val = (((Object)(object)componentInParent != (Object)null) ? ((Il2CppObjectBase)componentInParent).TryCast<MarrowEntity>() : null);
			if (!((Object)(object)val != (Object)null))
			{
				return;
			}
			NetworkProp component = ((Component)val).GetComponent<NetworkProp>();
			if (component != null)
			{
				_currentEntity = component.NetworkEntity;
				if (_currentEntity != null)
				{
					NetworkEntityManager.TakeOwnership(_currentEntity);
					Main.Log.Msg("Claimed Fusion network ownership of '" + ((Object)((Component)_possessed).gameObject).name + "'.");
				}
			}
		}

		public static void EndPossession()
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: 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_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			if (!_active)
			{
				return;
			}
			if (NetworkInfo.HasServer && _currentEntity != null)
			{
				_currentEntity.RemoveOwner();
				Main.Log.Msg("Released Fusion network ownership.");
				_currentEntity = null;
			}
			if (!_isDebugPossession)
			{
				RigManager localRigManager = PropSelector.GetLocalRigManager();
				if ((Object)(object)localRigManager != (Object)null)
				{
					Vector3 val = (((Object)(object)_possessed != (Object)null) ? _possessed.position : _lastKnownPos);
					((Component)localRigManager).transform.position = val + Vector3.up * 2.5f;
				}
				FreezePlayerRig(freeze: false);
				SetPlayerAvatarVisibility(hide: false);
			}
			_active = false;
			_possessed = null;
			_isDebugPossession = false;
			_wantsToJump = false;
			_wantsToSnapUpright = false;
			Main.Log.Msg("Depropified.");
		}

		public static void SpawnFakeProppedPlayer()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_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_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)
			Vector3 spawnPos = PropSelector.GetPlayerPosition() + Vector3.forward * 2f + Vector3.up;
			Main.Log.Msg("Spawning Fake Propped Player dummy...");
			HelperMethods.SpawnCrate("c1534c5a-7f05-402f-9320-609647756e35", spawnPos, Quaternion.identity, Vector3.one, false, (Action<GameObject>)delegate(GameObject spawnedObject)
			{
				//IL_003a: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)spawnedObject == (Object)null))
				{
					((Object)spawnedObject).name = "Fake_Propped_Player_Dummy";
					spawnedObject.AddComponent<FakePropDamageTracker>();
					Main.Log.Msg($"Fake Propped Player ready at {spawnPos}. Shoot it to test detection!");
				}
			}, (Action<GameObject>)null);
		}

		private static void FreezePlayerRig(bool freeze)
		{
			//IL_006e: 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)
			RigManager localRigManager = PropSelector.GetLocalRigManager();
			if ((Object)(object)localRigManager == (Object)null || (Object)(object)localRigManager.physicsRig == (Object)null)
			{
				return;
			}
			if (freeze)
			{
				_frozenRigBodies.Clear();
				_frozenColliders.Clear();
				_frozenCharControllers.Clear();
				foreach (Rigidbody componentsInChild in ((Component)localRigManager.physicsRig).GetComponentsInChildren<Rigidbody>())
				{
					if (!((Object)(object)componentsInChild == (Object)null) && !componentsInChild.isKinematic)
					{
						componentsInChild.velocity = Vector3.zero;
						componentsInChild.angularVelocity = Vector3.zero;
						componentsInChild.isKinematic = true;
						_frozenRigBodies.Add(componentsInChild);
					}
				}
				foreach (Collider componentsInChild2 in ((Component)localRigManager.physicsRig).GetComponentsInChildren<Collider>())
				{
					if (!((Object)(object)componentsInChild2 == (Object)null) && componentsInChild2.enabled)
					{
						componentsInChild2.enabled = false;
						_frozenColliders.Add(componentsInChild2);
					}
				}
				{
					foreach (CharacterController componentsInChild3 in ((Component)localRigManager).GetComponentsInChildren<CharacterController>())
					{
						if (!((Object)(object)componentsInChild3 == (Object)null) && ((Collider)componentsInChild3).enabled)
						{
							((Collider)componentsInChild3).enabled = false;
							_frozenCharControllers.Add(componentsInChild3);
						}
					}
					return;
				}
			}
			foreach (Rigidbody frozenRigBody in _frozenRigBodies)
			{
				if ((Object)(object)frozenRigBody != (Object)null)
				{
					frozenRigBody.isKinematic = false;
				}
			}
			_frozenRigBodies.Clear();
			foreach (Collider frozenCollider in _frozenColliders)
			{
				if ((Object)(object)frozenCollider != (Object)null)
				{
					frozenCollider.enabled = true;
				}
			}
			_frozenColliders.Clear();
			_pendingCharControllerReenable.Clear();
			_pendingCharControllerReenable.AddRange(_frozenCharControllers);
			_frozenCharControllers.Clear();
			_charControllerReenableDelayFrames = 1;
		}

		private static void ProcessDelayedCharControllerReenable()
		{
			if (_charControllerReenableDelayFrames <= 0)
			{
				return;
			}
			_charControllerReenableDelayFrames--;
			if (_charControllerReenableDelayFrames > 0)
			{
				return;
			}
			foreach (CharacterController item in _pendingCharControllerReenable)
			{
				if ((Object)(object)item != (Object)null)
				{
					((Collider)item).enabled = true;
				}
			}
			_pendingCharControllerReenable.Clear();
			Main.Log.Msg("CharacterController re-enabled post-depropify.");
		}

		private static void SetPlayerAvatarVisibility(bool hide)
		{
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			RigManager localRigManager = PropSelector.GetLocalRigManager();
			if ((Object)(object)localRigManager == (Object)null)
			{
				return;
			}
			foreach (Renderer componentsInChild in ((Component)((Component)localRigManager).transform).GetComponentsInChildren<Renderer>(true))
			{
				if (!((Object)(object)componentsInChild != (Object)null))
				{
					continue;
				}
				componentsInChild.enabled = !hide;
				Vector3 value;
				if (hide)
				{
					if (!_originalScales.ContainsKey(((Component)componentsInChild).transform))
					{
						_originalScales[((Component)componentsInChild).transform] = ((Component)componentsInChild).transform.localScale;
					}
					((Component)componentsInChild).transform.localScale = Vector3.zero;
				}
				else if (_originalScales.TryGetValue(((Component)componentsInChild).transform, out value))
				{
					((Component)componentsInChild).transform.localScale = value;
				}
				else
				{
					((Component)componentsInChild).transform.localScale = Vector3.one;
				}
			}
		}

		public static void TeleportPropToPlayer()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			if (_active && !((Object)(object)_possessed == (Object)null))
			{
				Vector3 val = (((Object)(object)PropSelector.GetLocalRigManager() != (Object)null) ? ((Component)PropSelector.GetLocalRigManager()).transform.position : Vector3.zero);
				_possessed.position = val + Vector3.forward * 1.5f + Vector3.up * 0.5f;
				_possessed.velocity = Vector3.zero;
			}
		}

		public static void TeleportPropToSpawn()
		{
			//IL_0029: 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_0047: Unknown result type (might be due to invalid IL or missing references)
			if (_active && !((Object)(object)_possessed == (Object)null))
			{
				_possessed.position = new Vector3(0f, 1f, 0f);
				_possessed.velocity = Vector3.zero;
				_possessed.angularVelocity = Vector3.zero;
				Main.Log.Msg("Teleported prop to spawn.");
			}
		}

		public static void Tick()
		{
			//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)
			ProcessDelayedCharControllerReenable();
			if (!_active)
			{
				return;
			}
			if ((Object)(object)_possessed == (Object)null)
			{
				EndPossession();
				return;
			}
			_lastKnownPos = _possessed.position;
			if (NetworkInfo.HasServer && _currentEntity != null && !_currentEntity.IsOwner)
			{
				_ownershipReclaimCooldown--;
				if (_ownershipReclaimCooldown <= 0)
				{
					NetworkEntityManager.TakeOwnership(_currentEntity);
					Main.Log.Msg("Ownership lost - reclaiming.");
					_ownershipReclaimCooldown = 20;
				}
			}
			if (Input.GetKeyDown((KeyCode)339) || Input.GetKeyDown((KeyCode)103))
			{
				EndPossession();
				return;
			}
			if (Input.GetKeyDown((KeyCode)331) || Input.GetKeyDown((KeyCode)98))
			{
				if (Time.time - _lastBTapTime < 0.4f)
				{
					TeleportPropToSpawn();
				}
				_lastBTapTime = Time.time;
			}
			if (Input.GetKeyDown((KeyCode)32) || Input.GetButtonDown("Jump") || Input.GetKeyDown((KeyCode)330) || Input.GetKeyDown((KeyCode)344))
			{
				_wantsToJump = true;
			}
			if (Input.GetKeyDown((KeyCode)338) || Input.GetKeyDown((KeyCode)114))
			{
				_wantsToSnapUpright = true;
			}
		}

		public static void LateTick()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//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_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_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: 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_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			if (!_active || (Object)(object)_possessed == (Object)null || _isDebugPossession)
			{
				return;
			}
			RigManager localRigManager = PropSelector.GetLocalRigManager();
			if ((Object)(object)localRigManager != (Object)null)
			{
				((Component)localRigManager).transform.position = _possessed.position + Vector3.down * 2.5f;
			}
			if ((Object)(object)_camTransform == (Object)null && (Object)(object)Camera.main != (Object)null)
			{
				_camTransform = ((Component)Camera.main).transform;
			}
			if ((Object)(object)_camTransform != (Object)null)
			{
				Vector3 val = _camTransform.forward;
				val.y = 0f;
				if (((Vector3)(ref val)).sqrMagnitude < 0.01f)
				{
					val = _camTransform.up;
				}
				((Vector3)(ref val)).Normalize();
				Vector3 val2 = -val * 2.5f + Vector3.up * 1.2f;
				_camTransform.position = _possessed.position + val2;
			}
		}

		public static void FixedTick()
		{
			//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_005b: 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_0079: 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_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: 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_013c: 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_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			if (!_active || (Object)(object)_possessed == (Object)null || _possessed.isKinematic || (NetworkInfo.HasServer && _currentEntity != null && !_currentEntity.IsOwner))
			{
				return;
			}
			if (_wantsToSnapUpright)
			{
				Rigidbody possessed = _possessed;
				Quaternion rotation = _possessed.rotation;
				possessed.MoveRotation(Quaternion.Euler(0f, ((Quaternion)(ref rotation)).eulerAngles.y, 0f));
				_possessed.angularVelocity = Vector3.zero;
				_wantsToSnapUpright = false;
			}
			float axis = Input.GetAxis("Horizontal");
			float axis2 = Input.GetAxis("Vertical");
			Transform val = (((Object)(object)_camTransform != (Object)null) ? _camTransform : (((Object)(object)Camera.main != (Object)null) ? ((Component)Camera.main).transform : null));
			Vector3 val2 = (((Object)(object)val != (Object)null) ? val.forward : Vector3.forward);
			Vector3 val3 = (((Object)(object)val != (Object)null) ? val.right : Vector3.right);
			val2.y = 0f;
			val3.y = 0f;
			((Vector3)(ref val2)).Normalize();
			((Vector3)(ref val3)).Normalize();
			Vector3 val4 = (val2 * axis2 + val3 * axis) * 5f - _possessed.velocity;
			val4.y = 0f;
			_possessed.AddForce(val4, (ForceMode)2);
			if (_wantsToJump)
			{
				if (Time.time - _lastJumpTime > 0.2f && IsPossessedGrounded())
				{
					_possessed.velocity = new Vector3(_possessed.velocity.x, 0f, _possessed.velocity.z);
					_possessed.AddForce(Vector3.up * 5f, (ForceMode)2);
					_lastJumpTime = Time.time;
				}
				_wantsToJump = false;
			}
		}

		private static bool IsPossessedGrounded()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: 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_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: 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)
			Collider componentInChildren = ((Component)_possessed).GetComponentInChildren<Collider>();
			float num;
			if (!((Object)(object)componentInChildren != (Object)null))
			{
				num = _possessed.position.y - 0.3f;
			}
			else
			{
				Bounds bounds = componentInChildren.bounds;
				num = ((Bounds)(ref bounds)).min.y;
			}
			float num2 = num;
			RaycastHit val = default(RaycastHit);
			if (Physics.Raycast(new Vector3(_possessed.position.x, num2 + 0.05f, _possessed.position.z), Vector3.down, ref val, 0.15f))
			{
				return (Object)(object)((RaycastHit)(ref val)).rigidbody != (Object)(object)_possessed;
			}
			return false;
		}
	}
	[RegisterTypeInIl2Cpp]
	public class FakePropDamageTracker : MonoBehaviour
	{
		public FakePropDamageTracker(IntPtr ptr)
			: base(ptr)
		{
		}

		private void OnCollisionEnter(Collision collision)
		{
			Main.Log.Msg("Shot propped player! Fake dummy hit by: '" + ((Object)collision.gameObject).name + "'.");
		}
	}
	public static class PropSelector
	{
		private static Page _rootPage;

		private static bool _debugMode = false;

		private const float ScanRadius = 15f;

		private const int MaxResults = 15;

		private static readonly List<FunctionElement> _dynamicElements = new List<FunctionElement>();

		public static bool DebugMode => _debugMode;

		public static void Init()
		{
			//IL_000a: 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_0064: Unknown result type (might be due to invalid IL or missing references)
			_rootPage = Page.Root.CreatePage("Prop Hunt", Color.cyan, 20, true);
			_rootPage.CreateFunction("Depropify (Return to Player)", Color.red, (Action)delegate
			{
				Main.Log.Msg("Manually depropified from BoneMenu.");
				PropifyController.EndPossession();
			});
			TouchPossess.Init(_rootPage);
			_rootPage.CreateBool("Debug Mode", Color.yellow, false, (Action<bool>)delegate(bool enabled)
			{
				_debugMode = enabled;
				Main.Log.Msg("[PropHunt] Debug Mode: " + (_debugMode ? "ENABLED" : "DISABLED"));
				RefreshMenu();
			});
			Menu.OnPageOpened += OnAnyPageOpened;
			RefreshMenu();
		}

		private static void OnAnyPageOpened(Page opened)
		{
			if (opened == _rootPage)
			{
				RefreshMenu();
			}
		}

		public static void RefreshMenu()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: 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_01b6: Unknown result type (might be due to invalid IL or missing references)
			if (_rootPage == null)
			{
				return;
			}
			ClearDynamicElements();
			if (!_debugMode)
			{
				Main.Log.Msg("NO LIST FOR YOU TIMMY");
				return;
			}
			FunctionElement item = _rootPage.CreateFunction("TP Prop to Me", Color.yellow, (Action)delegate
			{
				if (PropifyController.IsActive)
				{
					PropifyController.TeleportPropToPlayer();
				}
			});
			_dynamicElements.Add(item);
			FunctionElement item2 = _rootPage.CreateFunction("TP Prop to Spawn", Color.green, (Action)delegate
			{
				if (PropifyController.IsActive)
				{
					PropifyController.TeleportPropToSpawn();
				}
			});
			_dynamicElements.Add(item2);
			FunctionElement item3 = _rootPage.CreateFunction("Spawn Seeker Shotgun", Color.red, (Action)delegate
			{
				SpawnSeekerShotgun();
			});
			_dynamicElements.Add(item3);
			FunctionElement item4 = _rootPage.CreateFunction("Spawn Fake Propped Player", Color.magenta, (Action)delegate
			{
				PropifyController.SpawnFakeProppedPlayer();
			});
			_dynamicElements.Add(item4);
			List<Rigidbody> list = FindNearbyProps();
			Main.Log.Msg($"[Debug] Found {list.Count} nearby props.");
			foreach (Rigidbody rb in list)
			{
				string propName = ((Object)((Component)rb).gameObject).name;
				FunctionElement item5 = _rootPage.CreateFunction("Possess: " + propName, Color.white, (Action)delegate
				{
					Main.Log.Msg("[Debug] Selected prop: " + propName);
					PropifyController.BeginPossession(rb);
				});
				_dynamicElements.Add(item5);
			}
		}

		private static void ClearDynamicElements()
		{
			foreach (FunctionElement dynamicElement in _dynamicElements)
			{
				if (dynamicElement != null)
				{
					_rootPage.Remove((Element)(object)dynamicElement);
				}
			}
			_dynamicElements.Clear();
		}

		private static void SpawnSeekerShotgun()
		{
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			AmmoInventory instance = AmmoInventory.Instance;
			if ((Object)(object)instance != (Object)null)
			{
				AmmoGroup lightAmmoGroup = instance.lightAmmoGroup;
				CartridgeData val = ((lightAmmoGroup == null) ? null : ((IEnumerable<CartridgeData>)lightAmmoGroup.cartridges)?.FirstOrDefault());
				AmmoGroup mediumAmmoGroup = instance.mediumAmmoGroup;
				CartridgeData val2 = ((mediumAmmoGroup == null) ? null : ((IEnumerable<CartridgeData>)mediumAmmoGroup.cartridges)?.FirstOrDefault());
				AmmoGroup heavyAmmoGroup = instance.heavyAmmoGroup;
				CartridgeData val3 = ((heavyAmmoGroup == null) ? null : ((IEnumerable<CartridgeData>)heavyAmmoGroup.cartridges)?.FirstOrDefault());
				if ((Object)(object)val != (Object)null)
				{
					instance.AddCartridge(val, 6);
				}
				if ((Object)(object)val2 != (Object)null)
				{
					instance.AddCartridge(val2, 6);
				}
				if ((Object)(object)val3 != (Object)null)
				{
					instance.AddCartridge(val3, 6);
				}
				Main.Log.Msg("[PropHunt] Granted seeker shotgun ammo.");
			}
			HelperMethods.SpawnCrate("c1534c5a-7f05-402f-9320-609647756e35", GetPlayerPosition() + Vector3.up, Quaternion.identity, Vector3.one, false, (Action<GameObject>)delegate(GameObject spawnedObject)
			{
				if (!((Object)(object)spawnedObject == (Object)null))
				{
					MelonCoroutines.Start(DelayedLoadShells(spawnedObject));
				}
			}, (Action<GameObject>)null);
		}

		private static IEnumerator DelayedLoadShells(GameObject spawnedObject)
		{
			yield return (object)new WaitForSeconds(0.2f);
			if (!((Object)(object)spawnedObject == (Object)null))
			{
				Gun componentInChildren = spawnedObject.GetComponentInChildren<Gun>();
				if (!((Object)(object)componentInChildren == (Object)null) && componentInChildren._magState != null)
				{
					componentInChildren._magState.SetCartridge(6);
				}
			}
		}

		public static List<Rigidbody> FindNearbyProps()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: 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_009e: Unknown result type (might be due to invalid IL or missing references)
			Vector3 origin = GetPlayerPosition();
			List<Rigidbody> list = new List<Rigidbody>();
			RigManager localRigManager = GetLocalRigManager();
			foreach (Poolee item in Object.FindObjectsOfType<Poolee>())
			{
				if (!((Object)(object)item == (Object)null))
				{
					Rigidbody componentInChildren = ((Component)item).GetComponentInChildren<Rigidbody>();
					if (IsValidProp(componentInChildren, origin, localRigManager))
					{
						list.Add(componentInChildren);
					}
				}
			}
			foreach (InteractableHost item2 in Object.FindObjectsOfType<InteractableHost>())
			{
				if (!((Object)(object)item2 == (Object)null))
				{
					Rigidbody componentInChildren2 = ((Component)item2).GetComponentInChildren<Rigidbody>();
					if (IsValidProp(componentInChildren2, origin, localRigManager) && !list.Contains(componentInChildren2))
					{
						list.Add(componentInChildren2);
					}
				}
			}
			return (from rb in list.Distinct()
				orderby Vector3.Distance(origin, rb.position)
				select rb).Take(15).ToList();
		}

		public static bool IsValidPropPublic(Rigidbody rb, Vector3 origin, RigManager rigManager)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return IsValidProp(rb, origin, rigManager);
		}

		private static bool IsValidProp(Rigidbody rb, Vector3 origin, RigManager rigManager)
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)rb == (Object)null || rb.isKinematic)
			{
				return false;
			}
			if ((Object)(object)rigManager != (Object)null && ((Component)rb).transform.IsChildOf(((Component)rigManager).transform))
			{
				return false;
			}
			string text = ((Object)((Component)rb).gameObject).name.ToLower();
			if (text.Contains("avatar") || text.Contains("head") || text.Contains("hand") || text.Contains("foot"))
			{
				return false;
			}
			return Vector3.Distance(origin, rb.position) <= 15f;
		}

		public static RigManager GetLocalRigManager()
		{
			return Player.RigManager;
		}

		public static Vector3 GetPlayerPosition()
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: 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)
			RigManager localRigManager = GetLocalRigManager();
			if ((Object)(object)localRigManager != (Object)null && (Object)(object)localRigManager.physicsRig != (Object)null)
			{
				return ((Component)localRigManager.physicsRig).transform.position;
			}
			Camera main = Camera.main;
			if (!((Object)(object)main != (Object)null))
			{
				return Vector3.zero;
			}
			return ((Component)main).transform.position;
		}
	}
	public static class TouchPossess
	{
		private static bool _armed;

		private const float HandTouchRadius = 0.15f;

		public static void Init(Page parentPage)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			parentPage.CreateBool("Transform to Prop (Touch)", Color.cyan, false, (Action<bool>)OnToggled);
		}

		private static void OnToggled(bool enabled)
		{
			_armed = enabled;
			Main.Log.Msg("[PropHunt] Touch-to-possess mode: " + (enabled ? "ARMED" : "off"));
		}

		public static void Arm()
		{
			_armed = true;
			Main.Log.Msg("[PropHunt] Touch-to-possess mode: ARMED (external trigger)");
		}

		public static void FixedTick()
		{
			//IL_0043: 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 (_armed && !PropifyController.IsActive && !((Object)(object)PropSelector.GetLocalRigManager() == (Object)null))
			{
				Hand leftHand = Player.LeftHand;
				Hand rightHand = Player.RightHand;
				if (!TryPossessNear(((Object)(object)leftHand != (Object)null) ? new Vector3?(((Component)leftHand).transform.position) : ((Vector3?)null)))
				{
					TryPossessNear(((Object)(object)rightHand != (Object)null) ? new Vector3?(((Component)rightHand).transform.position) : ((Vector3?)null));
				}
			}
		}

		private static bool TryPossessNear(Vector3? handPos)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			if (!handPos.HasValue)
			{
				return false;
			}
			Il2CppReferenceArray<Collider> obj = Physics.OverlapSphere(handPos.Value, 0.15f);
			RigManager localRigManager = PropSelector.GetLocalRigManager();
			foreach (Collider item in (Il2CppArrayBase<Collider>)(object)obj)
			{
				if (!((Object)(object)item == (Object)null))
				{
					Rigidbody attachedRigidbody = item.attachedRigidbody;
					if (!((Object)(object)attachedRigidbody == (Object)null) && PropSelector.IsValidPropPublic(attachedRigidbody, handPos.Value, localRigManager))
					{
						Main.Log.Msg("[PropHunt] Touch-selected '" + ((Object)((Component)attachedRigidbody).gameObject).name + "'. Creating copy...");
						PropifyController.BeginPossession(attachedRigidbody);
						_armed = false;
						return true;
					}
				}
			}
			return false;
		}
	}
}