Decompiled source of I Am Item v1.0.1

IamItem.dll

Decompiled 2 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.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 IamItem
{
	internal static class Balance
	{
		public static float DurationFor(float baseDuration, float upgradeLevel)
		{
			float num = baseDuration;
			float num2 = baseDuration * 0.2f;
			for (float num3 = upgradeLevel; num3 > 0f; num3 -= 1f)
			{
				num += num2;
				num2 *= 0.95f;
			}
			if (!(num < 1f))
			{
				return num;
			}
			return 1f;
		}

		public static int JumpsPerBar(float jumpCost, float idleSeconds, float secondsPerJump)
		{
			float num = jumpCost;
			if (idleSeconds > 0f)
			{
				num += secondsPerJump / idleSeconds;
			}
			if (num <= 0f)
			{
				return int.MaxValue;
			}
			return (int)(1f / num);
		}
	}
	internal static class Cfg
	{
		public static ConfigEntry<bool> Enabled;

		public static ConfigEntry<string> PossessKeyName;

		public static ConfigEntry<float> PossessionDuration;

		public static ConfigEntry<float> EntryCost;

		public static ConfigEntry<float> MinEnergyToPossess;

		public static ConfigEntry<float> JumpCost;

		public static ConfigEntry<float> CrawlSpeed;

		public static ConfigEntry<float> CrawlAcceleration;

		public static ConfigEntry<float> CrawlSpin;

		public static ConfigEntry<float> ExitGraceSeconds;

		public static ConfigEntry<float> ExitGraceMaxSeconds;

		public static ConfigEntry<bool> ValuableShield;

		public static ConfigEntry<float> GrabShieldDelay;

		public static ConfigEntry<bool> RamEnabled;

		public static ConfigEntry<float> RamMinSpeed;

		public static ConfigEntry<float> RamFullSpeed;

		public static ConfigEntry<int> RamDamage;

		public static ConfigEntry<float> RamHitCooldown;

		public static ConfigEntry<bool> RamHurtsPlayers;

		public static ConfigEntry<int> RamPlayerDamage;

		public static ConfigEntry<bool> RamTumblesPlayers;

		public static ConfigEntry<float> WallHitCostLight;

		public static ConfigEntry<float> WallHitCostMedium;

		public static ConfigEntry<float> WallHitCostHeavy;

		public static ConfigEntry<float> RattleCost;

		public static ConfigEntry<float> RattleRadiusLight;

		public static ConfigEntry<float> RattleRadiusMedium;

		public static ConfigEntry<float> RattleRadiusHeavy;

		public static ConfigEntry<float> KnockCost;

		public static ConfigEntry<bool> HeavySlideOnly;

		public static ConfigEntry<bool> SadPhrasesEnabled;

		public static ConfigEntry<bool> CartPhrasesEnabled;

		public static ConfigEntry<bool> BreakPhrasesEnabled;

		public static ConfigEntry<bool> ShowPossessorName;

		public static ConfigEntry<bool> PreviewEnabled;

		public static ConfigEntry<int> PreviewCount;

		public static ConfigEntry<bool> GlowEnabled;

		public static ConfigEntry<float> CameraDistance;

		private static readonly string[] KeyChoices = new string[24]
		{
			"Q", "R", "T", "F", "G", "H", "V", "B", "C", "X",
			"Z", "Alpha1", "Alpha2", "Alpha3", "Alpha4", "Alpha5", "Space", "Tab", "LeftAlt", "LeftControl",
			"LeftShift", "Mouse2", "Mouse3", "Mouse4"
		};

		private const KeyCode DefaultKey = (KeyCode)118;

		public static KeyCode PossessKey
		{
			get
			{
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				if (!Enum.TryParse<KeyCode>(PossessKeyName.Value, out KeyCode result))
				{
					return (KeyCode)118;
				}
				return result;
			}
		}

		private static ConfigEntry<float> Range(ConfigFile c, string section, string key, float value, float min, float max, string description)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			return c.Bind<float>(section, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(min, max), Array.Empty<object>()));
		}

		private static ConfigEntry<int> Range(ConfigFile c, string section, string key, int value, int min, int max, string description)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			return c.Bind<int>(section, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<int>(min, max), Array.Empty<object>()));
		}

		public static void Bind(ConfigFile c)
		{
			//IL_0028: 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_0054: Expected O, but got Unknown
			Enabled = c.Bind<bool>("General", "Enabled", true, "Master switch for the whole mod.");
			PossessKeyName = c.Bind<string>("General", "PossessKey", ((object)(KeyCode)118/*cast due to .constrained prefix*/).ToString(), new ConfigDescription("Key a dead spectating player presses to possess a random valuable. Exit is the vanilla Interact key (E).", (AcceptableValueBase)(object)new AcceptableValueList<string>(KeyChoices), Array.Empty<object>()));
			PossessionDuration = Range(c, "Balance", "PossessionDuration", 90f, 5f, 600f, "Seconds a full stamina bar lasts while doing nothing at all, before the Death Head Battery upgrade. Every action costs on top of this.");
			EntryCost = Range(c, "Balance", "EntryCost", 1f, 0f, 1f, "Head energy spent the moment you possess. This is the cooldown between possessions: head energy refills on its own, stamina inside the item is a separate bar.");
			MinEnergyToPossess = Range(c, "Balance", "MinEnergyToPossess", 0.75f, 0f, 1f, "Head energy needed before possession is allowed. Share of the bar, 0..1. Head energy refills in about 100 seconds, so 0.75 is roughly a 75 second wait.");
			JumpCost = Range(c, "Balance", "JumpCost", 0.085f, 0f, 1f, "Stamina spent per jump or dash, on top of the idle drain. 0.085 leaves about 8 jumps on a full bar.");
			ExitGraceSeconds = Range(c, "Balance", "ExitGraceSeconds", 3f, 0f, 30f, "Seconds the item has to lie still after the ghost leaves before it can break again. The item is indestructible until it has settled: a fixed grace ran out while the item was still rolling and it smashed anyway.");
			ExitGraceMaxSeconds = Range(c, "Balance", "ExitGraceMaxSeconds", 20f, 0f, 120f, "Hard ceiling on that protection, seconds. Stops an item that never settles - falling down a shaft, stuck spinning - from staying indestructible forever.");
			CameraDistance = Range(c, "General", "CameraDistance", 0.6f, 0f, 5f, "Metres the camera keeps behind the possessed item, on top of the item's own size. 0 puts the camera inside the item, first person.");
			ValuableShield = c.Bind<bool>("Shield", "ValuableShield", true, "While a ghost is inside, the item loses no money from any impact. Deadly pits, ram mode and living hands still break it.");
			GrabShieldDelay = Range(c, "Shield", "GrabShieldDelay", 1.5f, 0f, 10f, "Seconds the shield stays off after a living player lets the item go. While the item is in someone's hands it breaks by the normal rules of the game.");
			RamEnabled = c.Bind<bool>("Ram", "RamEnabled", true, "A possessed item moving fast enough hurts what it hits. No key to press: speed is the weapon. The item itself never loses money for it - the risk is where you end up, who you hit and what you break.");
			RamMinSpeed = Range(c, "Ram", "RamMinSpeed", 5f, 0f, 30f, "Metres per second below which a hit does no damage at all. Crawling never hurts anyone.");
			RamFullSpeed = Range(c, "Ram", "RamFullSpeed", 12f, 1f, 50f, "Metres per second that counts as a full power hit. Between this and RamMinSpeed damage scales up.");
			RamDamage = Range(c, "Ram", "RamDamage", 35, 0, 200, "Damage a full power hit does to an enemy, before the item size multiplier (small 0.6, medium 1.0, big 1.6) and the enemy's own object damage multiplier. Enough to finish small enemies, not enough to solo a big one.");
			RamHitCooldown = Range(c, "Ram", "RamHitCooldown", 0.6f, 0f, 5f, "Seconds between damaging hits. Stops one long roll from counting as ten hits.");
			RamHurtsPlayers = c.Bind<bool>("Ram", "RamHurtsPlayers", true, "A fast item hurts living players too. This is the price of a heavy item flying down a corridor.");
			RamPlayerDamage = Range(c, "Ram", "RamPlayerDamage", 18, 0, 200, "Damage a full power hit does to a living player, before the item size multiplier.");
			RamTumblesPlayers = c.Bind<bool>("Ram", "RamTumblesPlayers", true, "A fast item also knocks a living player off their feet.");
			WallHitCostLight = Range(c, "Impacts", "WallHitCostLight", 0f, 0f, 1f, "Stamina lost on a light impact. Zero by default: landing after your own jump counts as a light impact, and charging for that punished simply moving around.");
			WallHitCostMedium = Range(c, "Impacts", "WallHitCostMedium", 0.05f, 0f, 1f, "Stamina lost on a medium impact.");
			WallHitCostHeavy = Range(c, "Impacts", "WallHitCostHeavy", 0.1f, 0f, 1f, "Stamina lost on a heavy impact.");
			RattleCost = Range(c, "Noise", "RattleCost", 0.04f, 0f, 1f, "Stamina spent per rattle.");
			RattleRadiusLight = Range(c, "Noise", "RattleRadiusLight", 6f, 0f, 50f, "Enemy attract radius for Tiny and Small items, meters.");
			RattleRadiusMedium = Range(c, "Noise", "RattleRadiusMedium", 9f, 0f, 50f, "Enemy attract radius for Medium items, meters.");
			RattleRadiusHeavy = Range(c, "Noise", "RattleRadiusHeavy", 14f, 0f, 50f, "Enemy attract radius for Big and larger items, meters.");
			KnockCost = Range(c, "Noise", "KnockCost", 0.02f, 0f, 1f, "Stamina spent per knock while a living player holds the item.");
			CrawlSpeed = Range(c, "Movement", "CrawlSpeed", 3.5f, 0f, 20f, "Top speed of WASD crawling along the floor, metres per second. 0 turns crawling off, jumps only. Heavy items are capped lower by their own speed limit.");
			CrawlAcceleration = Range(c, "Movement", "CrawlAcceleration", 14f, 0f, 100f, "How hard the item is pushed towards CrawlSpeed. A flat push lost to floor friction and items only rocked in place.");
			CrawlSpin = Range(c, "Movement", "CrawlSpin", 6f, 0f, 50f, "Extra roll applied across the crawl direction so the item rolls instead of sliding. 0 turns rolling off.");
			HeavySlideOnly = c.Bind<bool>("Movement", "HeavySlideOnly", true, "Big, Wide, Tall and VeryTall items slide along the floor instead of jumping.");
			SadPhrasesEnabled = c.Bind<bool>("Phrases", "SadPhrasesEnabled", true, "Phrase when a living player picks up a possessed item.");
			CartPhrasesEnabled = c.Bind<bool>("Phrases", "CartPhrasesEnabled", true, "Phrase when a possessed item goes into the cart.");
			BreakPhrasesEnabled = c.Bind<bool>("Phrases", "BreakPhrasesEnabled", true, "Phrase when a possessed item is destroyed.");
			ShowPossessorName = c.Bind<bool>("Visuals", "ShowPossessorName", false, "Draw the possessing player name above the item.");
			PreviewEnabled = c.Bind<bool>("Visuals", "PreviewEnabled", true, "Spinning valuable models above the spectate head, so a dead player can see the mod exists before the bar is full. They are real items from this level, picked at random.");
			PreviewCount = Range(c, "Visuals", "PreviewCount", 3, 1, 5, "How many models stand on the shelf, 1 to 5. They are picked once per death and just spin.");
			GlowEnabled = c.Bind<bool>("Visuals", "GlowEnabled", true, "Fresnel glow on a possessed item.");
		}
	}
	internal static class Effects
	{
		public static void Teleport(Vector3 position)
		{
			//IL_0023: 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)
			GameObject val = (Object.op_Implicit((Object)(object)AssetManager.instance) ? AssetManager.instance.prefabTeleportEffect : null);
			if (Object.op_Implicit((Object)(object)val))
			{
				Object.Instantiate<GameObject>(val, position, Quaternion.identity);
			}
		}

		public static void PlayEquip(Vector3 position)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			AssetManager instance = AssetManager.instance;
			if (instance != null)
			{
				Sound soundEquip = instance.soundEquip;
				if (soundEquip != null)
				{
					soundEquip.Play(position, 1f, 1f, 1f, 1f);
				}
			}
		}

		public static void PlayUnequip(Vector3 position)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			AssetManager instance = AssetManager.instance;
			if (instance != null)
			{
				Sound soundUnequip = instance.soundUnequip;
				if (soundUnequip != null)
				{
					soundUnequip.Play(position, 1f, 1f, 1f, 1f);
				}
			}
		}
	}
	internal static class Speech
	{
		private static readonly Queue<string> pending = new Queue<string>();

		public static void Tick()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			if (pending.Count == 0)
			{
				return;
			}
			ChatManager instance = ChatManager.instance;
			if (Object.op_Implicit((Object)(object)instance) && instance.StateIsInactive())
			{
				if ((int)instance.currentPossessChatID != 0)
				{
					instance.currentPossessChatID = (PossessChatID)0;
				}
				string text = pending.Dequeue();
				instance.PossessChatScheduleStart(20);
				instance.PossessChat((PossessChatID)2, text, 1f, new Color(0.75f, 0.75f, 0.8f, 1f), 0f, false, 0, (UnityEvent)null);
				instance.PossessChatScheduleEnd();
			}
		}

		public static void Say(string message)
		{
			if (!string.IsNullOrEmpty(message))
			{
				pending.Enqueue(message);
			}
		}
	}
	internal static class GhostCamera
	{
		private static bool entered;

		private static float settleTimer;

		public static void Enter()
		{
			entered = false;
			settleTimer = 0.5f;
		}

		public static void Exit()
		{
			entered = false;
			SpectateCamera instance = SpectateCamera.instance;
			if (Object.op_Implicit((Object)(object)instance))
			{
				instance.stateImpulse = true;
			}
		}

		private static Vector3 ViewPoint(SpectateCamera cam, PhysGrabObject target)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			float value = Cfg.CameraDistance.Value;
			if (value <= 0f)
			{
				return target.centerPoint;
			}
			Camera val = (Object.op_Implicit((Object)(object)GameDirector.instance) ? GameDirector.instance.MainCamera : null);
			Transform obj = (Object.op_Implicit((Object)(object)val) ? ((Component)val).transform : ((Component)cam).transform);
			Vector3 val2 = obj.position - ((Component)cam).transform.position;
			float num = ((Vector3)(ref target.boundingBox)).magnitude * 0.5f + 0.15f;
			float num2 = num + value;
			Vector3 val3 = -obj.forward;
			RaycastHit val4 = default(RaycastHit);
			if (Physics.SphereCast(target.centerPoint, 0.15f, val3, ref val4, num2, LayerMask.GetMask(new string[2] { "Default", "StaticGrabObject" }), (QueryTriggerInteraction)1))
			{
				num2 = ((RaycastHit)(ref val4)).distance - 0.1f;
			}
			if (num2 < num)
			{
				num2 = num;
			}
			return target.centerPoint + val3 * num2 - val2;
		}

		public static void Tick(Possession possession)
		{
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: 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)
			//IL_01dc: 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)
			SpectateCamera instance = SpectateCamera.instance;
			PhysGrabObject target = possession.Target;
			if (!Object.op_Implicit((Object)(object)instance) || !Object.op_Implicit((Object)(object)target))
			{
				return;
			}
			SemiFunc.UIHideHealth();
			SemiFunc.UIHideOvercharge();
			SemiFunc.UIHideEnergy();
			SemiFunc.UIHideInventory();
			SemiFunc.UIHideAim();
			if (Object.op_Implicit((Object)(object)MissionUI.instance))
			{
				((SemiUI)MissionUI.instance).Hide();
			}
			Camera val = (Object.op_Implicit((Object)(object)GameDirector.instance) ? GameDirector.instance.MainCamera : null);
			if (!entered)
			{
				entered = true;
				((Component)instance).transform.position = ViewPoint(instance, target);
				if (Object.op_Implicit((Object)(object)val))
				{
					val.nearClipPlane = 0.01f;
				}
				CameraGlitch.Instance.PlayTiny();
				GameDirector.instance.CameraImpact.Shake(1f, 0.1f);
				AudioManager.instance.RestartAudioLoopDistances();
				LevelGenerator.Instance.RestartParticleDistances();
				SemiFunc.LightManagerSetCullTargetTransform(((Component)instance).transform);
				CameraAim.Instance.OverridePlayerAimDisableReset();
				CameraAim.Instance.SetPlayerAim(((Component)target).transform.rotation, true);
				PlayerController.instance.playerAvatarScript.localCamera.Teleported();
				AudioManager.instance.AudioListener.TargetPositionTransform = ((Component)instance).transform;
			}
			if (settleTimer > 0f)
			{
				settleTimer -= Time.deltaTime;
			}
			PostProcessing.Instance.VignetteOverride(Color.black, 0.4f, 1f, 5f, 5f, 0.1f, ((Component)instance).gameObject);
			PostProcessing.Instance.SaturationOverride(-50f, 20f, 20f, 0.1f, ((Component)instance).gameObject);
			CameraNoise.Instance.Override(0.03f, 0.25f);
			((Component)instance).transform.localRotation = Quaternion.identity;
			((Component)instance).transform.position = Vector3.Lerp(((Component)instance).transform.position, ViewPoint(instance, target), 25f * Time.deltaTime);
			RoomVolumeCheck roomVolumeCheck = PlayerController.instance.playerAvatarScript.RoomVolumeCheck;
			roomVolumeCheck.PauseCheckTimer = 1f;
			if (Object.op_Implicit((Object)(object)target.roomVolumeCheck))
			{
				roomVolumeCheck.CurrentRooms.Clear();
				roomVolumeCheck.CurrentRooms.AddRange(target.roomVolumeCheck.CurrentRooms);
			}
		}
	}
	internal sealed class Glow
	{
		private struct Entry
		{
			public Material material;

			public bool hasFresnel;

			public Color originalColor;

			public float originalPower;

			public Color originalEmission;
		}

		private static readonly int FresnelColor = Shader.PropertyToID("_FresnelColor");

		private static readonly int FresnelPower = Shader.PropertyToID("_FresnelPower");

		private static readonly int EmissionColor = Shader.PropertyToID("_EmissionColor");

		private readonly List<Entry> entries = new List<Entry>();

		private readonly List<Renderer> touched = new List<Renderer>();

		private readonly List<Material[]> originalArrays = new List<Material[]>();

		public Color BaseColor = Color.cyan;

		public void Attach(GameObject root)
		{
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			Detach();
			if (!Cfg.GlowEnabled.Value || !Object.op_Implicit((Object)(object)root))
			{
				return;
			}
			Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if (!Object.op_Implicit((Object)(object)val) || val.sharedMaterials == null || val.sharedMaterials.Length == 0)
				{
					continue;
				}
				originalArrays.Add(val.sharedMaterials);
				touched.Add(val);
				Material[] materials = val.materials;
				foreach (Material val2 in materials)
				{
					if (!Object.op_Implicit((Object)(object)val2))
					{
						continue;
					}
					Entry item = new Entry
					{
						material = val2
					};
					if (val2.HasProperty(FresnelColor) && val2.HasProperty(FresnelPower))
					{
						item.hasFresnel = true;
						item.originalColor = val2.GetColor(FresnelColor);
						item.originalPower = val2.GetFloat(FresnelPower);
					}
					else
					{
						if (!val2.HasProperty(EmissionColor))
						{
							continue;
						}
						item.originalEmission = val2.GetColor(EmissionColor);
					}
					entries.Add(item);
				}
			}
			if (entries.Count == 0 && touched.Count > 0)
			{
				Plugin.Log.LogWarning((object)("No glowable material on " + ((Object)root).name + ", item stays unlit."));
			}
		}

		public void Tick(bool ram)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: 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_00a8: Unknown result type (might be due to invalid IL or missing references)
			if (entries.Count == 0)
			{
				return;
			}
			Color val = (ram ? Color.red : BaseColor);
			float num = (ram ? 9f : 3f);
			float num2 = 0.5f + 0.5f * Mathf.Sin(Time.time * num);
			float num3 = Mathf.Lerp(ram ? 1.2f : 2.5f, ram ? 0.4f : 1.2f, num2);
			foreach (Entry entry in entries)
			{
				if (Object.op_Implicit((Object)(object)entry.material))
				{
					if (entry.hasFresnel)
					{
						entry.material.SetColor(FresnelColor, val);
						entry.material.SetFloat(FresnelPower, num3);
					}
					else
					{
						entry.material.SetColor(EmissionColor, val * Mathf.Lerp(0.15f, 0.6f, num2));
					}
				}
			}
		}

		public void Detach()
		{
			for (int i = 0; i < touched.Count; i++)
			{
				if (Object.op_Implicit((Object)(object)touched[i]))
				{
					touched[i].sharedMaterials = originalArrays[i];
				}
			}
			foreach (Entry entry in entries)
			{
				if (Object.op_Implicit((Object)(object)entry.material))
				{
					Object.Destroy((Object)(object)entry.material);
				}
			}
			entries.Clear();
			touched.Clear();
			originalArrays.Clear();
		}
	}
	internal sealed class Hud : MonoBehaviour
	{
		private static string message;

		private static float messageTimer;

		private static Texture2D white;

		private GUIStyle centered;

		public static void Message(string text, float seconds)
		{
			message = text;
			messageTimer = seconds;
		}

		private void Update()
		{
			if (messageTimer > 0f)
			{
				messageTimer -= Time.deltaTime;
			}
			Speech.Tick();
			PossessPrompt.Tick();
			ExitGrace.Tick();
			for (int num = Possession.All.Count - 1; num >= 0; num--)
			{
				Possession possession = Possession.All[num];
				if (Object.op_Implicit((Object)(object)possession))
				{
					possession.Tick();
				}
			}
		}

		private void FixedUpdate()
		{
			for (int num = Possession.All.Count - 1; num >= 0; num--)
			{
				Possession possession = Possession.All[num];
				if (Object.op_Implicit((Object)(object)possession))
				{
					possession.PhysicsTick();
				}
			}
		}

		private void OnGUI()
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Unknown result type (might be due to invalid IL or missing references)
			//IL_0272: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)white))
			{
				white = new Texture2D(1, 1);
				white.SetPixel(0, 0, Color.white);
				white.Apply();
				((Object)white).hideFlags = (HideFlags)61;
			}
			if (centered == null)
			{
				centered = new GUIStyle(GUI.skin.label)
				{
					alignment = (TextAnchor)4,
					fontSize = 16
				};
			}
			if (messageTimer > 0f && !string.IsNullOrEmpty(message))
			{
				GUI.color = Color.white;
				GUI.Label(new Rect(0f, (float)Screen.height * 0.35f, (float)Screen.width, 30f), message, centered);
			}
			DrawPossessorNames();
			Possession local = Possession.Local;
			if ((Object)(object)local == (Object)null || !local.Active)
			{
				GUI.color = Color.white;
				return;
			}
			float localStamina = Possession.LocalStamina;
			float num = (float)Screen.width * 0.28f;
			float num2 = 10f;
			float num3 = ((float)Screen.width - num) * 0.5f;
			float num4 = (float)Screen.height - 90f;
			Color color = (Color)((localStamina < 0.15f) ? Color.Lerp(new Color(0.4f, 0f, 0f), Color.red, Mathf.PingPong(Time.time * 4f, 1f)) : new Color(0.55f, 0.85f, 1f));
			Fill(new Rect(num3 - 2f, num4 - 2f, num + 4f, num2 + 4f), new Color(0f, 0f, 0f, 0.55f));
			Fill(new Rect(num3, num4, num * Mathf.Clamp01(localStamina), num2), color);
			if (local.ChargeVisual > 0.01f)
			{
				Fill(new Rect(num3, num4 + num2 + 6f, num * Mathf.Clamp01(local.ChargeVisual), 5f), new Color(1f, 0.85f, 0.2f));
			}
			GUI.color = new Color(1f, 1f, 1f, 0.85f);
			string text = ((local.Class == ItemClass.Heavy) ? "WASD  crawl    Space  slide    LMB  noise    E  leave" : "WASD  crawl    Space  jump     LMB  noise    E  leave");
			GUI.Label(new Rect(0f, num4 - 56f, (float)Screen.width, 24f), text, centered);
			GUI.color = Color.white;
		}

		private void DrawPossessorNames()
		{
			//IL_0116: 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_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: 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)
			if (!Cfg.ShowPossessorName.Value)
			{
				return;
			}
			Camera main = Camera.main;
			if (!Object.op_Implicit((Object)(object)main))
			{
				return;
			}
			foreach (Possession item in Possession.All)
			{
				if (item.Active && Object.op_Implicit((Object)(object)item.avatar) && Object.op_Implicit((Object)(object)item.Target))
				{
					Vector3 val = item.Target.centerPoint + Vector3.up * 0.35f;
					Vector3 val2 = main.WorldToScreenPoint(val);
					if (!(val2.z <= 0f))
					{
						GUI.color = new Color(1f, 1f, 1f, 0.85f);
						GUI.Label(new Rect(val2.x - 100f, (float)Screen.height - val2.y - 12f, 200f, 24f), item.avatar.playerName, centered);
					}
				}
			}
			GUI.color = Color.white;
		}

		private static void Fill(Rect rect, Color color)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			GUI.color = color;
			GUI.DrawTexture(rect, (Texture)(object)white);
			GUI.color = Color.white;
		}
	}
	[HarmonyPatch(typeof(PlayerAvatar), "Start")]
	internal static class PlayerAvatarStartPatch
	{
		private static void Postfix(PlayerAvatar __instance)
		{
			if (Cfg.Enabled.Value && !Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<Possession>()) && Object.op_Implicit((Object)(object)GameDirector.instance) && GameDirector.instance.PlayerList.Contains(__instance))
			{
				((Component)__instance).gameObject.AddComponent<Possession>();
				PhotonView component = ((Component)__instance).GetComponent<PhotonView>();
				if (Object.op_Implicit((Object)(object)component))
				{
					component.RefreshRpcMonoBehaviourCache();
				}
			}
		}
	}
	[HarmonyPatch(typeof(SpectateCamera), "LateUpdate")]
	internal static class SpectateCameraLateUpdatePatch
	{
		private static bool Prefix()
		{
			Possession local = Possession.Local;
			if ((Object)(object)local == (Object)null || !local.Active)
			{
				return true;
			}
			GhostCamera.Tick(local);
			return false;
		}
	}
	[HarmonyPatch(typeof(SpectateCamera), "HeadEnergyLogic")]
	internal static class HeadEnergyLogicPatch
	{
		private static bool Prefix()
		{
			Possession local = Possession.Local;
			if (!((Object)(object)local == (Object)null))
			{
				return !local.Active;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(SpectateCamera), "Update")]
	internal static class SpectateCameraUpdatePatch
	{
		private static void Postfix()
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			if (Cfg.Enabled.Value && (!Object.op_Implicit((Object)(object)MenuManager.instance) || !Object.op_Implicit((Object)(object)MenuManager.instance.currentMenuPage)) && (!Object.op_Implicit((Object)(object)ChatManager.instance) || !ChatManager.instance.StateIsActive()) && Input.GetKeyDown(Cfg.PossessKey) && Possession.CanPossess())
			{
				Possession.Local.RequestPossess();
			}
		}
	}
	[HarmonyPatch(typeof(PhysGrabObject), "GrabStarted")]
	internal static class GrabStartedPatch
	{
		private static void Prefix(PhysGrabObject __instance, out bool __state)
		{
			__state = __instance.grabbedLocal;
		}

		private static void Postfix(PhysGrabObject __instance, PhysGrabber player, bool __state)
		{
			if (!__state && Cfg.Enabled.Value && Cfg.SadPhrasesEnabled.Value && Object.op_Implicit((Object)(object)player) && Object.op_Implicit((Object)(object)player.playerAvatar) && player.playerAvatar.isLocal && Possession.IsPossessed(__instance))
			{
				Speech.Say(Phrases.Pick(Phrases.Pickup));
			}
		}
	}
	[HarmonyPatch(typeof(PhysGrabObject), "DeathPitEffectCreate")]
	internal static class DeathPitPatch
	{
		private static bool Prefix(PhysGrabObject __instance)
		{
			if (!Cfg.Enabled.Value)
			{
				return true;
			}
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				return true;
			}
			Possession possession = Possession.Of(__instance);
			if ((Object)(object)possession == (Object)null)
			{
				return true;
			}
			possession.KillInDeathPit();
			return false;
		}
	}
	[HarmonyPatch(typeof(PhysGrabObjectImpactDetector), "DestroyObject")]
	internal static class DestroyObjectPatch
	{
		private static void Prefix(PhysGrabObjectImpactDetector __instance)
		{
			if (Cfg.Enabled.Value && SemiFunc.IsMasterClientOrSingleplayer())
			{
				Possession possession = Possession.Of(__instance.physGrabObject);
				if ((Object)(object)possession != (Object)null && possession.Active)
				{
					possession.Stop(StopReason.Destroyed);
				}
			}
		}
	}
	internal static class Phrases
	{
		public static readonly string[] Pickup = new string[20]
		{
			"Sorry, I need to sell you, friend.", "Mate, you will serve the future, sorry.", "It is nothing personal. It is just money.", "You were a good teammate. Now you are good money.", "I promise I will spend you well.", "Rest now, buddy. The truck is waiting.", "Please do not look at me like that.", "I really hate this job.", "You always wanted to be useful.", "One last ride, pal.",
			"I will tell them you went quietly.", "Please stop rattling. It is harder this way.", "We all end up in the cart eventually.", "Say hello to the taxman for me.", "Sorry. The rent is due.", "You feel heavier than you looked.", "This is exactly why I have no friends.", "I would carry you out, but you are the loot now.", "Forgive me. The quota does not.", "You are worth more like this. Sorry."
		};

		public static readonly string[] Cart = new string[7] { "Goodbye, friend.", "In you go.", "Try to be worth something.", "It is warm in there. Probably.", "See you next level. Maybe.", "You are officially cargo now.", "Sleep well, little guy." };

		public static readonly string[] Break = new string[5] { "Oh no. Oh no no no.", "That was a person.", "I did not do that.", "We do not talk about this.", "He was already broken. Probably." };

		private static readonly Dictionary<string[], int> lastIndex = new Dictionary<string[], int>();

		public static string Pick(string[] set)
		{
			if (set == null || set.Length == 0)
			{
				return null;
			}
			if (set.Length == 1)
			{
				return set[0];
			}
			lastIndex.TryGetValue(set, out var value);
			int num;
			do
			{
				num = Random.Range(0, set.Length);
			}
			while (num == value);
			lastIndex[set] = num;
			return set[num];
		}
	}
	[BepInPlugin("sweet.iamitem", "I Am Item", "1.0.1")]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "sweet.iamitem";

		public const string Name = "I Am Item";

		public const string Version = "1.0.1";

		internal static ManualLogSource Log;

		private static Harmony harmony;

		private void Awake()
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			Cfg.Bind(((BaseUnityPlugin)this).Config);
			if (!Cfg.Enabled.Value)
			{
				Log.LogInfo((object)"I Am Item disabled in config, patches not applied.");
				return;
			}
			harmony = new Harmony("sweet.iamitem");
			harmony.PatchAll();
			GameObject val = new GameObject("IamItemHud");
			val.AddComponent<Hud>();
			Object.DontDestroyOnLoad((Object)val);
			((Object)val).hideFlags = (HideFlags)61;
			Log.LogInfo((object)string.Format("{0} {1} loaded. Possess key: {2}.", "I Am Item", "1.0.1", Cfg.PossessKey));
		}
	}
	internal enum StopReason : byte
	{
		Manual,
		Cart,
		Extraction,
		Destroyed,
		RoundOver
	}
	internal sealed class Possession : MonoBehaviour
	{
		public static readonly List<Possession> All = new List<Possession>();

		public static Possession Local;

		internal PlayerAvatar avatar;

		private PhotonView view;

		public PhysGrabObject Target;

		public ValuableObject Valuable;

		public ItemClass Class;

		public bool HeldByPlayer;

		private bool shieldApplied;

		private float grabOpenTimer;

		private bool savedDestroyDisable;

		private bool savedPlayerHurtDisable;

		private bool jumpHeld;

		private Vector2 moveInput;

		private Vector2 moveSent;

		private float charge;

		private float jumpCooldown;

		private bool grounded;

		private float groundCheckTimer;

		private float crawlGrace;

		private float pendingImpulse;

		private float hitCooldown;

		private Vector3 lastVelocity;

		private ImpactRelay relay;

		private float extractionTimer;

		private bool grabbedPrevious;

		private int lastGrabberViewID;

		private UnityAction onLight;

		private UnityAction onMedium;

		private UnityAction onHeavy;

		public float ChargeVisual;

		public float HitFlash;

		private float actionCooldown;

		private float rattleCooldown;

		private bool stopRequested;

		private readonly Glow glow = new Glow();

		private Quaternion shakeTarget = Quaternion.identity;

		private float shakeCooldown;

		private Transform shakeTransform;

		private Quaternion shakeOriginal;

		public float Stamina;

		public bool Active => (Object)(object)Target != (Object)null;

		public static float Energy
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)SpectateCamera.instance))
				{
					return 0f;
				}
				return SpectateCamera.instance.headEnergy;
			}
			set
			{
				if (Object.op_Implicit((Object)(object)SpectateCamera.instance))
				{
					SpectateCamera.instance.headEnergy = Mathf.Clamp01(value);
				}
			}
		}

		public static float LocalStamina
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)Local))
				{
					return 0f;
				}
				return Local.Stamina;
			}
		}

		private void Awake()
		{
			avatar = ((Component)this).GetComponent<PlayerAvatar>();
			view = ((Component)this).GetComponent<PhotonView>();
			All.Add(this);
		}

		private void Start()
		{
			if (Object.op_Implicit((Object)(object)avatar) && avatar.isLocal)
			{
				Local = this;
			}
		}

		private void OnDestroy()
		{
			RestoreShield();
			if (Object.op_Implicit((Object)(object)relay))
			{
				Object.Destroy((Object)(object)relay);
			}
			relay = null;
			glow.Detach();
			RestoreShake();
			UnsubscribeImpacts();
			All.Remove(this);
			if ((Object)(object)Local == (Object)(object)this)
			{
				Local = null;
			}
		}

		public static bool IsPossessed(PhysGrabObject pgo)
		{
			foreach (Possession item in All)
			{
				if ((Object)(object)item.Target == (Object)(object)pgo)
				{
					return true;
				}
			}
			return false;
		}

		public static Possession Of(PhysGrabObject pgo)
		{
			foreach (Possession item in All)
			{
				if ((Object)(object)item.Target == (Object)(object)pgo)
				{
					return item;
				}
			}
			return null;
		}

		public static float Duration()
		{
			PlayerAvatar val = (Object.op_Implicit((Object)(object)PlayerController.instance) ? PlayerController.instance.playerAvatarScript : null);
			return Balance.DurationFor(Cfg.PossessionDuration.Value, Object.op_Implicit((Object)(object)val) ? val.upgradeDeathHeadBattery : 0f);
		}

		private void Spend(float amount)
		{
			Stamina = Mathf.Clamp01(Stamina - amount);
			if (Stamina <= 0f)
			{
				RequestStop();
			}
		}

		public static bool PossessReady()
		{
			if (!Cfg.Enabled.Value)
			{
				return false;
			}
			if (!SemiFunc.RunIsLevel())
			{
				return false;
			}
			SpectateCamera instance = SpectateCamera.instance;
			if (!Object.op_Implicit((Object)(object)instance))
			{
				return false;
			}
			if (instance.CheckState((State)2))
			{
				return false;
			}
			if (!instance.CheckState((State)1))
			{
				return false;
			}
			Possession local = Local;
			if (!Object.op_Implicit((Object)(object)local) || local.Active)
			{
				return false;
			}
			if (!Object.op_Implicit((Object)(object)local.avatar) || !local.avatar.isDisabled)
			{
				return false;
			}
			return true;
		}

		public static bool CanPossess()
		{
			if (PossessReady())
			{
				return Energy >= Cfg.MinEnergyToPossess.Value;
			}
			return false;
		}

		public void RequestPossess()
		{
			//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)
			if (SemiFunc.IsMultiplayer())
			{
				view.RPC("IamRequestRPC", (RpcTarget)2, Array.Empty<object>());
			}
			else
			{
				IamRequestRPC();
			}
		}

		[PunRPC]
		private void IamRequestRPC(PhotonMessageInfo info = default(PhotonMessageInfo))
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			if (!SemiFunc.IsMasterClientOrSingleplayer() || !SemiFunc.OwnerOnlyRPC(info, view) || Active)
			{
				return;
			}
			PhysGrabObject val = Targets.PickRandom();
			if (Object.op_Implicit((Object)(object)val) && IsPossessed(val))
			{
				Plugin.Log.LogWarning((object)"Picked an already possessed item, refusing.");
				val = null;
			}
			if (!Object.op_Implicit((Object)(object)val))
			{
				if (SemiFunc.IsMultiplayer())
				{
					view.RPC("IamDeniedRPC", view.Owner, Array.Empty<object>());
				}
				else
				{
					IamDeniedRPC();
				}
			}
			else if (SemiFunc.IsMultiplayer())
			{
				view.RPC("IamStartRPC", (RpcTarget)0, new object[1] { val.photonView.ViewID });
			}
			else
			{
				ApplyStart(val);
			}
		}

		[PunRPC]
		private void IamDeniedRPC(PhotonMessageInfo info = default(PhotonMessageInfo))
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (SemiFunc.MasterOnlyRPC(info))
			{
				Hud.Message("Nothing to possess", 2f);
			}
		}

		[PunRPC]
		private void IamStartRPC(int viewID, PhotonMessageInfo info = default(PhotonMessageInfo))
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (SemiFunc.MasterOnlyRPC(info))
			{
				PhotonView val = PhotonView.Find(viewID);
				if (Object.op_Implicit((Object)(object)val))
				{
					ApplyStart(((Component)val).GetComponent<PhysGrabObject>());
				}
			}
		}

		private void ApplyStart(PhysGrabObject target)
		{
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)target))
			{
				return;
			}
			ValuableObject component = ((Component)target).GetComponent<ValuableObject>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				return;
			}
			Target = target;
			Valuable = component;
			Class = Targets.ClassOf(component);
			HeldByPlayer = target.grabbed;
			charge = 0f;
			jumpCooldown = 0f;
			grounded = false;
			groundCheckTimer = 0f;
			crawlGrace = 0f;
			pendingImpulse = 0f;
			hitCooldown = 0f;
			lastVelocity = Vector3.zero;
			HitFlash = 0f;
			extractionTimer = 0f;
			grabbedPrevious = false;
			lastGrabberViewID = 0;
			stopRequested = false;
			grabOpenTimer = (target.grabbed ? Cfg.GrabShieldDelay.Value : 0f);
			moveInput = Vector2.zero;
			moveSent = Vector2.zero;
			Stamina = 1f;
			ApplyShield();
			SetupGlow();
			shakeTransform = FindShakeTransform(target);
			if (Object.op_Implicit((Object)(object)shakeTransform))
			{
				shakeOriginal = shakeTransform.localRotation;
			}
			Effects.Teleport(target.centerPoint);
			Effects.PlayEquip(target.centerPoint);
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				SubscribeImpacts();
				if (Object.op_Implicit((Object)(object)target.rb))
				{
					relay = ((Component)target.rb).gameObject.AddComponent<ImpactRelay>();
				}
				if (Object.op_Implicit((Object)(object)relay))
				{
					relay.owner = this;
				}
			}
			if ((Object)(object)this == (Object)(object)Local)
			{
				Energy -= Cfg.EntryCost.Value;
				GhostCamera.Enter();
			}
			Plugin.Log.LogInfo((object)$"{avatar?.playerName} possessed {((Object)component).name} ({Class})");
		}

		public void RequestStop()
		{
			if (Active && !stopRequested)
			{
				stopRequested = true;
				if (SemiFunc.IsMasterClientOrSingleplayer())
				{
					Stop(StopReason.Manual);
				}
				else
				{
					view.RPC("IamStopRequestRPC", (RpcTarget)2, Array.Empty<object>());
				}
			}
		}

		[PunRPC]
		private void IamStopRequestRPC(PhotonMessageInfo info = default(PhotonMessageInfo))
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			if (SemiFunc.IsMasterClientOrSingleplayer() && SemiFunc.OwnerOnlyRPC(info, view))
			{
				Stop(StopReason.Manual);
			}
		}

		public void Stop(StopReason reason)
		{
			if (Active)
			{
				int num = 0;
				if (reason == StopReason.Cart || reason == StopReason.Destroyed)
				{
					num = lastGrabberViewID;
				}
				if (SemiFunc.IsMultiplayer())
				{
					view.RPC("IamStopRPC", (RpcTarget)0, new object[2]
					{
						(byte)reason,
						num
					});
				}
				else
				{
					ApplyStop((byte)reason, num);
				}
			}
		}

		[PunRPC]
		private void IamStopRPC(byte reason, int speakerViewID, PhotonMessageInfo info = default(PhotonMessageInfo))
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (SemiFunc.MasterOnlyRPC(info))
			{
				ApplyStop(reason, speakerViewID);
			}
		}

		private void ApplyStop(byte reasonByte, int speakerViewID)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			if (!Active)
			{
				return;
			}
			StopReason stopReason = (StopReason)reasonByte;
			Vector3 position = (Object.op_Implicit((Object)(object)Target) ? Target.centerPoint : ((Component)this).transform.position);
			UnsubscribeImpacts();
			if (Object.op_Implicit((Object)(object)relay))
			{
				Object.Destroy((Object)(object)relay);
			}
			relay = null;
			bool flag = false;
			if (stopReason != StopReason.Destroyed && shieldApplied && Object.op_Implicit((Object)(object)Target) && Object.op_Implicit((Object)(object)Target.impactDetector))
			{
				ExitGrace.Add(Target, savedDestroyDisable, savedPlayerHurtDisable);
				shieldApplied = false;
				flag = true;
			}
			if (!flag)
			{
				RestoreShield();
			}
			glow.Detach();
			RestoreShake();
			Target = null;
			Valuable = null;
			HeldByPlayer = false;
			jumpHeld = false;
			ChargeVisual = 0f;
			Effects.Teleport(position);
			Effects.PlayUnequip(position);
			if ((Object)(object)this == (Object)(object)Local)
			{
				if (stopReason == StopReason.Destroyed)
				{
					Stamina = 0f;
				}
				GhostCamera.Exit();
			}
			if (speakerViewID != 0 && (Object)(object)Local != (Object)null && Object.op_Implicit((Object)(object)Local.avatar) && Object.op_Implicit((Object)(object)Local.avatar.photonView) && Local.avatar.photonView.ViewID == speakerViewID)
			{
				if (stopReason == StopReason.Cart && Cfg.CartPhrasesEnabled.Value)
				{
					Speech.Say(Phrases.Pick(Phrases.Cart));
				}
				else if (stopReason == StopReason.Destroyed && Cfg.BreakPhrasesEnabled.Value)
				{
					Speech.Say(Phrases.Pick(Phrases.Break));
				}
			}
		}

		private void ApplyShield()
		{
			if (!shieldApplied && Object.op_Implicit((Object)(object)Target) && Object.op_Implicit((Object)(object)Target.impactDetector))
			{
				ExitGrace.Release(Target);
				PhysGrabObjectImpactDetector impactDetector = Target.impactDetector;
				savedDestroyDisable = impactDetector.destroyDisable;
				savedPlayerHurtDisable = impactDetector.playerHurtDisable;
				shieldApplied = true;
				UpdateShield();
			}
		}

		private void UpdateShield()
		{
			if (shieldApplied && Object.op_Implicit((Object)(object)Target) && Object.op_Implicit((Object)(object)Target.impactDetector))
			{
				PhysGrabObjectImpactDetector impactDetector = Target.impactDetector;
				bool flag = grabOpenTimer > 0f;
				impactDetector.destroyDisable = (Cfg.ValuableShield.Value && !flag) || savedDestroyDisable;
				impactDetector.playerHurtDisable = savedPlayerHurtDisable || Cfg.ValuableShield.Value;
			}
		}

		private void RestoreShield()
		{
			if (shieldApplied)
			{
				shieldApplied = false;
				if (Object.op_Implicit((Object)(object)Target) && Object.op_Implicit((Object)(object)Target.impactDetector))
				{
					Target.impactDetector.destroyDisable = savedDestroyDisable;
					Target.impactDetector.playerHurtDisable = savedPlayerHurtDisable;
				}
			}
		}

		public void KillInDeathPit()
		{
			if (Active && SemiFunc.IsMasterClientOrSingleplayer())
			{
				PhysGrabObjectImpactDetector impactDetector = Target.impactDetector;
				RestoreShield();
				Stop(StopReason.Destroyed);
				if (Object.op_Implicit((Object)(object)impactDetector))
				{
					impactDetector.DestroyObject(true);
				}
			}
		}

		private void SendAction(byte action)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			if (SemiFunc.IsMultiplayer())
			{
				view.RPC("IamActionRPC", (RpcTarget)2, new object[1] { action });
			}
			else
			{
				IamActionRPC(action);
			}
		}

		[PunRPC]
		private void IamActionRPC(byte action, PhotonMessageInfo info = default(PhotonMessageInfo))
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			if (SemiFunc.IsMasterClientOrSingleplayer() && SemiFunc.OwnerOnlyRPC(info, view) && Active)
			{
				switch (action)
				{
				case 0:
					DoRattle();
					break;
				case 2:
					DoKnock();
					break;
				}
			}
		}

		private void DoRattle()
		{
			//IL_003b: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: 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_00e4: Unknown result type (might be due to invalid IL or missing references)
			float num = Class switch
			{
				ItemClass.Light => Cfg.RattleRadiusLight.Value, 
				ItemClass.Medium => Cfg.RattleRadiusMedium.Value, 
				_ => Cfg.RattleRadiusHeavy.Value, 
			};
			SemiFunc.EnemyInvestigate(Target.centerPoint, num, false);
			Target.rb.AddTorque(Random.insideUnitSphere * (Target.rb.mass * 1.5f), (ForceMode)1);
			if (SemiFunc.IsMultiplayer())
			{
				view.RPC("IamNoiseRPC", (RpcTarget)0, new object[1] { false });
				view.RPC("IamRattleSaidRPC", view.Owner, new object[1] { num });
			}
			else
			{
				IamNoiseRPC(quiet: false);
				IamRattleSaidRPC(num);
			}
		}

		private void DoKnock()
		{
			//IL_000b: 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_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			Target.rb.AddTorque(Random.insideUnitSphere * (Target.rb.mass * 0.15f), (ForceMode)1);
			if (SemiFunc.IsMultiplayer())
			{
				view.RPC("IamNoiseRPC", (RpcTarget)0, new object[1] { true });
			}
			else
			{
				IamNoiseRPC(quiet: true);
			}
		}

		[PunRPC]
		private void IamRattleSaidRPC(float radius, PhotonMessageInfo info = default(PhotonMessageInfo))
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (SemiFunc.MasterOnlyRPC(info))
			{
				Hud.Message("Rattle - monsters within " + Mathf.RoundToInt(radius) + " m heard it", 1.5f);
			}
		}

		[PunRPC]
		private void IamNoiseRPC(bool quiet, PhotonMessageInfo info = default(PhotonMessageInfo))
		{
			//IL_0000: 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)
			if (SemiFunc.MasterOnlyRPC(info) && Active && Object.op_Implicit((Object)(object)Target) && Object.op_Implicit((Object)(object)Target.impactDetector))
			{
				PhysAudio impactAudio = Target.impactDetector.impactAudio;
				Sound val = ((!Object.op_Implicit((Object)(object)impactAudio)) ? null : (quiet ? impactAudio.impactLight : impactAudio.impactMedium));
				if (val != null)
				{
					val.Play(Target.centerPoint, quiet ? 0.4f : 1f, 1f, 1f, 1f);
				}
				shakeCooldown = 0f;
			}
		}

		private void SpendRemote(float amount)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			if (!(amount <= 0f))
			{
				if (SemiFunc.IsMultiplayer())
				{
					view.RPC("IamSpendRPC", view.Owner, new object[1] { amount });
				}
				else
				{
					IamSpendRPC(amount);
				}
			}
		}

		[PunRPC]
		private void IamSpendRPC(float amount, PhotonMessageInfo info = default(PhotonMessageInfo))
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (SemiFunc.MasterOnlyRPC(info) && !((Object)(object)this != (Object)(object)Local) && Active)
			{
				Spend(amount);
			}
		}

		[PunRPC]
		private void IamGrabbedRPC(bool held, PhotonMessageInfo info = default(PhotonMessageInfo))
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (SemiFunc.MasterOnlyRPC(info))
			{
				HeldByPlayer = held;
			}
		}

		[PunRPC]
		private void IamChargeRPC(float amount, PhotonMessageInfo info = default(PhotonMessageInfo))
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (SemiFunc.MasterOnlyRPC(info))
			{
				ChargeVisual = amount;
			}
		}

		[PunRPC]
		private void IamHitRPC(PhotonMessageInfo info = default(PhotonMessageInfo))
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (SemiFunc.MasterOnlyRPC(info))
			{
				HitFlash = 0.35f;
				shakeCooldown = 0f;
			}
		}

		[PunRPC]
		private void IamMoveRPC(float x, float y, PhotonMessageInfo info = default(PhotonMessageInfo))
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			if (SemiFunc.IsMasterClientOrSingleplayer() && SemiFunc.OwnerOnlyRPC(info, view))
			{
				moveInput = new Vector2(x, y);
			}
		}

		[PunRPC]
		private void IamInputRPC(bool held, PhotonMessageInfo info = default(PhotonMessageInfo))
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			if (SemiFunc.IsMasterClientOrSingleplayer() && SemiFunc.OwnerOnlyRPC(info, view))
			{
				jumpHeld = held;
			}
		}

		internal void RamHit(Collision collision)
		{
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			if (!Active || !Cfg.RamEnabled.Value || !SemiFunc.IsMasterClientOrSingleplayer() || hitCooldown > 0f || Target.playerGrabbing.Count > 0)
			{
				return;
			}
			float magnitude = ((Vector3)(ref lastVelocity)).magnitude;
			if (magnitude < Cfg.RamMinSpeed.Value)
			{
				return;
			}
			float num = Mathf.InverseLerp(Cfg.RamMinSpeed.Value, Mathf.Max(Cfg.RamFullSpeed.Value, Cfg.RamMinSpeed.Value + 0.01f), magnitude);
			if (!(num <= 0f))
			{
				float ramScale = Tuning.For(Class).ramScale;
				Transform transform = collision.transform;
				Vector3 point = ((collision.contacts.Length != 0) ? ((ContactPoint)(ref collision.contacts[0])).point : Target.centerPoint);
				if (((Component)transform).CompareTag("Enemy") && TryHurtEnemy(transform, num * ramScale))
				{
					HitDone();
				}
				else if (Cfg.RamHurtsPlayers.Value && TryHurtPlayer(transform, num * ramScale, point))
				{
					HitDone();
				}
			}
		}

		private void HitDone()
		{
			hitCooldown = Cfg.RamHitCooldown.Value;
			HitFlash = 0.35f;
			shakeCooldown = 0f;
			if (SemiFunc.IsMultiplayer())
			{
				view.RPC("IamHitRPC", (RpcTarget)1, Array.Empty<object>());
			}
		}

		private bool TryHurtEnemy(Transform hit, float amount)
		{
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: 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_0098: Unknown result type (might be due to invalid IL or missing references)
			EnemyRigidbody val = ((Component)hit).GetComponent<EnemyRigidbody>();
			if (!Object.op_Implicit((Object)(object)val))
			{
				val = ((Component)hit).GetComponentInParent<EnemyRigidbody>();
			}
			if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val.enemy) || !val.enemy.HasHealth)
			{
				return false;
			}
			EnemyHealth health = val.enemy.Health;
			if (!health.objectHurt || health.dead)
			{
				return false;
			}
			int num = Mathf.RoundToInt((float)Cfg.RamDamage.Value * amount * health.objectHurtMultiplier);
			if (num <= 0)
			{
				return false;
			}
			Vector3 val2 = ((Component)val).transform.position - Target.centerPoint;
			health.Hurt(num, ((Vector3)(ref val2)).normalized);
			return true;
		}

		private bool TryHurtPlayer(Transform hit, float amount, Vector3 point)
		{
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			PlayerTumble val = ((Component)hit).GetComponent<PlayerTumble>();
			if (!Object.op_Implicit((Object)(object)val))
			{
				val = ((Component)hit).GetComponentInParent<PlayerTumble>();
			}
			PlayerAvatar val2 = (Object.op_Implicit((Object)(object)val) ? val.playerAvatar : ((Component)hit).GetComponentInParent<PlayerAvatar>());
			if (!Object.op_Implicit((Object)(object)val2))
			{
				PlayerPhysPusher component = ((Component)hit).GetComponent<PlayerPhysPusher>();
				if (Object.op_Implicit((Object)(object)component))
				{
					val2 = component.Player;
				}
			}
			if (!Object.op_Implicit((Object)(object)val2) || (Object)(object)val2 == (Object)(object)avatar || val2.isDisabled || val2.deadSet)
			{
				return false;
			}
			if (!Object.op_Implicit((Object)(object)val2.playerHealth) || val2.playerHealth.health <= 0)
			{
				return false;
			}
			int num = Mathf.RoundToInt((float)Cfg.RamPlayerDamage.Value * amount);
			if (num > 0)
			{
				val2.playerHealth.HurtOther(num, point, true, -1, false);
			}
			if (Cfg.RamTumblesPlayers.Value && Object.op_Implicit((Object)(object)val2.tumble) && !val2.tumble.isTumbling)
			{
				val2.tumble.TumbleRequest(true, false);
				val2.tumble.TumbleOverrideTime(1f);
			}
			return true;
		}

		private void SubscribeImpacts()
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			PhysGrabObjectImpactDetector val = (Object.op_Implicit((Object)(object)Target) ? Target.impactDetector : null);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			onLight = (UnityAction)delegate
			{
				if (crawlGrace <= 0f)
				{
					SpendRemote(Cfg.WallHitCostLight.Value);
				}
			};
			onMedium = (UnityAction)delegate
			{
				if (crawlGrace <= 0f)
				{
					SpendRemote(Cfg.WallHitCostMedium.Value);
				}
			};
			onHeavy = (UnityAction)delegate
			{
				if (crawlGrace <= 0f)
				{
					SpendRemote(Cfg.WallHitCostHeavy.Value);
				}
			};
			val.onImpactLight.AddListener(onLight);
			val.onImpactMedium.AddListener(onMedium);
			val.onImpactHeavy.AddListener(onHeavy);
		}

		private void UnsubscribeImpacts()
		{
			PhysGrabObjectImpactDetector val = (Object.op_Implicit((Object)(object)Target) ? Target.impactDetector : null);
			if (Object.op_Implicit((Object)(object)val))
			{
				if (onLight != null)
				{
					val.onImpactLight.RemoveListener(onLight);
				}
				if (onMedium != null)
				{
					val.onImpactMedium.RemoveListener(onMedium);
				}
				if (onHeavy != null)
				{
					val.onImpactHeavy.RemoveListener(onHeavy);
				}
			}
			onLight = (onMedium = (onHeavy = null));
		}

		internal void Tick()
		{
			if (!Active)
			{
				return;
			}
			if (!Object.op_Implicit((Object)(object)Target) || !((Component)Target).gameObject.activeInHierarchy)
			{
				if (SemiFunc.IsMasterClientOrSingleplayer())
				{
					Stop(StopReason.Destroyed);
				}
				else
				{
					ApplyStop(3, lastGrabberViewID);
				}
				return;
			}
			if (Target.playerGrabbing.Count > 0)
			{
				PhysGrabber val = Target.playerGrabbing[Target.playerGrabbing.Count - 1];
				if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.playerAvatar) && Object.op_Implicit((Object)(object)val.playerAvatar.photonView))
				{
					lastGrabberViewID = val.playerAvatar.photonView.ViewID;
				}
			}
			if (HeldByPlayer)
			{
				grabOpenTimer = Cfg.GrabShieldDelay.Value;
			}
			else if (grabOpenTimer > 0f)
			{
				grabOpenTimer -= Time.deltaTime;
			}
			UpdateShield();
			if (HitFlash > 0f)
			{
				HitFlash -= Time.deltaTime;
			}
			glow.Tick(HitFlash > 0f);
			TickShake();
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				MasterUpdate();
			}
			if ((Object)(object)this == (Object)(object)Local)
			{
				OwnerUpdate();
			}
		}

		private void MasterUpdate()
		{
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			if (!SemiFunc.RunIsLevel() || !Object.op_Implicit((Object)(object)avatar) || !avatar.isDisabled)
			{
				Stop(StopReason.RoundOver);
				return;
			}
			PhysGrabObjectImpactDetector impactDetector = Target.impactDetector;
			if (Object.op_Implicit((Object)(object)impactDetector) && impactDetector.inCart)
			{
				Stop(StopReason.Cart);
				return;
			}
			if (Object.op_Implicit((Object)(object)Valuable) && Object.op_Implicit((Object)(object)Valuable.roomVolumeCheck) && Valuable.roomVolumeCheck.inExtractionPoint)
			{
				extractionTimer += Time.deltaTime;
				if (SemiFunc.PerSecond(4f, (Object)(object)this))
				{
					if (SemiFunc.IsMultiplayer())
					{
						view.RPC("IamWarnRPC", view.Owner, Array.Empty<object>());
					}
					else
					{
						IamWarnRPC();
					}
				}
				if (extractionTimer >= 2f)
				{
					Stop(StopReason.Extraction);
					return;
				}
			}
			else
			{
				extractionTimer = 0f;
			}
			if (((Component)Target).transform.position.y < -45f)
			{
				Stop(StopReason.RoundOver);
				return;
			}
			bool flag = Target.playerGrabbing.Count > 0;
			if (flag != grabbedPrevious)
			{
				grabbedPrevious = flag;
				HeldByPlayer = flag;
				if (SemiFunc.IsMultiplayer())
				{
					view.RPC("IamGrabbedRPC", (RpcTarget)1, new object[1] { flag });
				}
			}
			if (hitCooldown > 0f)
			{
				hitCooldown -= Time.deltaTime;
			}
			if (jumpCooldown > 0f)
			{
				jumpCooldown -= Time.deltaTime;
			}
			if (crawlGrace > 0f)
			{
				crawlGrace -= Time.deltaTime;
			}
			if (groundCheckTimer > 0f)
			{
				groundCheckTimer -= Time.deltaTime;
			}
			else
			{
				groundCheckTimer = 0.2f;
				grounded = SemiFunc.OnGroundCheck(Target.centerPoint, 0.5f, Target);
			}
			Tuning tuning = Tuning.For(Class);
			if (jumpHeld && !flag && charge <= tuning.chargeMax)
			{
				if (grounded && jumpCooldown <= 0f)
				{
					charge += Time.deltaTime;
				}
			}
			else if (charge > 0f)
			{
				pendingImpulse = Mathf.Max(charge, tuning.minCharge);
				charge = 0f;
				jumpCooldown = tuning.cooldown;
				grounded = false;
				groundCheckTimer = 0f;
				SpendRemote(Cfg.JumpCost.Value);
			}
			float num = charge / tuning.chargeMax;
			bool flag2 = !Mathf.Approximately(num, ChargeVisual);
			ChargeVisual = num;
			if (SemiFunc.IsMultiplayer() && flag2 && SemiFunc.PerSecond(5f, (Object)(object)this))
			{
				view.RPC("IamChargeRPC", (RpcTarget)1, new object[1] { num });
			}
		}

		[PunRPC]
		private void IamWarnRPC(PhotonMessageInfo info = default(PhotonMessageInfo))
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (SemiFunc.MasterOnlyRPC(info))
			{
				Hud.Message("Extraction point. Ejecting.", 0.5f);
			}
		}

		private void OwnerUpdate()
		{
			//IL_00e7: 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_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: 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_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: 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)
			if (!Active)
			{
				return;
			}
			if (actionCooldown > 0f)
			{
				actionCooldown -= Time.deltaTime;
			}
			if (rattleCooldown > 0f)
			{
				rattleCooldown -= Time.deltaTime;
			}
			if ((Object.op_Implicit((Object)(object)MenuManager.instance) && Object.op_Implicit((Object)(object)MenuManager.instance.currentMenuPage)) || (Object.op_Implicit((Object)(object)ChatManager.instance) && !ChatManager.instance.StateIsInactive() && !ChatManager.instance.StateIsPossessed()))
			{
				return;
			}
			if (SemiFunc.InputDown((InputKey)2))
			{
				RequestStop();
				return;
			}
			bool flag = !HeldByPlayer && SemiFunc.InputHold((InputKey)1);
			if (flag != jumpHeld)
			{
				jumpHeld = flag;
				if (SemiFunc.IsMultiplayer())
				{
					view.RPC("IamInputRPC", (RpcTarget)2, new object[1] { jumpHeld });
				}
			}
			Vector2 val = SemiFunc.InputMovement();
			Vector2 zero = default(Vector2);
			((Vector2)(ref zero))..ctor(Mathf.Clamp(Mathf.Round(val.x), -1f, 1f), Mathf.Clamp(Mathf.Round(val.y), -1f, 1f));
			if (HeldByPlayer)
			{
				zero = Vector2.zero;
			}
			if (zero != moveSent)
			{
				moveSent = zero;
				if (SemiFunc.IsMultiplayer())
				{
					view.RPC("IamMoveRPC", (RpcTarget)2, new object[2] { zero.x, zero.y });
				}
				else
				{
					moveInput = zero;
				}
			}
			if (SemiFunc.InputDown((InputKey)10) && actionCooldown <= 0f)
			{
				if (HeldByPlayer)
				{
					actionCooldown = 1f;
					Spend(Cfg.KnockCost.Value);
					SendAction(2);
				}
				else if (rattleCooldown <= 0f)
				{
					actionCooldown = 0.5f;
					rattleCooldown = 4f;
					Spend(Cfg.RattleCost.Value);
					SendAction(0);
				}
			}
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				Tuning tuning = Tuning.For(Class);
				ChargeVisual = (jumpHeld ? Mathf.Min(1f, ChargeVisual + Time.deltaTime / tuning.chargeMax) : 0f);
			}
			Spend(Time.deltaTime / Duration());
		}

		internal void PhysicsTick()
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0400: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_028d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			//IL_029d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: 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_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: 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_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_035d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0362: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0300: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_0395: Unknown result type (might be due to invalid IL or missing references)
			//IL_039a: Unknown result type (might be due to invalid IL or missing references)
			if (!Active || !SemiFunc.IsMasterClientOrSingleplayer() || !Object.op_Implicit((Object)(object)Target) || !Object.op_Implicit((Object)(object)Target.rb))
			{
				return;
			}
			Tuning tuning = Tuning.For(Class);
			Rigidbody rb = Target.rb;
			bool flag = Target.playerGrabbing.Count > 0;
			lastVelocity = rb.velocity;
			bool flag2 = !flag && ((Vector2)(ref moveInput)).sqrMagnitude > 0.01f && Cfg.CrawlSpeed.Value > 0f && grounded;
			if (!flag && !flag2)
			{
				Transform val = ((Object.op_Implicit((Object)(object)avatar) && Object.op_Implicit((Object)(object)avatar.localCamera)) ? avatar.localCamera.GetOverrideTransform() : null);
				if (Object.op_Implicit((Object)(object)val))
				{
					Quaternion val2;
					if (Class == ItemClass.Heavy)
					{
						Quaternion rotation = ((Component)Target).transform.rotation;
						Vector3 eulerAngles = ((Quaternion)(ref rotation)).eulerAngles;
						float x = eulerAngles.x;
						rotation = val.rotation;
						val2 = Quaternion.Euler(x, ((Quaternion)(ref rotation)).eulerAngles.y, eulerAngles.z);
					}
					else
					{
						val2 = val.rotation;
					}
					Vector3 val3 = SemiFunc.PhysFollowRotation(((Component)Target).transform, val2, rb, tuning.followMaxSpeed);
					val3 = Vector3.Lerp(Vector3.zero, val3, tuning.followStrength * Time.fixedDeltaTime);
					rb.AddTorque(val3, (ForceMode)1);
					Target.OverrideTorqueStrength(0f, 0.1f);
				}
			}
			if (flag2)
			{
				Transform val4 = ((Object.op_Implicit((Object)(object)avatar) && Object.op_Implicit((Object)(object)avatar.localCamera)) ? avatar.localCamera.GetOverrideTransform() : null);
				if (Object.op_Implicit((Object)(object)val4))
				{
					Vector3 forward = val4.forward;
					forward.y = 0f;
					Vector3 right = val4.right;
					right.y = 0f;
					Vector3 val5 = ((Vector3)(ref forward)).normalized * moveInput.y + ((Vector3)(ref right)).normalized * moveInput.x;
					if (((Vector3)(ref val5)).sqrMagnitude > 0.0001f)
					{
						((Vector3)(ref val5)).Normalize();
						crawlGrace = 0.5f;
						float num = Cfg.CrawlSpeed.Value * tuning.crawlScale;
						Vector3 val6 = default(Vector3);
						((Vector3)(ref val6))..ctor(rb.velocity.x, 0f, rb.velocity.z);
						Vector3 val7 = val5 * num - val6;
						rb.AddForce(Vector3.ClampMagnitude(val7 * Cfg.CrawlAcceleration.Value, Cfg.CrawlAcceleration.Value) * rb.mass, (ForceMode)0);
						if (Cfg.CrawlSpin.Value > 0f)
						{
							rb.AddTorque(Vector3.Cross(Vector3.up, val5) * (Cfg.CrawlSpin.Value * rb.mass), (ForceMode)0);
						}
					}
				}
			}
			if (pendingImpulse > 0f)
			{
				Transform val8 = ((Object.op_Implicit((Object)(object)avatar) && Object.op_Implicit((Object)(object)avatar.localCamera)) ? avatar.localCamera.GetOverrideTransform() : null);
				if (Object.op_Implicit((Object)(object)val8) && !flag)
				{
					Vector3 val9 = val8.forward;
					if (Class == ItemClass.Heavy && Cfg.HeavySlideOnly.Value)
					{
						val9.y = 0f;
						if (((Vector3)(ref val9)).sqrMagnitude < 0.0001f)
						{
							val9 = val8.up;
						}
						((Vector3)(ref val9)).Normalize();
					}
					rb.AddForce(val9 * (tuning.force * pendingImpulse * rb.mass), (ForceMode)1);
				}
				pendingImpulse = 0f;
			}
			if (!flag)
			{
				Vector3 velocity = rb.velocity;
				if (((Vector3)(ref velocity)).magnitude > tuning.speedCap)
				{
					velocity = rb.velocity;
					rb.velocity = ((Vector3)(ref velocity)).normalized * tuning.speedCap;
				}
			}
		}

		private void SetupGlow()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			Color baseColor = Color.cyan;
			PlayerAvatarVisuals val = (Object.op_Implicit((Object)(object)avatar) ? avatar.playerAvatarVisuals : null);
			if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.playerCosmetics) && (Object)(object)MetaManager.instance != (Object)null && MetaManager.instance.colors != null && MetaManager.instance.colors.Count > 0)
			{
				int[] colorsEquipped = val.playerCosmetics.colorsEquipped;
				int num = 7;
				if (colorsEquipped != null && colorsEquipped.Length > num)
				{
					int index = Mathf.Clamp(colorsEquipped[num], 0, MetaManager.instance.colors.Count - 1);
					SemiColor val2 = MetaManager.instance.colors[index];
					if (Object.op_Implicit((Object)(object)val2))
					{
						baseColor = val2.color;
					}
				}
			}
			glow.BaseColor = baseColor;
			glow.Attach(((Component)Target).gameObject);
		}

		private static Transform FindShakeTransform(PhysGrabObject pgo)
		{
			MeshRenderer componentInChildren = ((Component)pgo).GetComponentInChildren<MeshRenderer>();
			if (Object.op_Implicit((Object)(object)componentInChildren) && (Object)(object)((Component)componentInChildren).transform != (Object)(object)((Component)pgo).transform)
			{
				return ((Component)componentInChildren).transform;
			}
			return null;
		}

		private void TickShake()
		{
			//IL_0030: 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_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_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_00a7: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)shakeTransform))
			{
				float num = 0.6f + ChargeVisual * 3f;
				if (shakeCooldown <= 0f)
				{
					shakeTarget = shakeOriginal * Quaternion.Euler(Random.Range(0f - num, num), Random.Range(0f - num, num), Random.Range(0f - num, num));
					shakeCooldown = Random.Range(0.01f, 0.05f);
				}
				else
				{
					shakeCooldown -= Time.deltaTime;
				}
				shakeTransform.localRotation = Quaternion.Slerp(shakeTransform.localRotation, shakeTarget, 20f * Time.deltaTime);
			}
		}

		private void RestoreShake()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)shakeTransform))
			{
				shakeTransform.localRotation = shakeOriginal;
			}
			shakeTransform = null;
			shakeTarget = Quaternion.identity;
		}
	}
	internal static class ExitGrace
	{
		private sealed class Entry
		{
			public PhysGrabObject item;

			public bool destroyDisable;

			public bool playerHurtDisable;

			public float left;

			public float still;
		}

		private static readonly List<Entry> entries = new List<Entry>();

		public static void Add(PhysGrabObject item, bool destroyDisable, bool playerHurtDisable)
		{
			if (!Object.op_Implicit((Object)(object)item) || !Object.op_Implicit((Object)(object)item.impactDetector))
			{
				return;
			}
			if (Cfg.ExitGraceSeconds.Value <= 0f)
			{
				Restore(item, destroyDisable, playerHurtDisable);
				return;
			}
			foreach (Entry entry in entries)
			{
				if ((Object)(object)entry.item == (Object)(object)item)
				{
					entry.left = Cfg.ExitGraceMaxSeconds.Value;
					entry.still = 0f;
					return;
				}
			}
			item.impactDetector.destroyDisable = true;
			item.OverrideIndestructible(Cfg.ExitGraceSeconds.Value);
			entries.Add(new Entry
			{
				item = item,
				destroyDisable = destroyDisable,
				playerHurtDisable = playerHurtDisable,
				left = Cfg.ExitGraceMaxSeconds.Value,
				still = 0f
			});
		}

		public static void Release(PhysGrabObject item)
		{
			for (int num = entries.Count - 1; num >= 0; num--)
			{
				if (!((Object)(object)entries[num].item != (Object)(object)item))
				{
					Restore(entries[num].item, entries[num].destroyDisable, entries[num].playerHurtDisable);
					entries.RemoveAt(num);
				}
			}
		}

		public static void Tick()
		{
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			for (int num = entries.Count - 1; num >= 0; num--)
			{
				Entry entry = entries[num];
				if (!Object.op_Implicit((Object)(object)entry.item) || !Object.op_Implicit((Object)(object)entry.item.rb) || !Object.op_Implicit((Object)(object)entry.item.impactDetector))
				{
					entries.RemoveAt(num);
				}
				else
				{
					bool num2 = entry.item.playerGrabbing.Count > 0;
					entry.left -= Time.deltaTime;
					Vector3 val = entry.item.rb.velocity;
					int num3;
					if (!(((Vector3)(ref val)).magnitude > 0.4f))
					{
						val = entry.item.rb.angularVelocity;
						num3 = ((((Vector3)(ref val)).magnitude > 1.5f) ? 1 : 0);
					}
					else
					{
						num3 = 1;
					}
					bool flag = (byte)num3 != 0;
					entry.still = (flag ? 0f : (entry.still + Time.deltaTime));
					if (num2 || entry.left <= 0f || entry.still >= Cfg.ExitGraceSeconds.Value)
					{
						Restore(entry.item, entry.destroyDisable, entry.playerHurtDisable);
						entries.RemoveAt(num);
					}
					else
					{
						entry.item.impactDetector.destroyDisable = true;
						entry.item.OverrideIndestructible(0.25f);
					}
				}
			}
		}

		private static void Restore(PhysGrabObject item, bool destroyDisable, bool playerHurtDisable)
		{
			if (Object.op_Implicit((Object)(object)item) && Object.op_Implicit((Object)(object)item.impactDetector))
			{
				item.impactDetector.destroyDisable = destroyDisable;
				item.impactDetector.playerHurtDisable = playerHurtDisable;
			}
		}
	}
	internal sealed class ImpactRelay : MonoBehaviour
	{
		internal Possession owner;

		private void OnCollisionEnter(Collision collision)
		{
			if (Object.op_Implicit((Object)(object)owner))
			{
				owner.RamHit(collision);
			}
		}
	}
	internal struct Tuning
	{
		public float chargeMax;

		public float minCharge;

		public float force;

		public float crawlScale;

		public float ramScale;

		public float speedCap;

		public float cooldown;

		public float followMaxSpeed;

		public float followStrength;

		public static Tuning For(ItemClass c)
		{
			return c switch
			{
				ItemClass.Light => new Tuning
				{
					chargeMax = 0.7f,
					minCharge = 0.15f,
					force = 16f,
					crawlScale = 1f,
					ramScale = 0.6f,
					speedCap = 18f,
					cooldown = 0.5f,
					followMaxSpeed = 5f,
					followStrength = 10f
				}, 
				ItemClass.Medium => new Tuning
				{
					chargeMax = 0.8f,
					minCharge = 0.15f,
					force = 13f,
					crawlScale = 0.85f,
					ramScale = 1f,
					speedCap = 15f,
					cooldown = 0.6f,
					followMaxSpeed = 5f,
					followStrength = 10f
				}, 
				_ => new Tuning
				{
					chargeMax = 1f,
					minCharge = 0.25f,
					force = 9f,
					crawlScale = 0.5f,
					ramScale = 1.6f,
					speedCap = 9f,
					cooldown = 0.9f,
					followMaxSpeed = 1.5f,
					followStrength = 3f
				}, 
			};
		}
	}
	internal static class PossessPrompt
	{
		private const float OffsetY = 102f;

		private const float PreviewOffsetY = 50f;

		private static GameObject clone;

		private static TextMeshProUGUI text;

		private static string shownText;

		public static void Tick()
		{
			//IL_00cf: 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_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			SpectateHeadUI instance = SpectateHeadUI.instance;
			if (!Object.op_Implicit((Object)(object)instance) || !Object.op_Implicit((Object)(object)instance.promptTransform) || !Object.op_Implicit((Object)(object)instance.promptTargetTransform) || !Possession.PossessReady())
			{
				if (Object.op_Implicit((Object)(object)clone))
				{
					clone.SetActive(false);
				}
				Preview.Hide();
				return;
			}
			if (!Object.op_Implicit((Object)(object)clone))
			{
				Build(instance);
			}
			if (!Object.op_Implicit((Object)(object)clone))
			{
				Preview.Hide();
				return;
			}
			if (!clone.activeSelf)
			{
				clone.SetActive(true);
			}
			bool flag = Possession.CanPossess();
			string text = (flag ? ReadyText() : ChargingText());
			if (Object.op_Implicit((Object)(object)PossessPrompt.text) && shownText != text)
			{
				shownText = text;
				((TMP_Text)PossessPrompt.text).text = text;
			}
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(((Transform)instance.promptTransform).position.x, instance.promptTargetTransform.position.y + 10f + 102f, clone.transform.position.z);
			clone.transform.position = val;
			Transform parent = ((Transform)instance.promptTransform).parent;
			Preview.Tick((RectTransform)(object)((parent is RectTransform) ? parent : null), val, 50f, flag);
		}

		private static string ReadyText()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			return "<color=#FF8C00>Press</color> <color=white>" + ((object)Cfg.PossessKey/*cast due to .constrained prefix*/).ToString().ToUpperInvariant() + "</color>";
		}

		private static string ChargingText()
		{
			//IL_0040: 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)
			float num = Mathf.Max(0.01f, Cfg.MinEnergyToPossess.Value);
			int num2 = Mathf.Clamp(Mathf.FloorToInt(Possession.Energy / num * 100f), 0, 99);
			return "<color=#FF8C00>" + ((object)Cfg.PossessKey/*cast due to .constrained prefix*/).ToString().ToUpperInvariant() + "</color> <color=#808080>" + num2 + "%</color>";
		}

		private static void Build(SpectateHeadUI ui)
		{
			clone = Object.Instantiate<GameObject>(((Component)ui.promptTransform).gameObject, ((Transform)ui.promptTransform).parent);
			((Object)clone).name = "IamItemPossessPrompt";
			text = clone.GetComponentInChildren<TextMeshProUGUI>(true);
			shownText = null;
			if (!Object.op_Implicit((Object)(object)text))
			{
				Plugin.Log.LogWarning((object)"Spectate prompt has no text, possess hint stays hidden.");
				Object.Destroy((Object)(object)clone);
				clone = null;
			}
		}
	}
	internal static class Preview
	{
		private static readonly Vector3 StageOrigin = new Vector3(7777f, -7777f, 7777f);

		private const int TextureHeight = 64;

		private const float ModelSize = 0.3f;

		private const float OrbitRadius = 0.5f;

		private const float OrbitSpeed = 30f;

		private const float SpinSpeed = 60f;

		private const float CameraPitch = 24f;

		private static GameObject stage;

		private static Camera camera;

		private static RenderTexture texture;

		private static RawImage image;

		private static Transform orbit;

		private static readonly List<Transform> slots = new List<Transform>();

		private static readonly List<GameObject> models = new List<GameObject>();

		private static bool visible;

		public static void Hide()
		{
			if (visible)
			{
				visible = false;
				if (Object.op_Implicit((Object)(object)stage))
				{
					stage.SetActive(false);
				}
				if (Object.op_Implicit((Object)(object)camera))
				{
					((Behaviour)camera).enabled = false;
				}
				if (Object.op_Implicit((Object)(object)image))
				{
					((Behaviour)image).enabled = false;
				}
			}
		}

		public static void Tick(RectTransform parent, Vector3 anchor, float offsetY, bool ready)
		{
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: 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_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			if (!Cfg.PreviewEnabled.Value)
			{
				Hide();
				return;
			}
			int count = Mathf.Clamp(Cfg.PreviewCount.Value, 1, 5);
			if (!Object.op_Implicit((Object)(object)stage))
			{
				Build(parent, count);
			}
			if (!Object.op_Implicit((Object)(object)stage))
			{
				Hide();
				return;
			}
			if (!visible)
			{
				visible = true;
				stage.SetActive(true);
				((Behaviour)camera).enabled = true;
				((Behaviour)image).enabled = true;
				for (int i = 0; i < slots.Count; i++)
				{
					Fill(i);
				}
			}
			((Graphic)image).color = (Color)(ready ? Color.white : new Color(1f, 1f, 1f, 0.45f));
			((Transform)((Graphic)image).rectTransform).position = new Vector3(anchor.x, anchor.y + offsetY, anchor.z);
			if (Object.op_Implicit((Object)(object)orbit))
			{
				orbit.Rotate(Vector3.up, 30f * Time.deltaTime, (Space)1);
			}
			for (int j = 0; j < slots.Count; j++)
			{
				slots[j].Rotate(Vector3.up, 60f * Time.deltaTime, (Space)1);
			}
			for (int k = 0; k < models.Count; k++)
			{
				if (!Object.op_Implicit((Object)(object)models[k]))
				{
					Fill(k);
				}
			}
		}

		private static void Build(RectTransform parent, int count)
		{
			//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_0053: 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_0067: Expected O, but got Unknown
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Expected O, but got Unknown
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: 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_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_0257: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0302: Unknown result type (might be due to invalid IL or missing references)
			//IL_0348: Unknown result type (might be due to invalid IL or missing references)
			//IL_035d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0372: Unknown result type (might be due to invalid IL or missing references)
			//IL_037d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0388: Unknown result type (might be due to invalid IL or missing references)
			//IL_039a: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)parent))
			{
				float num = Mathf.Sin(MathF.PI * 2f / 15f);
				float num2 = 0.22500001f;
				float num3 = 0.5f + num2;
				float num4 = 0.5f * num + num2;
				int num5 = Mathf.RoundToInt(64f * (num3 / num4));
				texture = new RenderTexture(num5, 64, 16, (RenderTextureFormat)0)
				{
					name = "IamItemPreviewTexture",
					antiAliasing = 2,
					hideFlags = (HideFlags)61
				};
				stage = new GameObject("IamItemPreviewStage");
				stage.transform.position = StageOrigin;
				((Object)stage).hideFlags = (HideFlags)61;
				Object.DontDestroyOnLoad((Object)(object)stage);
				GameObject val = new GameObject("Camera");
				val.transform.SetParent(stage.transform, false);
				val.transform.localPosition = new Vector3(0f, 3f * Mathf.Tan(MathF.PI * 2f / 15f), -3f);
				val.transform.localRotation = Quaternion.Euler(24f, 0f, 0f);
				camera = val.AddComponent<Camera>();
				camera.orthographic = true;
				camera.orthographicSize = num4;
				camera.nearClipPlane = 0.05f;
				camera.farClipPlane = 8f;
				camera.clearFlags = (CameraClearFlags)2;
				camera.backgroundColor = new Color(0f, 0f, 0f, 0f);
				camera.targetTexture = texture;
				camera.allowHDR = false;
				camera.allowMSAA = false;
				GameObject val2 = new GameObject("Light");
				val2.transform.SetParent(stage.transform, false);
				val2.transform.localPosition = new Vector3(-0.6f, 1.2f, -1.6f);
				Light obj = val2.AddComponent<Light>();
				obj.type = (LightType)2;
				obj.range = 8f;
				obj.intensity = 3.5f;
				obj.shadows = (LightShadows)0;
				orbit = new GameObject("Orbit").transform;
				orbit.SetParent(stage.transform, false);
				for (int i = 0; i < count; i++)
				{
					float num6 = (float)i * MathF.PI * 2f / (float)count;
					Transform transform = new GameObject("Slot" + i).transform;
					transform.SetParent(orbit, false);
					transform.localPosition = new Vector3(Mathf.Sin(num6) * 0.5f, 0f, Mathf.Cos(num6) * 0.5f);
					transform.localRotation = Quaternion.Euler(0f, Random.Range(0f, 360f), 0f);
					slots.Add(transform);
					models.Add(null);
				}
				GameObject val3 = new GameObject("IamItemPreview", new Type[1] { typeof(RectTransform) });
				val3.transform.SetParent((Transform)(object)parent, false);
				image = val3.AddComponent<RawImage>();
				image.texture = (Texture)(object)texture;
				((Graphic)image).raycastTarget = false;
				RectTransform rectTransform = ((Graphic)image).rectTransform;
				rectTransform.anchorMin = new Vector2(0.5f, 0.5f);
				rectTransform.anchorMax = new Vector2(0.5f, 0.5f);
				rectTransform.pivot = new Vector2(0.5f, 0.5f);
				((Transform)rectTransform).localScale = Vector3.one;
				((Transform)rectTransform).localRotation = Quaternion.identity;
				rectTransform.sizeDelta = new Vector2((float)num5, 64f);
				for (int j = 0; j < count; j++)
				{
					Fill(j);
				}
			}
		}

		private static void Fill(int index)
		{
			if (index < 0 || index >= slots.Count)
			{
				return;
			}
			if (Object.op_Implicit((Object)(object)models[index]))
			{
				Object.Destroy((Object)(object)models[index]);
			}
			models[index] = null;
			for (int i = 0; i < 6; i++)
			{
				ValuableObject val = Targets.PickRandomValuable();
				if (!Object.op_Implicit((Object)(object)val))
				{
					break;
				}
				GameObject val2 = BuildModel(val, slots[index]);
				if (Object.op_Implicit((Object)(object)val2))
				{
					models[index] = val2;
					break;
				}
			}
		}

		private static GameObject BuildModel(ValuableObject source, Transform slot)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: 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_0094: 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_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: 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)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: 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_