Decompiled source of TheContractor v1.0.3

TheContractor.dll

Decompiled 2 months ago
using System;
using System.Collections;
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 BoneLib;
using BoneLib.BoneMenu;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSLZ.Marrow;
using Il2CppSLZ.Marrow.Interaction;
using Il2CppSLZ.Marrow.Pool;
using Il2CppSLZ.Marrow.Warehouse;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using TheContractor;
using UnityEngine;
using UnityEngine.AI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Core), "The Contractor", "1.0.3", "Deakins", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: MelonAdditionalDependencies(new string[] { "BoneLib" })]
[assembly: MelonOptionalDependencies(new string[] { "LabFusion" })]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("TheContractor")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("TheContractor")]
[assembly: AssemblyTitle("TheContractor")]
[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 TheContractor
{
	[RegisterTypeInIl2Cpp]
	public class ContractorBehaviour : MonoBehaviour
	{
		private readonly List<RigManager> _rigBuffer = new List<RigManager>(8);

		private readonly Dictionary<int, float> _killCooldownUntil = new Dictionary<int, float>(8);

		private NavMeshAgent _agent;

		private bool _useAgent;

		private float _nextPathTime;

		private Vector3 _lastDestination;

		private Animation _legacyAnim;

		private string _runStateName = "ContractorRun";

		private bool _ready;

		private float _nextTargetTime;

		private RigManager _currentRig;

		private Transform _currentTarget;

		private bool _animPlaying;

		private Vector3 _lastPosition;

		public ContractorBehaviour(IntPtr ptr)
			: base(ptr)
		{
		}

		public void Initialize()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			if (!_ready)
			{
				((Object)((Component)this).gameObject).name = "TheContractor_NPC";
				EnsureMarker();
				ConfigurePhysics();
				ConfigureAgent();
				ConfigureAnimation();
				_lastPosition = ((Component)this).transform.position;
				_ready = true;
				MelonLogger.Msg("[TheContractor] AI ready (NavMesh=" + _useAgent + ")");
			}
		}

		private void OnDestroy()
		{
			_ready = false;
			_currentRig = null;
			_currentTarget = null;
			_agent = null;
		}

		public void DespawnNow()
		{
			try
			{
				Poolee val = ((Component)this).GetComponent<Poolee>() ?? ((Component)this).GetComponentInChildren<Poolee>(true);
				if ((Object)(object)val != (Object)null)
				{
					val.Despawn();
					return;
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("[TheContractor] Poolee.Despawn: " + ex.Message);
			}
			Object.Destroy((Object)(object)((Component)this).gameObject);
		}

		public void Tick()
		{
			//IL_0039: 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)
			if (!_ready)
			{
				return;
			}
			if (!FusionBridge.ShouldRunAi())
			{
				MirrorClientVisuals();
				return;
			}
			UpdateTarget();
			if ((Object)(object)_currentTarget == (Object)null)
			{
				HoldStill();
				return;
			}
			FaceTargetY(_currentTarget.position);
			MoveToward(_currentTarget.position);
			TryKillNearby();
		}

		private void EnsureMarker()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)((Component)this).transform.Find("TheContractor_Marker") == (Object)null)
			{
				new GameObject("TheContractor_Marker").transform.SetParent(((Component)this).transform, false);
			}
			if ((Object)(object)((Component)this).GetComponent<ContractorMarker>() == (Object)null)
			{
				((Component)this).gameObject.AddComponent<ContractorMarker>();
			}
		}

		private void ConfigurePhysics()
		{
			foreach (Rigidbody componentsInChild in ((Component)this).GetComponentsInChildren<Rigidbody>(true))
			{
				if (!((Object)(object)componentsInChild == (Object)null))
				{
					componentsInChild.isKinematic = true;
					componentsInChild.useGravity = false;
					componentsInChild.constraints = (RigidbodyConstraints)80;
				}
			}
			foreach (Joint componentsInChild2 in ((Component)this).GetComponentsInChildren<Joint>(true))
			{
				if ((Object)(object)componentsInChild2 != (Object)null)
				{
					Object.Destroy((Object)(object)componentsInChild2);
				}
			}
		}

		private void ConfigureAgent()
		{
			//IL_00e3: 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)
			_useAgent = false;
			_agent = null;
			try
			{
				_agent = ((Component)this).GetComponent<NavMeshAgent>();
				if ((Object)(object)_agent == (Object)null)
				{
					_agent = ((Component)this).gameObject.AddComponent<NavMeshAgent>();
				}
				_agent.speed = Core.MovementSpeed.Value;
				_agent.acceleration = Core.Acceleration.Value;
				_agent.angularSpeed = Core.AngularSpeed.Value;
				_agent.stoppingDistance = Core.StoppingDistance.Value;
				_agent.updateRotation = false;
				_agent.updateUpAxis = true;
				_agent.autoBraking = true;
				_agent.radius = 0.35f;
				_agent.height = 2f;
				((Behaviour)_agent).enabled = true;
				NavMeshHit val = default(NavMeshHit);
				if (NavMesh.SamplePosition(((Component)this).transform.position, ref val, 8f, -1))
				{
					_agent.Warp(((NavMeshHit)(ref val)).position);
					_useAgent = _agent.isOnNavMesh;
				}
				if (!_useAgent)
				{
					MelonLogger.Warning("[TheContractor] No NavMesh under spawn — using direct chase fallback.");
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("[TheContractor] NavMeshAgent setup failed: " + ex.Message);
				_useAgent = false;
				_agent = null;
			}
		}

		private void ConfigureAnimation()
		{
			_legacyAnim = ((Component)this).GetComponentInChildren<Animation>(true);
			if ((Object)(object)_legacyAnim == (Object)null)
			{
				MelonLogger.Warning("[TheContractor] No Legacy Animation component on spawnable.");
				return;
			}
			try
			{
				_legacyAnim.playAutomatically = false;
				_legacyAnim.wrapMode = (WrapMode)2;
				AnimationClip clip = _legacyAnim.clip;
				if ((Object)(object)clip != (Object)null)
				{
					clip.wrapMode = (WrapMode)2;
					_runStateName = (string.IsNullOrEmpty(((Object)clip).name) ? "ContractorRun" : ((Object)clip).name);
				}
				if ((Object)(object)_legacyAnim.GetClip("ContractorRun") != (Object)null)
				{
					_runStateName = "ContractorRun";
				}
				MelonLogger.Msg("[TheContractor] Animation ready: state='" + _runStateName + "'");
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("[TheContractor] ConfigureAnimation: " + ex.Message);
				_legacyAnim = null;
			}
		}

		private void UpdateTarget()
		{
			//IL_0089: 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_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			if (Time.time < _nextTargetTime && FusionBridge.IsLiving(_currentRig) && (Object)(object)_currentTarget != (Object)null)
			{
				return;
			}
			_nextTargetTime = Time.time + Mathf.Max(0.05f, Core.TargetUpdateInterval.Value);
			FusionBridge.CollectLivingRigs(_rigBuffer);
			RigManager val = null;
			Transform val2 = null;
			float num = float.MaxValue;
			for (int i = 0; i < _rigBuffer.Count; i++)
			{
				RigManager val3 = _rigBuffer[i];
				Transform aimPoint = FusionBridge.GetAimPoint(val3);
				if (!((Object)(object)aimPoint == (Object)null))
				{
					float num2 = Vector3.Distance(((Component)this).transform.position, aimPoint.position);
					if (num2 < num)
					{
						num = num2;
						val = val3;
						val2 = aimPoint;
					}
				}
			}
			if ((Object)(object)val2 == (Object)null)
			{
				_currentRig = null;
				_currentTarget = null;
				return;
			}
			if (FusionBridge.IsLiving(_currentRig) && (Object)(object)_currentTarget != (Object)null)
			{
				float num3 = Vector3.Distance(((Component)this).transform.position, _currentTarget.position);
				if ((Object)(object)val == (Object)(object)_currentRig || num + Core.TargetSwitchMargin.Value >= num3)
				{
					_currentTarget = FusionBridge.GetAimPoint(_currentRig) ?? _currentTarget;
					return;
				}
			}
			_currentRig = val;
			_currentTarget = val2;
		}

		private void MoveToward(Vector3 worldTarget)
		{
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: 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_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: 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_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: 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_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: 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_00b1: 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_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: 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_0120: 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_014d: 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_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			float value = Core.MovementSpeed.Value;
			if (_useAgent && (Object)(object)_agent != (Object)null && ((Behaviour)_agent).enabled)
			{
				try
				{
					_agent.speed = value;
					_agent.acceleration = Core.Acceleration.Value;
					_agent.angularSpeed = Core.AngularSpeed.Value;
					_agent.stoppingDistance = Core.StoppingDistance.Value;
					if (!_agent.isOnNavMesh)
					{
						NavMeshHit val = default(NavMeshHit);
						if (NavMesh.SamplePosition(((Component)this).transform.position, ref val, 8f, -1))
						{
							_agent.Warp(((NavMeshHit)(ref val)).position);
							_useAgent = _agent.isOnNavMesh;
						}
						else
						{
							_useAgent = false;
						}
					}
					if (_useAgent && _agent.isOnNavMesh)
					{
						if (!(Time.time >= _nextPathTime))
						{
							Vector3 val2 = worldTarget - _lastDestination;
							if (!(((Vector3)(ref val2)).sqrMagnitude > 0.35f))
							{
								goto IL_016e;
							}
						}
						Vector3 val3 = worldTarget;
						NavMeshHit val4 = default(NavMeshHit);
						if (NavMesh.SamplePosition(worldTarget, ref val4, 4f, -1))
						{
							val3 = ((NavMeshHit)(ref val4)).position;
						}
						_agent.isStopped = false;
						_agent.SetDestination(val3);
						_lastDestination = val3;
						_nextPathTime = Time.time + 0.2f;
						goto IL_016e;
					}
					goto end_IL_0037;
					IL_016e:
					SetRunAnim(play: true);
					return;
					end_IL_0037:;
				}
				catch (Exception ex)
				{
					MelonLogger.Warning("[TheContractor] Agent move failed, fallback: " + ex.Message);
					_useAgent = false;
				}
			}
			Vector3 position = ((Component)this).transform.position;
			Vector3 val5 = worldTarget - position;
			val5.y = 0f;
			float magnitude = ((Vector3)(ref val5)).magnitude;
			if (magnitude > Core.StoppingDistance.Value)
			{
				Vector3 val6 = ((Vector3)(ref val5)).normalized * value * Time.deltaTime;
				float num = magnitude - Core.StoppingDistance.Value;
				if (((Vector3)(ref val6)).magnitude > num)
				{
					val6 = ((Vector3)(ref val5)).normalized * Mathf.Max(0f, num);
				}
				Vector3 val7 = position + val6;
				RaycastHit val8 = default(RaycastHit);
				if (Physics.Raycast(val7 + Vector3.up * 2.5f, Vector3.down, ref val8, 8f, -1, (QueryTriggerInteraction)1))
				{
					val7.y = ((RaycastHit)(ref val8)).point.y;
				}
				((Component)this).transform.position = val7;
			}
			SetRunAnim(play: true);
		}

		private void FaceTargetY(Vector3 worldTarget)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: 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)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: 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_0084: 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)
			Vector3 val = worldTarget - ((Component)this).transform.position;
			val.y = 0f;
			if (!(((Vector3)(ref val)).sqrMagnitude < 0.0001f))
			{
				Quaternion val2 = Quaternion.LookRotation(((Vector3)(ref val)).normalized, Vector3.up);
				float num = Core.AngularSpeed.Value * Time.deltaTime;
				((Component)this).transform.rotation = Quaternion.RotateTowards(((Component)this).transform.rotation, val2, num);
				Vector3 eulerAngles = ((Component)this).transform.eulerAngles;
				((Component)this).transform.rotation = Quaternion.Euler(0f, eulerAngles.y, 0f);
			}
		}

		private void TryKillNearby()
		{
			//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_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			float value = Core.KillDistance.Value;
			float value2 = Core.KillCooldown.Value;
			FusionBridge.CollectLivingRigs(_rigBuffer);
			for (int i = 0; i < _rigBuffer.Count; i++)
			{
				RigManager val = _rigBuffer[i];
				Transform aimPoint = FusionBridge.GetAimPoint(val);
				if ((Object)(object)aimPoint == (Object)null)
				{
					continue;
				}
				Vector3 position = ((Component)val).transform.position;
				float num = Vector3.Distance(((Component)this).transform.position, position);
				float num2 = Vector3.Distance(((Component)this).transform.position, aimPoint.position);
				if (!(num > value) || !(num2 > value + 0.35f))
				{
					int instanceID = ((Object)val).GetInstanceID();
					if (!_killCooldownUntil.TryGetValue(instanceID, out var value3) || !(Time.time < value3))
					{
						_killCooldownUntil[instanceID] = Time.time + value2;
						Core.KillPlayer(val);
					}
				}
			}
		}

		private void HoldStill()
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_agent != (Object)null && ((Behaviour)_agent).enabled && _agent.isOnNavMesh)
			{
				try
				{
					_agent.isStopped = true;
					_agent.ResetPath();
					_agent.velocity = Vector3.zero;
				}
				catch
				{
				}
			}
			SetRunAnim(play: false);
		}

		private void MirrorClientVisuals()
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: 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_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: 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_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_agent != (Object)null && ((Behaviour)_agent).enabled && _agent.isOnNavMesh)
			{
				try
				{
					_agent.isStopped = true;
					_agent.ResetPath();
				}
				catch
				{
				}
			}
			Vector3 eulerAngles = ((Component)this).transform.eulerAngles;
			((Component)this).transform.rotation = Quaternion.Euler(0f, eulerAngles.y, 0f);
			bool runAnim = false;
			if (Time.deltaTime > 0.0001f)
			{
				Vector3 val = (((Component)this).transform.position - _lastPosition) / Time.deltaTime;
				runAnim = ((Vector3)(ref val)).sqrMagnitude > 0.25f;
			}
			_lastPosition = ((Component)this).transform.position;
			SetRunAnim(runAnim);
		}

		private void SetRunAnim(bool play)
		{
			if ((Object)(object)_legacyAnim == (Object)null)
			{
				return;
			}
			try
			{
				if (play)
				{
					if (_animPlaying && _legacyAnim.IsPlaying(_runStateName))
					{
						return;
					}
					if (!string.IsNullOrEmpty(_runStateName) && (Object)(object)_legacyAnim.GetClip(_runStateName) != (Object)null)
					{
						_legacyAnim.Play(_runStateName);
					}
					else
					{
						if (!((Object)(object)_legacyAnim.clip != (Object)null))
						{
							return;
						}
						_legacyAnim.Play();
					}
					_animPlaying = true;
				}
				else
				{
					if (_animPlaying)
					{
						_legacyAnim.Stop();
					}
					_animPlaying = false;
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("[TheContractor] SetRunAnim: " + ex.Message);
				_legacyAnim = null;
			}
		}
	}
	public class Core : MelonMod
	{
		public const string SpawnableBarcode = "Deakins.TheContractor.Spawnable.TheContractor";

		public const string MarkerName = "TheContractor_Marker";

		public const string PalletId = "Deakins.TheContractor";

		internal static Core Instance;

		internal static MelonPreferences_Category Prefs;

		internal static MelonPreferences_Entry<float> SpawnDelay;

		internal static MelonPreferences_Entry<float> MovementSpeed;

		internal static MelonPreferences_Entry<float> Acceleration;

		internal static MelonPreferences_Entry<float> AngularSpeed;

		internal static MelonPreferences_Entry<float> StoppingDistance;

		internal static MelonPreferences_Entry<float> TargetUpdateInterval;

		internal static MelonPreferences_Entry<float> TargetSwitchMargin;

		internal static MelonPreferences_Entry<float> KillDistance;

		internal static MelonPreferences_Entry<float> KillCooldown;

		private readonly List<ContractorBehaviour> _active = new List<ContractorBehaviour>();

		private float _scanTimer;

		private float _levelGrace;

		private bool _hooksReady;

		public override void OnInitializeMelon()
		{
			Instance = this;
			Prefs = MelonPreferences.CreateCategory("TheContractor");
			SpawnDelay = Prefs.CreateEntry<float>("SpawnDelay", 0f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			MovementSpeed = Prefs.CreateEntry<float>("MovementSpeed", 9f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			Acceleration = Prefs.CreateEntry<float>("Acceleration", 40f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			AngularSpeed = Prefs.CreateEntry<float>("AngularSpeed", 720f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			StoppingDistance = Prefs.CreateEntry<float>("StoppingDistance", 0.6f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			TargetUpdateInterval = Prefs.CreateEntry<float>("TargetUpdateInterval", 0.25f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			TargetSwitchMargin = Prefs.CreateEntry<float>("TargetSwitchMargin", 1.5f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			KillDistance = Prefs.CreateEntry<float>("KillDistance", 1f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			KillCooldown = Prefs.CreateEntry<float>("KillCooldown", 1.25f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			SpawnDelay.Value = 0f;
			((MelonBase)this).LoggerInstance.Msg("The Contractor 1.0.3 ready. Spawn: Deakins.TheContractor.Spawnable.TheContractor (NavMesh + BoneLib)");
		}

		public override void OnLateInitializeMelon()
		{
			try
			{
				Hooking.OnLevelLoaded += delegate
				{
					OnLevelReady();
				};
				Hooking.OnLevelUnloaded += OnLevelUnloaded;
				_hooksReady = true;
				TryAddBoneMenu();
			}
			catch (Exception ex)
			{
				((MelonBase)this).LoggerInstance.Error("Hook setup failed: " + ex);
			}
		}

		private void TryAddBoneMenu()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Page.Root.CreatePage("The Contractor", Color.black, 0, true).CreateFunction("Despawn All", Color.red, (Action)delegate
				{
					for (int num = _active.Count - 1; num >= 0; num--)
					{
						if ((Object)(object)_active[num] != (Object)null)
						{
							_active[num].DespawnNow();
						}
					}
					_active.Clear();
					((MelonBase)this).LoggerInstance.Msg("Despawned all Contractor instances.");
				});
			}
			catch (Exception ex)
			{
				((MelonBase)this).LoggerInstance.Warning("BoneMenu skipped: " + ex.Message);
			}
		}

		private void OnLevelReady()
		{
			_active.Clear();
			_scanTimer = 0f;
			_levelGrace = 2.5f;
			((MelonBase)this).LoggerInstance.Msg("Level ready — Contractor binder waiting " + _levelGrace + "s");
		}

		private void OnLevelUnloaded()
		{
			_active.Clear();
			_levelGrace = 0f;
		}

		public override void OnUpdate()
		{
			try
			{
				if (!_hooksReady || HelperMethods.IsLoading() || (Object)(object)Player.RigManager == (Object)null)
				{
					return;
				}
				if (_levelGrace > 0f)
				{
					_levelGrace -= Time.deltaTime;
					return;
				}
				_scanTimer -= Time.deltaTime;
				if (_scanTimer <= 0f)
				{
					_scanTimer = 1.25f;
					ScanForSpawnables();
				}
				for (int num = _active.Count - 1; num >= 0; num--)
				{
					ContractorBehaviour contractorBehaviour = _active[num];
					if ((Object)(object)contractorBehaviour == (Object)null || (Object)(object)((Component)contractorBehaviour).gameObject == (Object)null)
					{
						_active.RemoveAt(num);
					}
					else
					{
						try
						{
							contractorBehaviour.Tick();
						}
						catch (Exception ex)
						{
							((MelonBase)this).LoggerInstance.Warning("Tick failed, unbinding: " + ex.Message);
							_active.RemoveAt(num);
						}
					}
				}
			}
			catch (Exception ex2)
			{
				((MelonBase)this).LoggerInstance.Warning("OnUpdate: " + ex2.Message);
			}
		}

		private void ScanForSpawnables()
		{
			MarrowEntity[] array;
			try
			{
				array = Il2CppArrayBase<MarrowEntity>.op_Implicit(Object.FindObjectsOfType<MarrowEntity>());
			}
			catch
			{
				return;
			}
			if (array == null)
			{
				return;
			}
			foreach (MarrowEntity val in array)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				Transform transform = ((Component)val).transform;
				string cleanObjectName = HelperMethods.GetCleanObjectName(((Object)transform).name);
				if (!IsOurSpawnable(val, transform, cleanObjectName) || (Object)(object)((Component)transform).GetComponent<ContractorBehaviour>() != (Object)null)
				{
					continue;
				}
				try
				{
					if ((Object)(object)((Component)transform).GetComponent<ContractorMarker>() == (Object)null)
					{
						((Component)transform).gameObject.AddComponent<ContractorMarker>();
					}
					ContractorBehaviour contractorBehaviour = ((Component)transform).gameObject.AddComponent<ContractorBehaviour>();
					contractorBehaviour.Initialize();
					_active.Add(contractorBehaviour);
					((MelonBase)this).LoggerInstance.Msg("Bound The Contractor AI to " + ((Object)transform).name);
				}
				catch (Exception ex)
				{
					((MelonBase)this).LoggerInstance.Error("Bind failed: " + ex);
				}
			}
		}

		private static bool IsOurSpawnable(MarrowEntity ent, Transform root, string clean)
		{
			if (clean.IndexOf("TheContractor", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
			if ((Object)(object)root.Find("TheContractor_Marker") != (Object)null)
			{
				return true;
			}
			if ((Object)(object)((Component)root).GetComponentInChildren<ContractorMarker>(true) != (Object)null)
			{
				return true;
			}
			string text = TryGetBarcode(ent);
			if (!string.IsNullOrEmpty(text) && text.IndexOf("Deakins.TheContractor", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
			return false;
		}

		private static string TryGetBarcode(MarrowEntity ent)
		{
			try
			{
				Poolee val = ((Component)ent).GetComponent<Poolee>() ?? ((Component)ent).GetComponentInChildren<Poolee>(true);
				if ((Object)(object)val == (Object)null)
				{
					return null;
				}
				SpawnableCrate spawnableCrate = val.SpawnableCrate;
				Barcode obj = ((spawnableCrate != null) ? ((Scannable)spawnableCrate).Barcode : null);
				return (obj != null) ? obj.ID : null;
			}
			catch
			{
				return null;
			}
		}

		internal static void KillPlayer(RigManager rm)
		{
			if (!((Object)(object)rm == (Object)null))
			{
				MelonCoroutines.Start(KillCoroutine(rm));
			}
		}

		private static IEnumerator KillCoroutine(RigManager rm)
		{
			try
			{
				Player_Health val = ResolvePlayerHealth(rm);
				if ((Object)(object)val != (Object)null)
				{
					try
					{
						val.ApplyKillDamage();
					}
					catch
					{
						((Health)val).TAKEDAMAGE(100000f);
					}
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("Kill failed: " + ex.Message);
			}
			yield return null;
		}

		private static Player_Health ResolvePlayerHealth(RigManager rm)
		{
			if ((Object)(object)rm == (Object)null)
			{
				return null;
			}
			Health health = rm.health;
			Player_Health val = ((health != null) ? ((Il2CppObjectBase)health).TryCast<Player_Health>() : null);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			return ((Component)rm).GetComponentInChildren<Player_Health>();
		}
	}
	[RegisterTypeInIl2Cpp]
	public class ContractorMarker : MonoBehaviour
	{
		public ContractorMarker(IntPtr ptr)
			: base(ptr)
		{
		}
	}
	internal static class FusionBridge
	{
		private static bool _resolved;

		private static bool _hasFusion;

		private static PropertyInfo _hasServer;

		private static PropertyInfo _isServer;

		private static void Resolve()
		{
			if (_resolved)
			{
				return;
			}
			_resolved = true;
			try
			{
				if (!HelperMethods.CheckIfAssemblyLoaded("LabFusion"))
				{
					_hasFusion = false;
					return;
				}
				_hasFusion = true;
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				foreach (Assembly assembly in assemblies)
				{
					if (!assembly.GetName().Name.Equals("LabFusion", StringComparison.OrdinalIgnoreCase))
					{
						continue;
					}
					Type[] types = assembly.GetTypes();
					foreach (Type obj in types)
					{
						PropertyInfo property = obj.GetProperty("HasServer", BindingFlags.Static | BindingFlags.Public);
						PropertyInfo property2 = obj.GetProperty("IsServer", BindingFlags.Static | BindingFlags.Public);
						if (property != null && property2 != null)
						{
							_hasServer = property;
							_isServer = property2;
							return;
						}
					}
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("[TheContractor] Fusion resolve: " + ex.Message);
				_hasFusion = false;
			}
		}

		public static bool ShouldRunAi()
		{
			Resolve();
			if (!_hasFusion || _hasServer == null)
			{
				return true;
			}
			try
			{
				if (!(bool)_hasServer.GetValue(null))
				{
					return true;
				}
				if (_isServer == null)
				{
					return true;
				}
				return (bool)_isServer.GetValue(null);
			}
			catch
			{
				return true;
			}
		}

		public static void CollectLivingRigs(List<RigManager> results)
		{
			results.Clear();
			try
			{
				Il2CppArrayBase<RigManager> val = Object.FindObjectsOfType<RigManager>();
				if (val == null)
				{
					return;
				}
				for (int i = 0; i < val.Length; i++)
				{
					RigManager val2 = val[i];
					if (!((Object)(object)val2 == (Object)null) && ((Behaviour)val2).isActiveAndEnabled && IsLiving(val2))
					{
						results.Add(val2);
					}
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("[TheContractor] CollectLivingRigs: " + ex.Message);
			}
			if ((Object)(object)Player.RigManager != (Object)null && IsLiving(Player.RigManager) && !results.Contains(Player.RigManager))
			{
				results.Add(Player.RigManager);
			}
		}

		public static bool IsLiving(RigManager rm)
		{
			if ((Object)(object)rm == (Object)null)
			{
				return false;
			}
			try
			{
				Health health = rm.health;
				if ((Object)(object)health == (Object)null)
				{
					return true;
				}
				Player_Health val = ((Il2CppObjectBase)health).TryCast<Player_Health>();
				if ((Object)(object)val != (Object)null)
				{
					if (((Health)val).deathIsImminent)
					{
						return false;
					}
					if (((Health)val).max_Health > 0f && ((Health)val).curr_Health <= 0f && !((Health)val).alive)
					{
						return false;
					}
				}
				return true;
			}
			catch
			{
				return true;
			}
		}

		public static Transform GetAimPoint(RigManager rm)
		{
			if ((Object)(object)rm == (Object)null)
			{
				return null;
			}
			try
			{
				if ((Object)(object)rm.physicsRig != (Object)null && (Object)(object)((Rig)rm.physicsRig).m_head != (Object)null)
				{
					return ((Rig)rm.physicsRig).m_head;
				}
			}
			catch
			{
			}
			try
			{
				if ((Object)(object)Player.RigManager == (Object)(object)rm && (Object)(object)Player.Head != (Object)null)
				{
					return Player.Head;
				}
			}
			catch
			{
			}
			return ((Component)rm).transform;
		}
	}
}