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;
}
}
}