Decompiled source of PossessedCart v1.0.0

PossessedCart.dll

Decompiled 14 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 ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("FyiRon")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("A dead player's head thrown into a cart can drive it and fire its cannon.")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Possessed Cart")]
[assembly: AssemblyTitle("PossessedCart")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace PossessedCart
{
	internal static class Loc
	{
		internal static bool Russian;

		private static readonly Dictionary<string, string[]> Table = new Dictionary<string, string[]>
		{
			{
				"cart_not_found",
				new string[2] { "Cart not found (a level with a cart is required)", "Тележка не найдена (нужен уровень с тележкой)" }
			},
			{
				"no_local_player",
				new string[2] { "Local player not found", "Локальный игрок не найден" }
			},
			{
				"sim_on",
				new string[2] { "SIMULATION: camera and controls moved to the cart (Numpad5 to exit)", "СИМУЛЯЦИЯ: камера и управление на тележке (Numpad5 - выйти)" }
			},
			{
				"attached",
				new string[2] { "The head is in the cart and has taken control", "Голова лежит в тележке и получила управление" }
			},
			{
				"stun",
				new string[2] { "The head lost control for 20 seconds", "Голова потеряла управление на 20 секунд" }
			},
			{
				"head_out",
				new string[2] { "The head is out of the cart: control lost", "Голова вне тележки: управление потеряно" }
			},
			{
				"cannon_empty",
				new string[2] { "The cannon is out of charge", "Пушка разряжена" }
			},
			{
				"mode_drive",
				new string[2] { "Cart control mode", "Режим управления тележкой" }
			},
			{
				"mode_spectate",
				new string[2] { "Spectate mode ({0} to resume control)", "Режим наблюдения ({0} - вернуться к управлению)" }
			},
			{
				"hud_stun",
				new string[2] { "STUNNED {0:0.0}s", "ОГЛУШЕНА {0:0.0}с" }
			},
			{
				"hud_stamina",
				new string[2] { "CART STAMINA {0:0}", "СТАМИНА ТЕЛЕЖКИ {0:0}" }
			},
			{
				"hud_aim",
				new string[2] { "AIM", "ПРИЦЕЛ" }
			},
			{
				"hud_spectate",
				new string[2] { "SPECTATING ({0})", "НАБЛЮДЕНИЕ ({0})" }
			},
			{
				"poss_on",
				new string[2] { "Possessed Cart: ON (throw a dead player's head into the cart)", "Одержимая тележка: ВКЛ (брось голову мёртвого игрока в тележку)" }
			},
			{
				"poss_off",
				new string[2] { "Possessed Cart: OFF", "Одержимая тележка: ВЫКЛ" }
			},
			{
				"books",
				new string[2] { "Portability: {0} books, weight reduction {1:0.#}%, next price {2}", "Переносимость: книг {0}, снижение веса {1:0.#}%, цена следующей: {2}" }
			},
			{
				"fixation",
				new string[2] { "Improved fixation: level {0}, physics influence reduced {1:0}%, next price {2}", "Улучшенная фиксация: ур. {0}, снижение влияния физики {1:0}%, цена следующей: {2}" }
			},
			{
				"weapon_on",
				new string[2] { "Head weapon: ON", "Вооружение головы: ВКЛ" }
			},
			{
				"weapon_off",
				new string[2] { "Head weapon: OFF", "Вооружение головы: ВЫКЛ" }
			},
			{
				"reset",
				new string[2] { "All upgrades reset", "Все улучшения сброшены" }
			}
		};

		internal static void Init(string setting)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Invalid comparison between Unknown and I4
			Russian = setting == "Russian" || (setting != "English" && (int)Application.systemLanguage == 30);
		}

		internal static string T(string key, params object[] args)
		{
			if (!Table.TryGetValue(key, out var value))
			{
				return key;
			}
			string text = (Russian ? value[1] : value[0]);
			if (args.Length == 0)
			{
				return text;
			}
			return string.Format(text, args);
		}
	}
	internal static class R
	{
		private const BindingFlags F = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

		private static readonly Dictionary<Type, Dictionary<string, MemberInfo>> cache = new Dictionary<Type, Dictionary<string, MemberInfo>>();

		private static MemberInfo Lookup(Type type, string name)
		{
			if (!cache.TryGetValue(type, out var value))
			{
				value = new Dictionary<string, MemberInfo>();
				cache[type] = value;
			}
			if (value.TryGetValue(name, out var value2))
			{
				return value2;
			}
			Type type2 = type;
			while (type2 != null && value2 == null)
			{
				value2 = (MemberInfo)(((object)type2.GetField(name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) ?? ((object)type2.GetProperty(name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)));
				type2 = type2.BaseType;
			}
			value[name] = value2;
			return value2;
		}

		public static T Get<T>(object o, string name)
		{
			if (o == null)
			{
				return default(T);
			}
			MemberInfo memberInfo = Lookup(o.GetType(), name);
			object obj = null;
			FieldInfo fieldInfo = memberInfo as FieldInfo;
			if (fieldInfo != null)
			{
				obj = fieldInfo.GetValue(o);
			}
			else
			{
				PropertyInfo propertyInfo = memberInfo as PropertyInfo;
				if (propertyInfo != null)
				{
					obj = propertyInfo.GetValue(o);
				}
			}
			if (obj != null)
			{
				return (T)obj;
			}
			return default(T);
		}

		public static void Set(object o, string name, object value)
		{
			if (o != null)
			{
				FieldInfo fieldInfo = Lookup(o.GetType(), name) as FieldInfo;
				if (fieldInfo != null)
				{
					fieldInfo.SetValue(o, value);
				}
			}
		}
	}
	internal static class S
	{
		public static int Books;

		public static int Fixation;

		public static bool Weapon = true;

		public static bool Possessed;

		public static string DriverId = "";

		public static PhysGrabCart Cart;

		public static PlayerDeathHead Head;

		public const float MaxStamina = 100f;

		public static float Stamina = 100f;

		public static float StunTimer;

		public static float DbgSpeed;

		public static bool DbgSprint;

		public static float StunDelay;

		public static bool Aiming;

		public static bool PossessEnabled = true;

		public static float AttachCooldown;

		public static float HeadInCartTimer;

		public static bool Sim;

		public static bool Exhausted;

		public static float InX;

		public static float InY;

		public static float DrivingStamp;

		public static bool InSprint;

		public static bool InFire;

		public static bool InDetach;

		public static bool InAim;

		public static bool InDrive = true;

		public static float InAimYaw;

		public static float LocalAimYaw;

		public static bool LocalDrive = true;

		public static float HeadOutTimer;

		public static float InStamp;

		public static float BookReduction(int n)
		{
			return 1f - Mathf.Pow(0.85f, (float)n);
		}

		public static float FixationReduction(int n)
		{
			return Mathf.Clamp01(0.1f * (float)n);
		}

		public static int BookPrice(int n)
		{
			return Mathf.RoundToInt(11000f * (1f + 0.3f * (float)n));
		}

		public static int FixationPrice(int n)
		{
			return Mathf.RoundToInt(7000f * (1f + 0.2f * (float)n));
		}
	}
	[BepInPlugin("fyiron.possessedcart", "Possessed Cart", "1.0.0")]
	public class Plugin : BaseUnityPlugin, IOnEventCallback
	{
		private struct ZoneKind
		{
			public PhysGrabObject pgo;

			public int kind;

			public PlayerDeathHead head;
		}

		internal static Plugin I;

		internal static ConfigEntry<float> WalkSpeed;

		internal static ConfigEntry<float> SprintSpeed;

		internal static ConfigEntry<float> TurnSpeed;

		internal static ConfigEntry<float> DrainWalk;

		internal static ConfigEntry<float> DrainSprint;

		internal static ConfigEntry<float> RegenIdle;

		internal static ConfigEntry<float> RegenPulled;

		internal static ConfigEntry<float> WeightRef;

		internal static ConfigEntry<Vector3> HeadOffset;

		internal static ConfigEntry<KeyCode> FireKey;

		internal static ConfigEntry<float> Accel;

		internal static ConfigEntry<float> CamDistance;

		internal static ConfigEntry<float> CamHeight;

		internal static ConfigEntry<float> HeadSide;

		internal static ConfigEntry<float> AimBack;

		internal static ConfigEntry<float> AimUp;

		internal static ConfigEntry<KeyCode> AimKey;

		internal static ConfigEntry<KeyCode> DetachKey;

		internal static ConfigEntry<KeyCode> SpectateKey;

		internal static ConfigEntry<bool> EnablePossessed;

		internal static ConfigEntry<bool> EnableWeapon;

		internal static ConfigEntry<int> PortabilityBooks;

		internal static ConfigEntry<int> FixationLevel;

		internal static ConfigEntry<string> LanguageCfg;

		private const byte EvState = 190;

		private const byte EvInput = 191;

		private float stateSendTimer;

		private float inputSendTimer;

		private Vector2 lastSentMv;

		private bool lastSentSprint;

		private bool lastSentAim;

		private bool lastSentDrive;

		private bool fireLatch;

		private bool detachLatch;

		private string toast = "";

		private float toastTimer;

		private float lastStateTime;

		private float hudTimer;

		private string hudLabel = "";

		private static PhysGrabCart cartCache;

		private static float cartCacheUntil;

		private static PlayerAvatar avatarCache;

		private static string avatarCacheId = "";

		private static ItemCartCannonMain cannonCache;

		private static float cannonCacheUntil;

		private static PhysGrabCart anchorCart;

		private static BoxCollider anchorBox;

		private bool wasLocalDriver;

		private string voiceId = "";

		private static readonly Collider[] zoneBuf = (Collider[])(object)new Collider[128];

		private static readonly List<PhysGrabObject> zoneInside = new List<PhysGrabObject>();

		private static readonly List<PhysGrabObject> zoneAbove = new List<PhysGrabObject>();

		private static readonly HashSet<PhysGrabObject> zoneSeen = new HashSet<PhysGrabObject>();

		private static readonly List<PlayerDeathHead> zoneHeads = new List<PlayerDeathHead>();

		private static readonly Dictionary<Rigidbody, ZoneKind> kindCache = new Dictionary<Rigidbody, ZoneKind>();

		private static int itemMask = -1;

		private void Awake()
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Expected O, but got Unknown
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Expected O, but got Unknown
			//IL_02d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c4: Unknown result type (might be due to invalid IL or missing references)
			I = this;
			LanguageCfg = ((BaseUnityPlugin)this).Config.Bind<string>("General", "Language", "Auto", new ConfigDescription("Interface language: Auto (follows the system language), English or Russian", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[3] { "Auto", "English", "Russian" }), Array.Empty<object>()));
			Loc.Init(LanguageCfg.Value);
			EnablePossessed = ((BaseUnityPlugin)this).Config.Bind<bool>("Upgrades", "PossessedCart", true, "Possessed Cart: a dead player's head thrown into the cart can drive it (host setting)");
			EnableWeapon = ((BaseUnityPlugin)this).Config.Bind<bool>("Upgrades", "Weapon", true, "Cart weapon: the driving head can fire the cart cannon (host setting)");
			PortabilityBooks = ((BaseUnityPlugin)this).Config.Bind<int>("Upgrades", "PortabilityBooks", 0, new ConfigDescription("Portability level (books in the cart), 0-10: lowers the weight of cargo, 15% per book with diminishing returns (host setting)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 10), Array.Empty<object>()));
			FixationLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Upgrades", "FixationLevel", 0, new ConfigDescription("Improved fixation level, 0-9: cargo holds together and follows the cart, 10% per level (host setting)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 9), Array.Empty<object>()));
			WalkSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Drive", "WalkSpeed", 3f, "Cart speed when driven by the head");
			SprintSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Drive", "SprintSpeed", 6f, "Cart speed while sprinting");
			TurnSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Drive", "TurnSpeed", 2.2f, "Turn rate (grows with sprint)");
			Accel = ((BaseUnityPlugin)this).Config.Bind<float>("Drive", "Acceleration", 50f, "Cart acceleration (m/s per second). Must clearly exceed floor friction, otherwise speed hits a ceiling");
			CamDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "Distance", 2f, "Simulation only: how far the camera sits behind the head spot");
			CamHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "Height", 0f, "Simulation only: how high the camera sits above the head spot");
			HeadSide = ((BaseUnityPlugin)this).Config.Bind<float>("Head", "Side", -1f, "Which end of the cart the camera spot is on: -1 rear (handle side), 1 front");
			DrainWalk = ((BaseUnityPlugin)this).Config.Bind<float>("Stamina", "DrainWalk", 4f, "Cart stamina drained per second while driving");
			DrainSprint = ((BaseUnityPlugin)this).Config.Bind<float>("Stamina", "DrainSprint", 8f, "Cart stamina drained per second while sprinting");
			RegenIdle = ((BaseUnityPlugin)this).Config.Bind<float>("Stamina", "RegenIdle", 2f, "Stamina regained per second while the cart stands still");
			RegenPulled = ((BaseUnityPlugin)this).Config.Bind<float>("Stamina", "RegenPulled", 6f, "Stamina regained per second while a living player pulls the cart");
			WeightRef = ((BaseUnityPlugin)this).Config.Bind<float>("Stamina", "WeightRef", 100f, "Cargo mass at which the driven cart's speed drops by a third (cargo weight does not drain stamina)");
			HeadOffset = ((BaseUnityPlugin)this).Config.Bind<Vector3>("Head", "OffsetFromEdge", new Vector3(0f, 0.1f, 0f), "Extra offset of the camera spot from the cart's rear edge (cart axes: x sideways, y up, z forward)");
			FireKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Weapon", "FireKey", (KeyCode)323, "Driver: fire the cannon (only while aiming)");
			SpectateKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Head", "SpectateKey", (KeyCode)102, "Driver: toggle drive mode / spectate mode (control rights stay with the head)");
			DetachKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Head", "DetachKey", (KeyCode)120, "Driver: let go of the cart");
			AimKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Weapon", "AimKey", (KeyCode)324, "Driver: hold to aim (camera moves to the cannon)");
			AimBack = ((BaseUnityPlugin)this).Config.Bind<float>("Weapon", "AimBack", 1f, "Aim mode: how far the camera sits behind the cannon");
			AimUp = ((BaseUnityPlugin)this).Config.Bind<float>("Weapon", "AimUp", 0.8f, "Aim mode: how high the camera sits above the cannon");
			new Harmony("fyiron.possessedcart").PatchAll(typeof(Plugin).Assembly);
			PhotonNetwork.AddCallbackTarget((object)this);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Possessed Cart v1.0.0 by FyiRon loaded.");
		}

		private void OnDestroy()
		{
			PhotonNetwork.RemoveCallbackTarget((object)this);
		}

		internal static PhysGrabCart FindCart()
		{
			if (Time.time < cartCacheUntil)
			{
				return cartCache;
			}
			cartCache = null;
			PhysGrabCart[] array = Object.FindObjectsByType<PhysGrabCart>((FindObjectsSortMode)0);
			foreach (PhysGrabCart val in array)
			{
				if (Object.op_Implicit((Object)(object)val) && !val.isSmallCart)
				{
					cartCache = val;
					break;
				}
			}
			cartCacheUntil = Time.time + 1f;
			return cartCache;
		}

		internal static PlayerAvatar AvatarById(string id)
		{
			if (string.IsNullOrEmpty(id) || (Object)(object)GameDirector.instance == (Object)null)
			{
				return null;
			}
			if (Object.op_Implicit((Object)(object)avatarCache) && avatarCacheId == id)
			{
				return avatarCache;
			}
			foreach (PlayerAvatar player in GameDirector.instance.PlayerList)
			{
				if (Object.op_Implicit((Object)(object)player) && R.Get<string>(player, "steamID") == id)
				{
					avatarCache = player;
					avatarCacheId = id;
					return player;
				}
			}
			return null;
		}

		internal static bool IsLocalDriver()
		{
			if (!S.Possessed)
			{
				return false;
			}
			PlayerAvatar val = AvatarById(S.DriverId);
			if (Object.op_Implicit((Object)(object)val))
			{
				return R.Get<bool>(val, "isLocal");
			}
			return false;
		}

		private void Update()
		{
			if (toastTimer > 0f)
			{
				toastTimer -= Time.deltaTime;
			}
			bool flag = SemiFunc.IsMasterClientOrSingleplayer();
			if (flag)
			{
				MasterTick();
			}
			else if (S.Possessed && Time.time - lastStateTime > 3f)
			{
				S.Possessed = false;
				S.DriverId = "";
			}
			if (S.Possessed)
			{
				hudTimer -= Time.deltaTime;
				if (hudTimer <= 0f)
				{
					hudTimer = 0.1f;
					hudLabel = BuildHudLabel(flag);
				}
			}
			LocalDriverInput();
			VoiceEffect();
			SimCamera();
		}

		private void SimCamera()
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: 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_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: 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_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: 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_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			S.Aiming = false;
			if (!S.Sim || !S.Possessed || !S.LocalDrive || !IsLocalDriver() || (Object)(object)CameraPosition.instance == (Object)null)
			{
				return;
			}
			PhysGrabCart val = (Object.op_Implicit((Object)(object)S.Cart) ? S.Cart : FindCart());
			if (!Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			Camera main = Camera.main;
			Vector3 val2 = (Object.op_Implicit((Object)(object)main) ? ((Component)main).transform.forward : ((Component)val).transform.forward);
			ItemCartCannonMain val3 = (Input.GetKey(AimKey.Value) ? FindCannon(val) : null);
			Vector3 val5;
			if (Object.op_Implicit((Object)(object)val3))
			{
				S.Aiming = true;
				Vector3 val4 = Vector3.ProjectOnPlane(val2, Vector3.up);
				if (((Vector3)(ref val4)).sqrMagnitude < 0.0001f)
				{
					val4 = ((Component)val).transform.forward;
				}
				((Vector3)(ref val4)).Normalize();
				val5 = ((Component)val3).transform.position - val4 * AimBack.Value + Vector3.up * AimUp.Value;
				Quaternion val6 = Quaternion.LookRotation(val4, Vector3.up);
				S.LocalAimYaw = ((Quaternion)(ref val6)).eulerAngles.y;
			}
			else
			{
				Vector3 val7 = HeadAnchor(val);
				Vector3 val8 = -val2 * CamDistance.Value + Vector3.up * CamHeight.Value;
				float num = Mathf.Max(0.1f, ((Vector3)(ref val8)).magnitude);
				Vector3 val9 = val8 / num;
				val5 = val7 + val9 * num;
				RaycastHit val10 = default(RaycastHit);
				if (Physics.Raycast(val7, val9, ref val10, num, LayerMask.op_Implicit(SemiFunc.LayerMaskGetVisionObstruct())))
				{
					val5 = val7 + val9 * Mathf.Max(0.3f, ((RaycastHit)(ref val10)).distance - 0.2f);
				}
			}
			CameraPosition.instance.OverridePosition(val5, 0.1f);
			if (S.Sim)
			{
				PlayerAvatar instance = PlayerAvatar.instance;
				if (Object.op_Implicit((Object)(object)instance) && Object.op_Implicit((Object)(object)instance.playerAvatarVisuals))
				{
					R.Set(instance.playerAvatarVisuals, "showSelfOverrideTimer", 0.2f);
				}
			}
		}

		internal static ItemCartCannonMain FindCannon(PhysGrabCart cart)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)cannonCache) && Time.time < cannonCacheUntil)
			{
				return cannonCache;
			}
			ItemCartCannonMain result = null;
			float num = 3f;
			ItemCartCannonMain[] array = Object.FindObjectsByType<ItemCartCannonMain>((FindObjectsSortMode)0);
			foreach (ItemCartCannonMain val in array)
			{
				if (Object.op_Implicit((Object)(object)val))
				{
					float num2 = Vector3.Distance(((Component)val).transform.position, ((Component)cart).transform.position);
					if (num2 < num)
					{
						num = num2;
						result = val;
					}
				}
			}
			cannonCache = result;
			cannonCacheUntil = Time.time + 0.5f;
			return result;
		}

		internal static Vector3 HeadAnchor(PhysGrabCart cart)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: 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_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: 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_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = ((Component)cart).transform;
			if ((Object)(object)cart != (Object)(object)anchorCart)
			{
				anchorCart = cart;
				Transform val = R.Get<Transform>(cart, "inCart");
				anchorBox = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<BoxCollider>() : null);
			}
			BoxCollider val2 = anchorBox;
			Vector3 val5 = default(Vector3);
			if (Object.op_Implicit((Object)(object)val2))
			{
				Vector3 val3 = transform.InverseTransformPoint(((Component)val2).transform.TransformPoint(val2.center));
				Vector3 val4 = Vector3.Scale(val2.size, ((Component)val2).transform.lossyScale);
				Vector3 lossyScale = transform.lossyScale;
				float num = val4.y * 0.5f / Mathf.Max(0.01f, lossyScale.y);
				float num2 = val4.z * 0.5f / Mathf.Max(0.01f, lossyScale.z);
				((Vector3)(ref val5))..ctor(val3.x, val3.y + num, val3.z + HeadSide.Value * num2);
			}
			else
			{
				val5 = transform.InverseTransformPoint((Object.op_Implicit((Object)(object)cart.handlePoint) ? cart.handlePoint : transform).position);
			}
			val5 += HeadOffset.Value;
			return transform.TransformPoint(val5);
		}

		internal void Toast(string msg)
		{
			toast = msg;
			toastTimer = 4f;
			((BaseUnityPlugin)this).Logger.LogInfo((object)msg);
		}

		internal void AttachWith(PhysGrabCart cart, PlayerAvatar driver, bool sim)
		{
			S.Cart = cart;
			S.Sim = sim;
			S.Head = (sim ? null : R.Get<PlayerDeathHead>(driver, "playerDeathHead"));
			S.DriverId = R.Get<string>(driver, "steamID");
			S.Possessed = true;
			S.Stamina = 100f;
			S.StunTimer = 0f;
			S.Exhausted = false;
			S.InX = (S.InY = 0f);
			S.InSprint = (S.InFire = (S.InDetach = (S.InAim = false)));
			S.StunDelay = 0f;
			S.HeadInCartTimer = 0f;
			S.HeadOutTimer = 0f;
			Toast(Loc.T(sim ? "sim_on" : "attached"));
			SendState();
		}

		internal void Release(string reason)
		{
			if (S.Possessed)
			{
				S.Possessed = false;
				S.Sim = false;
				S.Head = null;
				S.DriverId = "";
				S.StunDelay = 0f;
				S.AttachCooldown = 3f;
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Possession released: " + reason));
				SendState();
			}
		}

		private void MasterTick()
		{
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			if (S.Possessed)
			{
				PlayerAvatar val = AvatarById(S.DriverId);
				bool flag = (S.Sim ? Object.op_Implicit((Object)(object)val) : (Object.op_Implicit((Object)(object)val) && R.Get<bool>(val, "isDisabled") && Object.op_Implicit((Object)(object)S.Head)));
				if (!Object.op_Implicit((Object)(object)S.Cart) || !flag)
				{
					Release("cart or head gone, or the player respawned");
				}
			}
			S.PossessEnabled = EnablePossessed.Value;
			S.Weapon = EnableWeapon.Value;
			S.Books = Mathf.Clamp(PortabilityBooks.Value, 0, 10);
			S.Fixation = Mathf.Clamp(FixationLevel.Value, 0, 9);
			if (!S.PossessEnabled && S.Possessed)
			{
				Release("disabled in config");
			}
			if (S.AttachCooldown > 0f)
			{
				S.AttachCooldown -= Time.deltaTime;
			}
			if (S.Possessed && S.InAim && S.InDrive && Object.op_Implicit((Object)(object)S.Cart) && Time.time - S.InStamp < 0.5f)
			{
				ItemCartCannonMain val2 = FindCannon(S.Cart);
				if (Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)val2.currentCorrector))
				{
					val2.currentCorrector.transform.rotation = Quaternion.Euler(0f, S.InAimYaw, 0f);
				}
			}
			if (S.InDetach)
			{
				S.InDetach = false;
				if (S.Possessed)
				{
					Release("driver let go");
				}
			}
			if (S.StunDelay > 0f)
			{
				S.StunDelay -= Time.deltaTime;
				if (S.StunDelay <= 0f)
				{
					S.StunDelay = 0f;
					S.StunTimer = 20f;
					S.Stamina = 0f;
					Toast(Loc.T("stun"));
				}
			}
			if (S.StunTimer > 0f)
			{
				S.StunTimer -= Time.deltaTime;
				if (S.StunTimer <= 0f)
				{
					S.StunTimer = 0f;
					S.Stamina = 1f;
					S.Exhausted = true;
				}
			}
			stateSendTimer -= Time.deltaTime;
			if (stateSendTimer <= 0f)
			{
				stateSendTimer = (S.Possessed ? 0.1f : 0.5f);
				SendState(reliable: false);
			}
		}

		private void SendState(bool reliable = true)
		{
			//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_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Expected O, but got Unknown
			if (SemiFunc.IsMultiplayer())
			{
				object[] array = new object[7]
				{
					S.Possessed,
					S.DriverId ?? "",
					S.Stamina,
					S.StunTimer,
					S.Weapon,
					S.Books,
					S.Fixation
				};
				PhotonNetwork.RaiseEvent((byte)190, (object)array, new RaiseEventOptions
				{
					Receivers = (ReceiverGroup)0
				}, reliable ? SendOptions.SendReliable : SendOptions.SendUnreliable);
			}
		}

		public void OnEvent(EventData e)
		{
			try
			{
				if (e.Code == 190 && !SemiFunc.IsMasterClientOrSingleplayer())
				{
					object[] obj = (object[])e.CustomData;
					lastStateTime = Time.time;
					S.Possessed = (bool)obj[0];
					S.DriverId = (string)obj[1];
					S.Stamina = (float)obj[2];
					S.StunTimer = (float)obj[3];
					S.Weapon = (bool)obj[4];
					S.Books = (int)obj[5];
					S.Fixation = (int)obj[6];
				}
				else
				{
					if (e.Code != 191 || !SemiFunc.IsMasterClientOrSingleplayer())
					{
						return;
					}
					object[] array = (object[])e.CustomData;
					if (!((string)array[0] != S.DriverId))
					{
						S.InX = Mathf.Clamp((float)array[1], -1f, 1f);
						S.InY = Mathf.Clamp((float)array[2], -1f, 1f);
						S.InSprint = (bool)array[3];
						S.InAim = array.Length > 6 && (bool)array[6];
						S.InDrive = array.Length <= 7 || (bool)array[7];
						if (array.Length > 8)
						{
							S.InAimYaw = (float)array[8];
						}
						if ((bool)array[4])
						{
							S.InFire = true;
						}
						if (array.Length > 5 && (bool)array[5])
						{
							S.InDetach = true;
						}
						S.InStamp = Time.time;
					}
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("OnEvent: " + ex.Message));
			}
		}

		private void LocalDriverInput()
		{
			//IL_0029: 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_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: 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_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: 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_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Unknown result type (might be due to invalid IL or missing references)
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0305: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_030f: Expected O, but got Unknown
			if (!IsLocalDriver())
			{
				wasLocalDriver = false;
				return;
			}
			if (!wasLocalDriver)
			{
				wasLocalDriver = true;
				S.LocalDrive = true;
			}
			if (Input.GetKeyDown(SpectateKey.Value))
			{
				S.LocalDrive = !S.LocalDrive;
				Toast(Loc.T(S.LocalDrive ? "mode_drive" : "mode_spectate", SpectateKey.Value));
			}
			bool localDrive = S.LocalDrive;
			Vector2 val = Vector2.zero;
			bool flag = false;
			if (localDrive)
			{
				if (S.Sim)
				{
					SemiFunc.InputDisableMovement();
					((Vector2)(ref val))..ctor((Input.GetKey((KeyCode)100) ? 1f : 0f) - (Input.GetKey((KeyCode)97) ? 1f : 0f), (Input.GetKey((KeyCode)119) ? 1f : 0f) - (Input.GetKey((KeyCode)115) ? 1f : 0f));
					flag = Input.GetKey((KeyCode)304);
				}
				else
				{
					val = SemiFunc.InputMovement();
					flag = SemiFunc.InputHold((InputKey)15);
				}
				if (Input.GetKeyDown(FireKey.Value))
				{
					fireLatch = true;
				}
			}
			else
			{
				fireLatch = false;
			}
			if (Input.GetKeyDown(DetachKey.Value))
			{
				detachLatch = true;
			}
			bool flag2 = localDrive && Input.GetKey(AimKey.Value);
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				S.InX = val.x;
				S.InY = val.y;
				S.InSprint = flag;
				S.InAim = flag2;
				S.InDrive = localDrive;
				S.InAimYaw = S.LocalAimYaw;
				if (fireLatch)
				{
					S.InFire = true;
					fireLatch = false;
				}
				if (detachLatch)
				{
					S.InDetach = true;
					detachLatch = false;
				}
				S.InStamp = Time.time;
				return;
			}
			inputSendTimer -= Time.deltaTime;
			if (val != lastSentMv || flag != lastSentSprint || flag2 != lastSentAim || localDrive != lastSentDrive || !(inputSendTimer > 0f) || fireLatch || detachLatch)
			{
				inputSendTimer = 0.033f;
				lastSentMv = val;
				lastSentSprint = flag;
				lastSentAim = flag2;
				lastSentDrive = localDrive;
				bool flag3 = fireLatch || detachLatch;
				object[] array = new object[9]
				{
					S.DriverId,
					val.x,
					val.y,
					flag,
					fireLatch,
					detachLatch,
					flag2,
					localDrive,
					S.LocalAimYaw
				};
				fireLatch = false;
				detachLatch = false;
				PhotonNetwork.RaiseEvent((byte)191, (object)array, new RaiseEventOptions
				{
					Receivers = (ReceiverGroup)2
				}, flag3 ? SendOptions.SendReliable : SendOptions.SendUnreliable);
			}
		}

		private void VoiceEffect()
		{
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			PlayerAvatar val = (S.Possessed ? AvatarById(S.DriverId) : null);
			string text = (Object.op_Implicit((Object)(object)val) ? S.DriverId : "");
			if (text != voiceId)
			{
				PlayerAvatar val2 = AvatarById(voiceId);
				PlayerVoiceChat val3 = (Object.op_Implicit((Object)(object)val2) ? R.Get<PlayerVoiceChat>(val2, "voiceChat") : null);
				if (Object.op_Implicit((Object)(object)val3))
				{
					val3.ToggleMixer(R.Get<bool>(val2, "isDisabled"), false);
				}
				PlayerVoiceChat val4 = (Object.op_Implicit((Object)(object)val) ? R.Get<PlayerVoiceChat>(val, "voiceChat") : null);
				if (Object.op_Implicit((Object)(object)val4))
				{
					val4.ToggleMixer(false, true);
				}
				voiceId = text;
			}
			if (Object.op_Implicit((Object)(object)val))
			{
				PlayerVoiceChat val5 = R.Get<PlayerVoiceChat>(val, "voiceChat");
				PlayerDeathHead val6 = R.Get<PlayerDeathHead>(val, "playerDeathHead");
				PhysGrabObject val7 = (Object.op_Implicit((Object)(object)val6) ? ((Component)val6).GetComponent<PhysGrabObject>() : null);
				if (Object.op_Implicit((Object)(object)val5) && Object.op_Implicit((Object)(object)val7) && !S.Sim)
				{
					val5.OverridePositionActivate(val7.centerPoint, 0.1f);
				}
			}
		}

		private string BuildHudLabel(bool master)
		{
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			if (S.StunTimer > 0f)
			{
				return Loc.T("hud_stun", S.StunTimer);
			}
			string text = Loc.T("hud_stamina", S.Stamina);
			if (S.Aiming)
			{
				text = text + "  " + Loc.T("hud_aim");
			}
			if (!S.LocalDrive && IsLocalDriver())
			{
				text = text + "  " + Loc.T("hud_spectate", SpectateKey.Value);
			}
			return text;
		}

		private void OnGUI()
		{
			//IL_0137: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: 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_00bd: 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_00d7: 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_00fd: 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)
			if (S.Possessed && (IsLocalDriver() || SemiFunc.IsMasterClientOrSingleplayer()))
			{
				float num = 220f;
				float num2 = 16f;
				float num3 = (float)Screen.width / 2f - num / 2f;
				float num4 = (float)Screen.height - 70f;
				GUI.color = new Color(0f, 0f, 0f, 0.6f);
				GUI.DrawTexture(new Rect(num3 - 2f, num4 - 2f, num + 4f, num2 + 4f), (Texture)(object)Texture2D.whiteTexture);
				float num5 = Mathf.Clamp01(S.Stamina / 100f);
				GUI.color = ((S.StunTimer > 0f) ? Color.red : Color.Lerp(new Color(1f, 0.4f, 0f), new Color(0.3f, 1f, 0.2f), num5));
				GUI.DrawTexture(new Rect(num3, num4, num * num5, num2), (Texture)(object)Texture2D.whiteTexture);
				GUI.color = Color.white;
				GUI.Label(new Rect(num3, num4 - 20f, num + 100f, 20f), hudLabel);
			}
			if (toastTimer > 0f)
			{
				GUI.color = Color.white;
				GUI.Label(new Rect(20f, (float)(Screen.height - 90), 900f, 24f), "[CartMod] " + toast);
			}
		}

		private static void ScanZone(PhysGrabCart cart)
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: 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_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: 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_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c1: 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_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02db: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
			zoneInside.Clear();
			zoneAbove.Clear();
			zoneSeen.Clear();
			zoneHeads.Clear();
			Transform val = R.Get<Transform>(cart, "inCart");
			if (!Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			if (itemMask < 0)
			{
				itemMask = LayerMask.GetMask(new string[1] { "PhysGrabObject" });
			}
			Vector3[] array = (Vector3[])(object)new Vector3[3] { val.right, val.up, val.forward };
			int num = 1;
			float num2 = 0f;
			float num3 = 1f;
			for (int i = 0; i < 3; i++)
			{
				float num4 = Vector3.Dot(array[i], Vector3.up);
				if (Mathf.Abs(num4) > num2)
				{
					num2 = Mathf.Abs(num4);
					num = i;
					num3 = ((num4 >= 0f) ? 1f : (-1f));
				}
			}
			Vector3 lossyScale = val.lossyScale;
			Vector3 val2 = new Vector3(Mathf.Abs(lossyScale.x), Mathf.Abs(lossyScale.y), Mathf.Abs(lossyScale.z)) * 0.5f;
			Vector3 zero = Vector3.zero;
			((Vector3)(ref zero))[num] = 0.5f * num3;
			int num5 = num;
			((Vector3)(ref val2))[num5] = ((Vector3)(ref val2))[num5] * 2f;
			int num6 = Physics.OverlapBoxNonAlloc(val.TransformPoint(zero), val2, zoneBuf, val.rotation, itemMask, (QueryTriggerInteraction)1);
			for (int j = 0; j < num6; j++)
			{
				Collider val3 = zoneBuf[j];
				if (!Object.op_Implicit((Object)(object)val3))
				{
					continue;
				}
				Rigidbody attachedRigidbody = val3.attachedRigidbody;
				if (!Object.op_Implicit((Object)(object)attachedRigidbody) || !kindCache.TryGetValue(attachedRigidbody, out var value))
				{
					value = default(ZoneKind);
					PhysGrabObject componentInParent = ((Component)val3).GetComponentInParent<PhysGrabObject>();
					if (Object.op_Implicit((Object)(object)componentInParent))
					{
						value.pgo = componentInParent;
						PlayerDeathHead componentInParent2 = ((Component)componentInParent).GetComponentInParent<PlayerDeathHead>();
						if (Object.op_Implicit((Object)(object)componentInParent2))
						{
							value.kind = 2;
							value.head = componentInParent2;
						}
						else if (Object.op_Implicit((Object)(object)((Component)componentInParent).GetComponentInParent<ValuableObject>()) || Object.op_Implicit((Object)(object)((Component)componentInParent).GetComponentInParent<ItemAttributes>()))
						{
							value.kind = 1;
						}
					}
					if (Object.op_Implicit((Object)(object)attachedRigidbody))
					{
						if (kindCache.Count > 1024)
						{
							kindCache.Clear();
						}
						kindCache[attachedRigidbody] = value;
					}
				}
				if (value.kind == 0)
				{
					continue;
				}
				PhysGrabObject pgo = value.pgo;
				if (!Object.op_Implicit((Object)(object)pgo) || !Object.op_Implicit((Object)(object)pgo.rb) || pgo.rb.isKinematic || !zoneSeen.Add(pgo))
				{
					continue;
				}
				Vector3 val4 = val.InverseTransformPoint(pgo.rb.worldCenterOfMass);
				bool flag = Mathf.Abs(val4.x) <= 0.5f && Mathf.Abs(val4.y) <= 0.5f && Mathf.Abs(val4.z) <= 0.5f;
				if (value.kind == 2)
				{
					if (Object.op_Implicit((Object)(object)value.head) && flag)
					{
						zoneHeads.Add(value.head);
					}
				}
				else if (flag)
				{
					zoneInside.Add(pgo);
				}
				else
				{
					zoneAbove.Add(pgo);
				}
			}
		}

		private static void Couple(PhysGrabObject pgo, Rigidbody cartRb, float k)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: 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_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: 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)
			if (!(k <= 0f))
			{
				Vector3 pointVelocity = cartRb.GetPointVelocity(pgo.rb.worldCenterOfMass);
				Vector3 val = pgo.rb.linearVelocity - pointVelocity;
				Vector3 val2 = default(Vector3);
				((Vector3)(ref val2))..ctor(val.x * k, (val.y > 0f) ? (val.y * k) : 0f, val.z * k);
				Rigidbody rb = pgo.rb;
				rb.linearVelocity -= val2;
				Vector3 angularVelocity = pgo.rb.angularVelocity;
				angularVelocity.y = Mathf.Lerp(angularVelocity.y, cartRb.angularVelocity.y, k);
				angularVelocity.x *= 1f - k * 0.8f;
				angularVelocity.z *= 1f - k * 0.8f;
				pgo.rb.angularVelocity = angularVelocity;
			}
		}

		internal static void CartFixedTick(PhysGrabCart cart)
		{
			//IL_046e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0473: Unknown result type (might be due to invalid IL or missing references)
			//IL_0477: Unknown result type (might be due to invalid IL or missing references)
			//IL_0483: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_05fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0600: Unknown result type (might be due to invalid IL or missing references)
			//IL_0604: Unknown result type (might be due to invalid IL or missing references)
			//IL_060e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0613: Unknown result type (might be due to invalid IL or missing references)
			//IL_0615: Unknown result type (might be due to invalid IL or missing references)
			//IL_0617: Unknown result type (might be due to invalid IL or missing references)
			//IL_0625: Unknown result type (might be due to invalid IL or missing references)
			//IL_062a: Unknown result type (might be due to invalid IL or missing references)
			//IL_062c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0642: Unknown result type (might be due to invalid IL or missing references)
			//IL_0647: Unknown result type (might be due to invalid IL or missing references)
			//IL_064a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0651: Unknown result type (might be due to invalid IL or missing references)
			//IL_0658: Unknown result type (might be due to invalid IL or missing references)
			//IL_065f: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_06c9: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)cart) || cart.isSmallCart)
			{
				return;
			}
			Rigidbody component = ((Component)cart).GetComponent<Rigidbody>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				return;
			}
			float fixedDeltaTime = Time.fixedDeltaTime;
			float num = S.BookReduction(S.Books);
			float num2 = S.FixationReduction(S.Fixation);
			if (num <= 0f && num2 <= 0f && !S.PossessEnabled && !S.Possessed)
			{
				return;
			}
			ScanZone(cart);
			bool flag = false;
			foreach (PhysGrabObject item in zoneInside)
			{
				if (item.grabbed)
				{
					flag = true;
					break;
				}
			}
			if (!flag)
			{
				foreach (PhysGrabObject item2 in zoneAbove)
				{
					if (item2.grabbed)
					{
						flag = true;
						break;
					}
				}
			}
			float num3 = Mathf.Lerp(0f, 0.9f, num2);
			float k = num3 * 0.5f;
			float num4 = 0f;
			foreach (PhysGrabObject item3 in zoneInside)
			{
				if (!item3.grabbed)
				{
					float num5 = ((item3.massOriginal > 0f) ? item3.massOriginal : item3.rb.mass);
					num4 += num5 * (1f - num);
					float num6 = 1f - num;
					if (flag)
					{
						num6 *= 1f - 0.8f * num2;
					}
					if (num6 < 0.999f)
					{
						item3.OverrideMass(Mathf.Max(0.2f, num5 * num6), 0.1f);
					}
					Couple(item3, component, num3);
				}
			}
			foreach (PhysGrabObject item4 in zoneAbove)
			{
				if (!item4.grabbed)
				{
					if (flag && num2 > 0f)
					{
						float num7 = ((item4.massOriginal > 0f) ? item4.massOriginal : item4.rb.mass);
						item4.OverrideMass(Mathf.Max(0.2f, num7 * (1f - 0.8f * num2)), 0.1f);
					}
					Couple(item4, component, k);
				}
			}
			if (S.PossessEnabled && !S.Possessed && S.AttachCooldown <= 0f)
			{
				PlayerDeathHead val = null;
				PlayerAvatar driver = null;
				foreach (PlayerDeathHead zoneHead in zoneHeads)
				{
					if (!Object.op_Implicit((Object)(object)zoneHead))
					{
						continue;
					}
					PhysGrabObject component2 = ((Component)zoneHead).GetComponent<PhysGrabObject>();
					if (Object.op_Implicit((Object)(object)component2) && !component2.grabbed)
					{
						PlayerAvatar val2 = R.Get<PlayerAvatar>(zoneHead, "playerAvatar");
						if (Object.op_Implicit((Object)(object)val2) && R.Get<bool>(val2, "isDisabled"))
						{
							val = zoneHead;
							driver = val2;
							break;
						}
					}
				}
				if (Object.op_Implicit((Object)(object)val))
				{
					S.HeadInCartTimer += fixedDeltaTime;
					if (S.HeadInCartTimer > 0.5f && (Object)(object)I != (Object)null)
					{
						I.AttachWith(cart, driver, sim: false);
					}
				}
				else
				{
					S.HeadInCartTimer = 0f;
				}
			}
			if (!S.Possessed || (Object)(object)cart != (Object)(object)S.Cart || (!S.Sim && !Object.op_Implicit((Object)(object)S.Head)))
			{
				return;
			}
			if (Object.op_Implicit((Object)(object)S.Head))
			{
				PhysGrabObject component3 = ((Component)S.Head).GetComponent<PhysGrabObject>();
				if (zoneHeads.Contains(S.Head) && Object.op_Implicit((Object)(object)component3) && !component3.grabbed)
				{
					S.HeadOutTimer = 0f;
				}
				else
				{
					S.HeadOutTimer += fixedDeltaTime;
					if (S.HeadOutTimer > 0.4f && (Object)(object)I != (Object)null)
					{
						I.Toast(Loc.T("head_out"));
						I.Release("head fell out or was pulled out");
						return;
					}
				}
			}
			PhysGrabObject component4 = ((Component)cart).GetComponent<PhysGrabObject>();
			List<PhysGrabber> list = R.Get<List<PhysGrabber>>(component4, "playerGrabbing");
			bool flag2 = list != null && list.Count > 0;
			bool flag3 = R.Get<bool>(cart, "cartBeingPulled");
			float num8 = 1f + num4 / Mathf.Max(1f, WeightRef.Value);
			Vector3 linearVelocity = component.linearVelocity;
			Vector3 val3 = default(Vector3);
			((Vector3)(ref val3))..ctor(linearVelocity.x, 0f, linearVelocity.z);
			S.DbgSpeed = ((Vector3)(ref val3)).magnitude;
			S.DbgSprint = false;
			bool flag4 = S.StunTimer > 0f;
			bool num9 = Time.time - S.InStamp < 0.5f;
			float num10 = (num9 ? S.InX : 0f);
			float num11 = (num9 ? S.InY : 0f);
			bool flag5 = num9 && S.InSprint;
			if (S.Exhausted && S.Stamina >= 10f)
			{
				S.Exhausted = false;
			}
			if (S.Stamina <= 0f)
			{
				S.Stamina = 0f;
				S.Exhausted = true;
			}
			bool num12 = num9 && S.InDrive && !flag2 && !flag4 && !S.Exhausted && S.Stamina > 0f;
			bool flag6 = Mathf.Abs(num11) > 0.05f || Mathf.Abs(num10) > 0.05f;
			bool flag7 = false;
			if (num12 && flag6)
			{
				S.DrivingStamp = Time.time;
				if (Object.op_Implicit((Object)(object)component4))
				{
					component4.OverrideMass(4f, 0.1f);
				}
				bool flag8 = (S.DbgSprint = flag5 && Mathf.Abs(num11) > 0.05f);
				float num13 = (flag8 ? SprintSpeed.Value : WalkSpeed.Value) / (1f + (num8 - 1f) * 0.5f);
				Vector3 val4 = Vector3.ProjectOnPlane(((Component)cart).transform.forward, Vector3.up);
				Vector3 val5 = ((Vector3)(ref val4)).normalized * (num11 * num13);
				val3 = Vector3.MoveTowards(val3, val5, Accel.Value * fixedDeltaTime);
				val3 = Vector3.ClampMagnitude(val3, Mathf.Max(SprintSpeed.Value, 0.5f));
				component.linearVelocity = new Vector3(val3.x, linearVelocity.y, val3.z);
				float num14 = TurnSpeed.Value * (flag8 ? (SprintSpeed.Value / Mathf.Max(0.1f, WalkSpeed.Value)) : 1f);
				float num15 = Mathf.MoveTowards(component.angularVelocity.y, num10 * num14, 4f);
				component.angularVelocity = new Vector3(0f, num15, 0f);
				component.WakeUp();
				if (flag6)
				{
					flag7 = true;
					float num16 = (flag8 ? DrainSprint.Value : DrainWalk.Value);
					S.Stamina = Mathf.Max(0f, S.Stamina - num16 * fixedDeltaTime);
				}
			}
			if (!flag4 && !flag7)
			{
				bool flag9 = ((Vector3)(ref val3)).magnitude < 0.25f;
				if (flag2 && flag3)
				{
					S.Stamina = Mathf.Min(100f, S.Stamina + RegenPulled.Value * fixedDeltaTime);
				}
				else if (flag9 && !flag2)
				{
					S.Stamina = Mathf.Min(100f, S.Stamina + RegenIdle.Value * fixedDeltaTime);
				}
			}
			if (S.InFire)
			{
				S.InFire = false;
				if (S.Weapon && S.InAim && !flag2 && !flag4)
				{
					TryFire(cart);
				}
			}
		}

		private static void TryFire(PhysGrabCart cart)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Invalid comparison between Unknown and I4
			ItemCartCannonMain val = FindCannon(cart);
			if (Object.op_Implicit((Object)(object)val) && (int)R.Get<state>(val, "stateCurrent") != 1)
			{
				val = null;
			}
			if (!Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			ItemBattery component = ((Component)val).GetComponent<ItemBattery>();
			if (Object.op_Implicit((Object)(object)component) && R.Get<int>(component, "batteryLifeInt") <= 0)
			{
				I.Toast(Loc.T("cannon_empty"));
				return;
			}
			if (S.Stamina >= 50f)
			{
				S.Stamina -= 50f;
			}
			else
			{
				S.Stamina = 0f;
				if (S.StunDelay <= 0f && S.StunTimer <= 0f)
				{
					S.StunDelay = 3f;
				}
			}
			ItemToggle val2 = R.Get<ItemToggle>(val, "itemToggle");
			if (Object.op_Implicit((Object)(object)val2))
			{
				val2.ToggleItem(!val2.toggleState, -1);
			}
		}
	}
	[HarmonyPatch(typeof(PhysGrabCart), "FixedUpdate")]
	internal static class PatchCartFixedUpdate
	{
		private static void Postfix(PhysGrabCart __instance)
		{
			if (SemiFunc.IsMasterClientOrSingleplayer() && !((Object)(object)LevelGenerator.Instance == (Object)null) && LevelGenerator.Instance.Generated)
			{
				Plugin.CartFixedTick(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(PhysGrabCart), "AutoTurnOff")]
	internal static class PatchCartAutoTurnOff
	{
		private static bool Prefix(PhysGrabCart __instance)
		{
			if (!S.Possessed || (Object)(object)__instance != (Object)(object)S.Cart)
			{
				return true;
			}
			List<PhysGrabber> list = R.Get<List<PhysGrabber>>(((Component)__instance).GetComponent<PhysGrabObject>(), "playerGrabbing");
			if (list != null && list.Count > 0)
			{
				return true;
			}
			if (Time.time - S.DrivingStamp > 0.25f)
			{
				return true;
			}
			R.Set(__instance, "cartActive", true);
			return false;
		}
	}
	[HarmonyPatch(typeof(SpectateCamera), "StateNormal")]
	internal static class PatchSpectateNormal
	{
		private static void Postfix(SpectateCamera __instance)
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: 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_00c1: 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_0110: Unknown result type (might be due to invalid IL or missing references)
			if (!S.Possessed || S.Sim || !S.LocalDrive || !Plugin.IsLocalDriver())
			{
				return;
			}
			PhysGrabCart val = (Object.op_Implicit((Object)(object)S.Cart) ? S.Cart : Plugin.FindCart());
			if (!Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			Transform normalTransformPivot = __instance.normalTransformPivot;
			Transform normalTransformDistance = __instance.normalTransformDistance;
			if (Object.op_Implicit((Object)(object)normalTransformPivot) && Object.op_Implicit((Object)(object)normalTransformDistance))
			{
				ItemCartCannonMain val2 = (Input.GetKey(Plugin.AimKey.Value) ? Plugin.FindCannon(val) : null);
				if (Object.op_Implicit((Object)(object)val2))
				{
					normalTransformPivot.position = ((Component)val2).transform.position + Vector3.up * Plugin.AimUp.Value;
					normalTransformDistance.localPosition = new Vector3(0f, 0f, 0f - Plugin.AimBack.Value);
					S.Aiming = true;
					S.LocalAimYaw = normalTransformPivot.eulerAngles.y;
				}
				else
				{
					normalTransformPivot.position = Plugin.HeadAnchor(val) + Vector3.up * 0.2f;
					S.Aiming = false;
				}
				((Component)__instance).transform.position = normalTransformDistance.position;
			}
		}
	}
}