Decompiled source of OrganizedCrime v2.0.0

Mods/OrganizedCrime.dll

Decompiled 2 weeks ago
using System;
using System.Buffers.Binary;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;
using System.Threading;
using HarmonyLib;
using Il2Cpp;
using Il2CppFishNet;
using Il2CppFishNet.Connection;
using Il2CppFishNet.Managing;
using Il2CppFishNet.Managing.Client;
using Il2CppFishNet.Managing.Object;
using Il2CppFishNet.Managing.Server;
using Il2CppFishNet.Object;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppScheduleOne;
using Il2CppScheduleOne.Avatar;
using Il2CppScheduleOne.AvatarFramework;
using Il2CppScheduleOne.AvatarFramework.Equipping;
using Il2CppScheduleOne.Building.Doors;
using Il2CppScheduleOne.Calling;
using Il2CppScheduleOne.Cartel;
using Il2CppScheduleOne.Combat;
using Il2CppScheduleOne.Core.Avatar;
using Il2CppScheduleOne.Core.Items.Framework;
using Il2CppScheduleOne.Delivery;
using Il2CppScheduleOne.DevUtilities;
using Il2CppScheduleOne.Dialogue;
using Il2CppScheduleOne.Doors;
using Il2CppScheduleOne.Economy;
using Il2CppScheduleOne.Employees;
using Il2CppScheduleOne.EntityFramework;
using Il2CppScheduleOne.GameTime;
using Il2CppScheduleOne.Interaction;
using Il2CppScheduleOne.ItemFramework;
using Il2CppScheduleOne.Law;
using Il2CppScheduleOne.Management;
using Il2CppScheduleOne.Map;
using Il2CppScheduleOne.Messaging;
using Il2CppScheduleOne.Misc;
using Il2CppScheduleOne.NPCs;
using Il2CppScheduleOne.NPCs.Actions;
using Il2CppScheduleOne.NPCs.Behaviour;
using Il2CppScheduleOne.NPCs.Framework;
using Il2CppScheduleOne.NPCs.Responses;
using Il2CppScheduleOne.Networking;
using Il2CppScheduleOne.ObjectScripts;
using Il2CppScheduleOne.Persistence;
using Il2CppScheduleOne.Persistence.Datas;
using Il2CppScheduleOne.Persistence.Loaders;
using Il2CppScheduleOne.PlayerScripts;
using Il2CppScheduleOne.PlayerScripts.Health;
using Il2CppScheduleOne.Police;
using Il2CppScheduleOne.Product;
using Il2CppScheduleOne.Product.Packaging;
using Il2CppScheduleOne.Property;
using Il2CppScheduleOne.ScriptableObjects;
using Il2CppScheduleOne.Storage;
using Il2CppScheduleOne.Tiles;
using Il2CppScheduleOne.UI;
using Il2CppScheduleOne.UI.Management;
using Il2CppScheduleOne.UI.Phone;
using Il2CppScheduleOne.UI.Phone.Delivery;
using Il2CppScheduleOne.UI.SleepMessage;
using Il2CppScheduleOne.Vehicles;
using Il2CppScheduleOne.VoiceOver;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Il2CppSystem.Reflection;
using Il2CppTMPro;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using OrganizedCrime;
using OrganizedCrime.Core.Diagnostics;
using OrganizedCrime.Core.Hosting;
using OrganizedCrime.Core.Lifecycle;
using OrganizedCrime.Core.Persistence;
using OrganizedCrime.Core.Scheduling;
using OrganizedCrime.Core.Time;
using OrganizedCrime.Model;
using OrganizedCrime.Persistence;
using OrganizedCrime.Runtime;
using OrganizedCrime.Runtime.Chapter3;
using OrganizedCrime.Runtime.Composition;
using OrganizedCrime.Runtime.Platform;
using OrganizedCrime.Runtime.Police;
using OrganizedCrime.Runtime.Qa;
using OrganizedCrime.Runtime.Release1.Missions;
using OrganizedCrime.Runtime.Release1.World;
using S1API.Building;
using S1API.Console;
using S1API.DeadDrops;
using S1API.Entities;
using S1API.Entities.Appearances.AccessoryFields;
using S1API.Entities.Appearances.FaceLayerFields;
using S1API.GameTime;
using S1API.Items;
using S1API.Law;
using S1API.Lifecycle;
using S1API.Messaging;
using S1API.Money;
using S1API.PhoneCalls;
using S1API.Products;
using S1API.Property;
using S1API.Quests;
using S1API.Quests.Constants;
using S1API.Storages;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(OrganizedCrimeMod), "Organized Crime", "2.0.0", "MadJag Studios", null)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 OrganizedCrime
{
	public sealed class OrganizedCrimeMod : MelonMod
	{
		private bool _initialized;

		private OcCompositionRoot? _root;

		private OcLoggingPolicy? _logging;

		private readonly OcCompositionLifetime _lifetime = new OcCompositionLifetime();

		public override void OnInitializeMelon()
		{
			if (_initialized)
			{
				((MelonBase)this).LoggerInstance.Warning("duplicate initialization was ignored.");
				return;
			}
			_initialized = true;
			OcLoggingPolicy logging = new OcLoggingPolicy((Action<string>)((MelonBase)this).LoggerInstance.Msg, (Action<string>)((MelonBase)this).LoggerInstance.Warning);
			_logging = logging;
			OrganizedCrimeLog.DiagnosticSink = logging.Diagnostic;
			OrganizedCrimeLog.FlushWarningSummaries = logging.FlushWarningSummaries;
			OrganizedCrimeLog.CommandResponse = logging.CommandResponse;
			(_root = new OcCompositionRoot(new MelonEngineAdapters(((MelonBase)this).HarmonyInstance, logging.Warning, delegate(bool enabled)
			{
				logging.DiagnosticsEnabled = enabled;
			}), logging.Information, logging.Warning, _lifetime)).Build();
			logging.Startup(((MelonBase)this).Info.Version);
		}

		public override void OnDeinitializeMelon()
		{
			TeardownAndFlush(delegate
			{
				_root?.Teardown();
			}, _logging, delegate(string message)
			{
				((MelonBase)this).LoggerInstance.Error(message);
			}, delegate
			{
				_root = null;
				_logging = null;
				_initialized = false;
			});
		}

		public override void OnUpdate()
		{
			_root?.Lifecycle.Update();
		}

		public override void OnGUI()
		{
			_root?.Lifecycle.OnGUI();
		}

		private static void TeardownAndFlush(Action teardown, OcLoggingPolicy? logging, Action<string> error, Action reset)
		{
			try
			{
				teardown();
			}
			catch (Exception value)
			{
				error($"teardown failed: {value}");
				throw;
			}
			finally
			{
				try
				{
					logging?.FlushWarningSummaries();
				}
				catch (Exception value2)
				{
					error($"teardown warning-summary flush failed: {value2}");
					throw;
				}
				finally
				{
					reset();
				}
			}
		}
	}
}
namespace OrganizedCrime.Runtime
{
	public static class Chapter3ArthurAppearance
	{
		public const string OldPersonWrinklesPath = "avatar/layers/face/oldpersonwrinkles";

		public const string ButtonUpPath = "avatar/layers/top/buttonup";

		public const string JeansPath = "avatar/layers/bottom/jeans";

		public const string ChevronPath = "Avatar/Accessories/FacialHair/Chevron/Chevron";

		public static readonly IReadOnlyList<string> ExpectedPaths = new string[11]
		{
			"Avatar/Hair/bowlcut/BowlCut", "Avatar/Layers/Face/Face_Agitated", "avatar/layers/face/oldpersonwrinkles", "avatar/layers/top/buttonup", "avatar/layers/bottom/jeans", "Avatar/Accessories/FacialHair/Chevron/Chevron", "Avatar/Accessories/Head/FlatCap/FlatCap", "Avatar/Accessories/Chest/Blazer/Blazer", "Avatar/Accessories/Feet/DressShoes/DressShoes", "Avatar/Accessories/Waist/Belt/Belt",
			"Avatar/Accessories/Neck/GoldChain/GoldChain"
		};

		public static void ApplyTo(NPCPrefabBuilder builder)
		{
			if (builder != null)
			{
				builder.WithAppearanceDefaults((Action<AvatarDefaultsBuilder>)delegate(AvatarDefaultsBuilder appearance)
				{
					//IL_0033: Unknown result type (might be due to invalid IL or missing references)
					//IL_0042: Unknown result type (might be due to invalid IL or missing references)
					//IL_0047: Unknown result type (might be due to invalid IL or missing references)
					//IL_0056: Unknown result type (might be due to invalid IL or missing references)
					//IL_005b: Unknown result type (might be due to invalid IL or missing references)
					//IL_007a: Unknown result type (might be due to invalid IL or missing references)
					//IL_007f: Unknown result type (might be due to invalid IL or missing references)
					//IL_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_0129: Unknown result type (might be due to invalid IL or missing references)
					//IL_012e: Unknown result type (might be due to invalid IL or missing references)
					//IL_0147: Unknown result type (might be due to invalid IL or missing references)
					//IL_014c: 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_0176: 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_01b3: 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_01d4: Unknown result type (might be due to invalid IL or missing references)
					//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
					//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
					//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
					//IL_0216: Unknown result type (might be due to invalid IL or missing references)
					//IL_021b: 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_025e: Unknown result type (might be due to invalid IL or missing references)
					//IL_0263: Unknown result type (might be due to invalid IL or missing references)
					appearance.Gender = 0f;
					appearance.Height = 0.9822339f;
					appearance.Weight = 0.700238f;
					appearance.SkinColor = new Color32((byte)180, (byte)144, (byte)113, byte.MaxValue);
					appearance.LeftEyeLidColor = Color32.op_Implicit(new Color32((byte)0, (byte)0, (byte)0, (byte)0));
					appearance.RightEyeLidColor = Color32.op_Implicit(new Color32((byte)0, (byte)0, (byte)0, (byte)0));
					appearance.EyeBallTint = Color32.op_Implicit(new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue));
					appearance.EyeballMaterialIdentifier = "";
					appearance.PupilDilation = 0.65f;
					appearance.EyebrowScale = 1.064336f;
					appearance.EyebrowThickness = 1.246624f;
					appearance.EyebrowRestingHeight = -0.521843f;
					appearance.EyebrowRestingAngle = 1f;
					appearance.LeftEye = (0.5197827f, 0.5f);
					appearance.RightEye = (0.5197827f, 0.5f);
					appearance.HairPath = "Avatar/Hair/bowlcut/BowlCut";
					appearance.HairColor = Color32.op_Implicit(new Color32((byte)63, (byte)49, (byte)36, byte.MaxValue));
					appearance.WithFaceLayer<Face>("Avatar/Layers/Face/Face_Agitated", Color32.op_Implicit(new Color32((byte)0, (byte)0, (byte)0, byte.MaxValue)));
					appearance.WithFaceLayer("avatar/layers/face/oldpersonwrinkles", Color32.op_Implicit(new Color32((byte)0, (byte)0, (byte)0, (byte)133)));
					appearance.WithBodyLayer("avatar/layers/top/buttonup", Color32.op_Implicit(new Color32((byte)237, (byte)237, (byte)237, byte.MaxValue)));
					appearance.WithBodyLayer("avatar/layers/bottom/jeans", Color32.op_Implicit(new Color32((byte)31, (byte)42, (byte)68, byte.MaxValue)));
					appearance.WithAccessoryLayer<FacialHairAccessory>("Avatar/Accessories/FacialHair/Chevron/Chevron", Color32.op_Implicit(new Color32((byte)59, (byte)42, (byte)32, byte.MaxValue)));
					appearance.WithAccessoryLayer<Head>("Avatar/Accessories/Head/FlatCap/FlatCap", Color32.op_Implicit(new Color32((byte)58, (byte)58, (byte)58, byte.MaxValue)));
					appearance.WithAccessoryLayer<Chest>("Avatar/Accessories/Chest/Blazer/Blazer", Color32.op_Implicit(new Color32((byte)31, (byte)42, (byte)68, byte.MaxValue)));
					appearance.WithAccessoryLayer<Feet>("Avatar/Accessories/Feet/DressShoes/DressShoes", Color32.op_Implicit(new Color32((byte)26, (byte)26, (byte)26, byte.MaxValue)));
					appearance.WithAccessoryLayer<Waist>("Avatar/Accessories/Waist/Belt/Belt", Color32.op_Implicit(new Color32((byte)26, (byte)26, (byte)26, byte.MaxValue)));
					appearance.WithAccessoryLayer<Neck>("Avatar/Accessories/Neck/GoldChain/GoldChain", Color32.op_Implicit(new Color32((byte)212, (byte)175, (byte)55, byte.MaxValue)));
				});
			}
		}
	}
	public interface IChapter3BeatingWorld
	{
		bool IsHost { get; }

		bool IsPlayerSpawned { get; }

		bool TryReadHealth(out float health, out float maxHealth, out string reason);

		bool TrySetHealth(float health, out string reason);

		bool TryLock(out string reason);

		bool TryUnlock(out string reason);

		bool TryFadeOut(out string reason);

		bool TryFadeIn(out string reason);

		bool TryJoltCamera(out string reason);

		bool TryMoveToWake(out (float X, float Y, float Z) wokeAt, out string propertyCode, out string reason);

		bool TryOpenBill(out string reason);
	}
	public interface IChapter3BeatingHq
	{
		bool PlayerInsideHq { get; }

		bool TryExit(out string reason);
	}
	public sealed class Chapter3SyndicateHqExit : IChapter3BeatingHq
	{
		private readonly Func<bool> _playerInsideHq;

		private readonly Func<bool> _tryExit;

		public bool PlayerInsideHq
		{
			get
			{
				try
				{
					return _playerInsideHq();
				}
				catch
				{
					return false;
				}
			}
		}

		public Chapter3SyndicateHqExit(Func<bool> playerInsideHq, Func<bool> tryExit)
		{
			_playerInsideHq = playerInsideHq ?? throw new ArgumentNullException("playerInsideHq");
			_tryExit = tryExit ?? throw new ArgumentNullException("tryExit");
		}

		public bool TryExit(out string reason)
		{
			reason = "the HQ exit did not run.";
			try
			{
				if (_tryExit())
				{
					reason = "left the HQ through its own exit.";
					return true;
				}
				reason = "the HQ service refused the exit.";
				return false;
			}
			catch (Exception ex)
			{
				reason = "the HQ exit threw " + ex.GetType().Name + ".";
				return false;
			}
		}
	}
	public enum Chapter3BeatingKind
	{
		Scheduled,
		Attack
	}
	public sealed class Chapter3ArthurBeating
	{
		private delegate bool TryBeatingStep(out string reason);

		private enum Chapter3BeatingStage
		{
			Lock,
			Line,
			Punches,
			FadeOut,
			Move,
			Park,
			Bill,
			Unlock,
			Record,
			Nell,
			Done,
			Aborted,
			Faulted
		}

		public const int PunchCount = 4;

		public const float PunchIntervalSeconds = 1.1f;

		public const float LineSeconds = 2f;

		public const float FadeSeconds = 0.7f;

		public const float HealthFloorFraction = 0.25f;

		public const float TimeoutSeconds = 30f;

		private readonly IChapter3BeatingWorld _world;

		private readonly IChapter3ArthurWorld _arthur;

		private readonly IChapter3BeatingHq _hq;

		private readonly Action<string> _log;

		private readonly Action _record;

		private readonly Action _noteNell;

		private readonly Action _parkArthur;

		private readonly float _startedAt;

		private Chapter3ArthurVisitState _pumpAtStart;

		private Chapter3BeatingStage _stage;

		private float _stageDueAt;

		private int _punchesDone;

		private float _startHealth;

		private float _maxHealth;

		private bool _moved;

		private bool _terminalLogged;

		public Chapter3BeatingKind Kind { get; }

		public bool ParkArthur { get; }

		public bool IsDone
		{
			get
			{
				Chapter3BeatingStage stage = _stage;
				if ((uint)(stage - 10) <= 2u)
				{
					return true;
				}
				return false;
			}
		}

		public bool CompletedOk => _stage == Chapter3BeatingStage.Done;

		public Chapter3ArthurBeating(IChapter3BeatingWorld world, IChapter3ArthurWorld arthur, IChapter3BeatingHq hq, Chapter3BeatingKind kind, bool parkArthur, Chapter3ArthurVisitState pumpAtStart, float startedAt, Action<string> log, Action record, Action noteNell, Action parkArthurAction)
		{
			_world = world ?? throw new ArgumentNullException("world");
			_arthur = arthur ?? throw new ArgumentNullException("arthur");
			_hq = hq ?? throw new ArgumentNullException("hq");
			Kind = kind;
			ParkArthur = parkArthur;
			_pumpAtStart = pumpAtStart;
			_startedAt = startedAt;
			_log = log ?? throw new ArgumentNullException("log");
			_record = record ?? throw new ArgumentNullException("record");
			_noteNell = noteNell ?? throw new ArgumentNullException("noteNell");
			_parkArthur = parkArthurAction ?? throw new ArgumentNullException("parkArthurAction");
			_stage = Chapter3BeatingStage.Lock;
			_stageDueAt = startedAt;
		}

		public void Tick(float now, Chapter3ArthurVisitState pumpState)
		{
			if (IsDone)
			{
				return;
			}
			if (now - _startedAt > 30f && now >= _startedAt)
			{
				Abort($"timed out after {30f:0} s.");
				return;
			}
			if (!_moved && pumpState != _pumpAtStart)
			{
				if (_pumpAtStart != Chapter3ArthurVisitState.Coming || pumpState != Chapter3ArthurVisitState.Arrived)
				{
					Abort($"the pump left {_pumpAtStart} for {pumpState} mid-beating.");
					return;
				}
				_pumpAtStart = pumpState;
			}
			if (now < _stageDueAt && now >= _startedAt)
			{
				return;
			}
			try
			{
				TickStage(now);
			}
			catch (Exception ex)
			{
				Abort("threw " + ex.GetType().Name + ".");
			}
		}

		public void AbortOutside(string reason)
		{
			Abort(reason);
		}

		public void AbortForUnload(string reason)
		{
			if (!IsDone)
			{
				_stage = Chapter3BeatingStage.Aborted;
				if (!_terminalLogged)
				{
					_terminalLogged = true;
					_log("Chapter 3 Arthur beating aborted: " + reason);
				}
				UnlockBestEffort();
			}
		}

		private void TickStage(float now)
		{
			switch (_stage)
			{
			case Chapter3BeatingStage.Lock:
			{
				if (!Guarded(_world.TryLock, out string reason8))
				{
					Abort("the lock failed: " + reason8);
					break;
				}
				if (!GuardedHealth(out float health, out float maxHealth, out string reason9))
				{
					Abort("the health read failed: " + reason9);
					break;
				}
				if (maxHealth <= 0f || health <= 0f)
				{
					Abort("the player is not up for a beating.");
					break;
				}
				_startHealth = health;
				_maxHealth = maxHealth;
				_log($"Chapter 3 Arthur beating: locked (invincible, movement and items held) at {health:0} / {maxHealth:0} health.");
				Advance(Chapter3BeatingStage.Line, now);
				break;
			}
			case Chapter3BeatingStage.Line:
			{
				if ((ParkArthur ? _arthur.TryFacePlayer(out string reason6) : _arthur.TryFacePlayerAtHq(out reason6)) != Chapter3ArthurMutationStatus.Succeeded)
				{
					Abort("the face failed: " + reason6);
					break;
				}
				string text = ((Kind == Chapter3BeatingKind.Scheduled) ? "I said I wouldn't be polite." : "Wrong fucking move.");
				if (_arthur.TrySayArthur(text, out string reason7) != Chapter3ArthurMutationStatus.Succeeded)
				{
					Abort("the line failed: " + reason7);
					break;
				}
				_log("Chapter 3 Arthur beating: Arthur says \"" + text + "\"");
				_stage = Chapter3BeatingStage.Punches;
				_stageDueAt = now + 2f;
				break;
			}
			case Chapter3BeatingStage.Punches:
				ThrowPunch(now);
				break;
			case Chapter3BeatingStage.FadeOut:
			{
				if (!Guarded(_world.TryFadeOut, out string reason2))
				{
					Abort("the fade out failed: " + reason2);
				}
				else
				{
					Advance(Chapter3BeatingStage.Move, now + 0.7f);
				}
				break;
			}
			case Chapter3BeatingStage.Move:
			{
				if (ReadHqInside())
				{
					if (!Guarded(_hq.TryExit, out string reason3))
					{
						Abort("the HQ exit failed: " + reason3);
						break;
					}
					_log("Chapter 3 Arthur beating: left the HQ through its own exit.");
				}
				if (!GuardedMove(out (float, float, float) wokeAt, out string propertyCode, out string reason4))
				{
					Abort("the move failed: " + reason4);
					break;
				}
				_log($"Chapter 3 Arthur beating: woke at ({wokeAt.Item1:0.0}, {wokeAt.Item2:0.0}, {wokeAt.Item3:0.0}) ({propertyCode}).");
				_moved = true;
				Advance(Chapter3BeatingStage.Park, now);
				break;
			}
			case Chapter3BeatingStage.Park:
			{
				if (ParkArthur)
				{
					_parkArthur();
					_log("Chapter 3 Arthur beating: Arthur parked.");
				}
				else
				{
					_log("Chapter 3 Arthur beating: no park; the pump owns Arthur at the HQ.");
				}
				if (!Guarded(_world.TryFadeIn, out string reason10))
				{
					Abort("the fade in failed: " + reason10);
				}
				else
				{
					Advance(Chapter3BeatingStage.Bill, now + 0.7f);
				}
				break;
			}
			case Chapter3BeatingStage.Bill:
			{
				if (!Guarded(_world.TryOpenBill, out string reason5))
				{
					Abort("the bill failed: " + reason5);
					break;
				}
				_log("Chapter 3 Arthur beating: the hospital bill is open.");
				Advance(Chapter3BeatingStage.Unlock, now);
				break;
			}
			case Chapter3BeatingStage.Unlock:
			{
				if (!Guarded(_world.TryUnlock, out string reason))
				{
					Abort("the unlock failed: " + reason);
					break;
				}
				_log("Chapter 3 Arthur beating: unlocked, exactly as it was.");
				Advance(Chapter3BeatingStage.Record, now);
				break;
			}
			case Chapter3BeatingStage.Record:
				_record();
				Advance(Chapter3BeatingStage.Nell, now);
				break;
			case Chapter3BeatingStage.Nell:
				_noteNell();
				_stage = Chapter3BeatingStage.Done;
				_log("Chapter 3 Arthur beating: complete; Nell's text is queued.");
				break;
			}
		}

		private bool ThrowPunch(float now)
		{
			if (_arthur.TryPlayAnimationTrigger("Punch", out string reason) != Chapter3ArthurMutationStatus.Succeeded)
			{
				Abort($"punch {_punchesDone + 1} animation failed: {reason}");
				return false;
			}
			if (!Guarded(_world.TryJoltCamera, out string reason2))
			{
				Abort($"punch {_punchesDone + 1} jolt failed: {reason2}");
				return false;
			}
			float num = _maxHealth * 0.25f;
			float num2 = ((_startHealth > num) ? Math.Max(num, _startHealth - (_startHealth - num) * (float)(_punchesDone + 1) / 4f) : _startHealth);
			if (!GuardedSetHealth(num2, out string reason3))
			{
				Abort($"punch {_punchesDone + 1} health set failed: {reason3}");
				return false;
			}
			_punchesDone++;
			_log($"Chapter 3 Arthur beating: punch {_punchesDone}/{4} lands at {num2:0} health.");
			if (_punchesDone >= 4)
			{
				Advance(Chapter3BeatingStage.FadeOut, now);
			}
			else
			{
				_stageDueAt = now + 1.1f;
			}
			return true;
		}

		private void Advance(Chapter3BeatingStage stage, float dueAt)
		{
			_stage = stage;
			_stageDueAt = dueAt;
		}

		private void Abort(string reason)
		{
			if (IsDone)
			{
				return;
			}
			if (_moved)
			{
				FinishWithFault(reason);
				return;
			}
			_stage = Chapter3BeatingStage.Aborted;
			if (!_terminalLogged)
			{
				_terminalLogged = true;
				_log("Chapter 3 Arthur beating aborted: " + reason);
			}
			UnlockBestEffort();
		}

		private void FinishWithFault(string reason)
		{
			_stage = Chapter3BeatingStage.Faulted;
			UnlockBestEffort();
			try
			{
				if (!_world.TryFadeIn(out string reason2))
				{
					_log("Chapter 3 Arthur beating fault fade-in failed: " + reason2);
				}
			}
			catch (Exception ex)
			{
				_log("Chapter 3 Arthur beating fault fade-in threw " + ex.GetType().Name + ".");
			}
			try
			{
				_record();
			}
			catch (Exception ex2)
			{
				_log("Chapter 3 Arthur beating fault record threw " + ex2.GetType().Name + ".");
			}
			try
			{
				_noteNell();
			}
			catch (Exception ex3)
			{
				_log("Chapter 3 Arthur beating fault note threw " + ex3.GetType().Name + ".");
			}
			_log("Chapter 3 Arthur beating finished with a fault after the wake: " + reason + "; recorded.");
		}

		private void UnlockBestEffort()
		{
			try
			{
				if (!_world.TryUnlock(out string reason))
				{
					_log("Chapter 3 Arthur beating abort unlock failed: " + reason);
				}
			}
			catch (Exception ex)
			{
				_log("Chapter 3 Arthur beating abort unlock threw " + ex.GetType().Name + ".");
			}
		}

		private bool Guarded(TryBeatingStep step, out string reason)
		{
			reason = "the step did not run.";
			try
			{
				return step(out reason);
			}
			catch (Exception ex)
			{
				reason = "threw " + ex.GetType().Name + ".";
				return false;
			}
		}

		private bool GuardedHealth(out float health, out float maxHealth, out string reason)
		{
			health = 0f;
			maxHealth = 0f;
			reason = "the health read did not run.";
			try
			{
				return _world.TryReadHealth(out health, out maxHealth, out reason);
			}
			catch (Exception ex)
			{
				reason = "threw " + ex.GetType().Name + ".";
				return false;
			}
		}

		private bool GuardedSetHealth(float health, out string reason)
		{
			reason = "the health set did not run.";
			try
			{
				return _world.TrySetHealth(health, out reason);
			}
			catch (Exception ex)
			{
				reason = "threw " + ex.GetType().Name + ".";
				return false;
			}
		}

		private bool GuardedMove(out (float X, float Y, float Z) wokeAt, out string propertyCode, out string reason)
		{
			wokeAt = (X: 0f, Y: 0f, Z: 0f);
			propertyCode = string.Empty;
			reason = "the move did not run.";
			try
			{
				return _world.TryMoveToWake(out wokeAt, out propertyCode, out reason);
			}
			catch (Exception ex)
			{
				reason = "threw " + ex.GetType().Name + ".";
				return false;
			}
		}

		private bool ReadHqInside()
		{
			try
			{
				return _hq.PlayerInsideHq;
			}
			catch
			{
				return false;
			}
		}
	}
	public static class Chapter3ArthurIds
	{
		public const string NpcId = "oc_chapter3_arthur";

		public const string FirstName = "Arthur";

		public const string LastName = "Selby";
	}
	public enum Chapter3ArthurVisitState
	{
		Parked,
		Coming,
		Arrived,
		Leaving,
		AtHq
	}
	public enum Chapter3ArthurReadStatus
	{
		Ready,
		Pending,
		Unavailable,
		Faulted
	}
	public enum Chapter3ArthurMutationStatus
	{
		Succeeded,
		Rejected,
		Unavailable,
		Ambiguous
	}
	public sealed record Chapter3ArthurSnapshot(bool Present, bool Spawned, bool Visible, bool Moving, bool Conscious, (float X, float Y, float Z) Position, float DistanceToPlayer, int RegisteredCount, float Health = float.NaN, bool InPlayerView = true)
	{
		public static Chapter3ArthurSnapshot Absent()
		{
			return new Chapter3ArthurSnapshot(Present: false, Spawned: false, Visible: false, Moving: false, Conscious: false, (X: 0f, Y: 0f, Z: 0f), float.NaN, 0);
		}
	}
	public interface IChapter3ArthurWorld
	{
		bool HasAuthority { get; }

		Chapter3ArthurReadStatus TryReadArthur(out Chapter3ArthurSnapshot snapshot);

		Chapter3ArthurMutationStatus TryMoveOutOfSight(out string reason);

		Chapter3ArthurMutationStatus TryParkArthur(out string reason);

		Chapter3ArthurMutationStatus TryVerifyAppearancePaths(out string reason);

		Chapter3ArthurMutationStatus TryComeArthur(out string reason);

		Chapter3ArthurMutationStatus TrySayArthur(string text, out string reason);

		Chapter3ArthurMutationStatus TryLeaveArthur(out string reason);

		Chapter3ArthurMutationStatus TryFacePlayer(out string reason);

		Chapter3ArthurMutationStatus TryFacePlayerAtHq(out string reason);

		Chapter3ArthurMutationStatus TryCaptureHqSpot(out (float X, float Y, float Z) local, out float yawDegrees, out string reason);

		Chapter3ArthurMutationStatus TryPlaceAtHq(out string reason);

		Chapter3ArthurMutationStatus TryResumeWalk(out string reason);

		Chapter3ArthurMutationStatus TryDedupeArthur(out string reason);

		Chapter3ArthurMutationStatus TryPlayAnimationTrigger(string trigger, out string reason);

		bool PollArthurImpact();
	}
	public sealed record Chapter3ArthurCandidate((float X, float Y, float Z) Point, float DistanceToPlayer, bool BehindPlayer, bool Reachable);
	public interface IChapter3ArthurHqBody
	{
		Chapter3ArthurMutationStatus TryActivateBody(out string reason);

		Chapter3ArthurMutationStatus TrySetAgentEnabled(bool enabled, out string reason);

		Chapter3ArthurMutationStatus TrySetPhysicsHeld(bool held, out string reason);

		Chapter3ArthurMutationStatus TrySetTransform((float X, float Y, float Z) position, float yawDegrees, out string reason);

		Chapter3ArthurMutationStatus TrySetVisible(bool visible, out string reason);

		Chapter3ArthurMutationStatus TryFacePlayerDirect(out string reason);

		Chapter3ArthurMutationStatus TryReadPlacement(out (float X, float Y, float Z) position, out bool agentEnabled, out string reason);
	}
	public static class Chapter3ArthurHqPlacer
	{
		private delegate Chapter3ArthurMutationStatus Step(out string reason);

		public const float PlaceToleranceMetres = 0.5f;

		public static Chapter3ArthurMutationStatus TryPlace(IChapter3ArthurHqBody? body, (float X, float Y, float Z) spot, float yawDegrees, out string reason)
		{
			reason = "the HQ place did not run.";
			if (body == null)
			{
				reason = "the HQ body was not wired up.";
				return Chapter3ArthurMutationStatus.Unavailable;
			}
			Chapter3ArthurMutationStatus chapter3ArthurMutationStatus = Guarded(body.TryActivateBody, out string reason2);
			if (chapter3ArthurMutationStatus != Chapter3ArthurMutationStatus.Succeeded)
			{
				reason = $"activate {chapter3ArthurMutationStatus}: {reason2}";
				return chapter3ArthurMutationStatus;
			}
			chapter3ArthurMutationStatus = Guarded(delegate(out string r)
			{
				return body.TrySetAgentEnabled(enabled: false, out r);
			}, out reason2);
			if (chapter3ArthurMutationStatus != Chapter3ArthurMutationStatus.Succeeded)
			{
				reason = $"agent off {chapter3ArthurMutationStatus}: {reason2}";
				return chapter3ArthurMutationStatus;
			}
			chapter3ArthurMutationStatus = Guarded(delegate(out string r)
			{
				return body.TrySetPhysicsHeld(held: true, out r);
			}, out reason2);
			if (chapter3ArthurMutationStatus != Chapter3ArthurMutationStatus.Succeeded)
			{
				reason = $"physics hold {chapter3ArthurMutationStatus}: {reason2}";
				return chapter3ArthurMutationStatus;
			}
			chapter3ArthurMutationStatus = Guarded(delegate(out string r)
			{
				return body.TrySetTransform(spot, yawDegrees, out r);
			}, out reason2);
			if (chapter3ArthurMutationStatus != Chapter3ArthurMutationStatus.Succeeded)
			{
				reason = $"transform {chapter3ArthurMutationStatus}: {reason2}";
				return chapter3ArthurMutationStatus;
			}
			chapter3ArthurMutationStatus = Guarded(delegate(out string r)
			{
				return body.TrySetVisible(visible: true, out r);
			}, out reason2);
			if (chapter3ArthurMutationStatus != Chapter3ArthurMutationStatus.Succeeded)
			{
				reason = $"visible {chapter3ArthurMutationStatus}: {reason2}";
				return chapter3ArthurMutationStatus;
			}
			chapter3ArthurMutationStatus = GuardedRead(body, out (float, float, float) position, out bool agentEnabled, out string reason3);
			if (chapter3ArthurMutationStatus != Chapter3ArthurMutationStatus.Succeeded)
			{
				reason = $"read-back {chapter3ArthurMutationStatus}: {reason3}";
				return chapter3ArthurMutationStatus;
			}
			float num = position.Item1 - spot.X;
			float num2 = position.Item2 - spot.Y;
			float num3 = position.Item3 - spot.Z;
			float num4 = (float)Math.Sqrt(num * num + num2 * num2 + num3 * num3);
			reason = $"HQ place: requested {Format(spot)}, actual {Format(position)}, agent {(agentEnabled ? "on" : "off")}; {reason3}";
			if (!(num4 <= 0.5f))
			{
				return Chapter3ArthurMutationStatus.Ambiguous;
			}
			return Chapter3ArthurMutationStatus.Succeeded;
		}

		public static Chapter3ArthurMutationStatus TryRestoreForWalk(IChapter3ArthurHqBody? body, out string reason)
		{
			reason = "the movement restore did not run.";
			if (body == null)
			{
				reason = "the HQ body was not wired up.";
				return Chapter3ArthurMutationStatus.Unavailable;
			}
			Chapter3ArthurMutationStatus chapter3ArthurMutationStatus = Guarded(delegate(out string r)
			{
				return body.TrySetAgentEnabled(enabled: true, out r);
			}, out string reason2);
			if (chapter3ArthurMutationStatus != Chapter3ArthurMutationStatus.Succeeded)
			{
				reason = $"agent on {chapter3ArthurMutationStatus}: {reason2}";
				return chapter3ArthurMutationStatus;
			}
			chapter3ArthurMutationStatus = Guarded(delegate(out string r)
			{
				return body.TrySetPhysicsHeld(held: false, out r);
			}, out reason2);
			if (chapter3ArthurMutationStatus != Chapter3ArthurMutationStatus.Succeeded)
			{
				reason = $"physics restore {chapter3ArthurMutationStatus}: {reason2}";
				return chapter3ArthurMutationStatus;
			}
			reason = "movement restored for the walk: agent on, physics restored.";
			return Chapter3ArthurMutationStatus.Succeeded;
		}

		public static Chapter3ArthurMutationStatus TryFacePlayer(IChapter3ArthurHqBody? body, out string reason)
		{
			reason = "the HQ face did not run.";
			if (body == null)
			{
				reason = "the HQ body was not wired up.";
				return Chapter3ArthurMutationStatus.Unavailable;
			}
			return Guarded(body.TryFacePlayerDirect, out reason);
		}

		private static string Format((float X, float Y, float Z) point)
		{
			return $"({point.X:0.00}, {point.Y:0.00}, {point.Z:0.00})";
		}

		private static Chapter3ArthurMutationStatus Guarded(Step step, out string reason)
		{
			reason = "the HQ body step did not run.";
			try
			{
				return step(out reason);
			}
			catch (Exception ex)
			{
				reason = "threw " + ex.GetType().Name + ": " + ex.Message;
				return Chapter3ArthurMutationStatus.Ambiguous;
			}
		}

		private static Chapter3ArthurMutationStatus GuardedRead(IChapter3ArthurHqBody body, out (float X, float Y, float Z) position, out bool agentEnabled, out string reason)
		{
			position = (X: 0f, Y: 0f, Z: 0f);
			agentEnabled = true;
			reason = "the HQ body step did not run.";
			try
			{
				return body.TryReadPlacement(out position, out agentEnabled, out reason);
			}
			catch (Exception ex)
			{
				reason = "threw " + ex.GetType().Name + ": " + ex.Message;
				return Chapter3ArthurMutationStatus.Ambiguous;
			}
		}
	}
	public interface IChapter3HqPresence
	{
		bool ChapterActive { get; }

		bool PlayerInsideHq { get; }
	}
	public enum Chapter3ArthurHqForce
	{
		Auto,
		On,
		Off
	}
	public static class Chapter3ArthurHqSpot
	{
		public static readonly (float X, float Y, float Z) Local = (X: -2.9f, Y: 0f, Z: 3.7f);

		public const float YawDegrees = 180f;

		public const float FaceRangeMetres = 6f;

		public const float MaintainIntervalSeconds = 0.25f;

		public static (float X, float Y, float Z) ToWorld((float X, float Y, float Z) pocketRoot, float floorTopY)
		{
			return (X: pocketRoot.X + Local.X, Y: pocketRoot.Y + floorTopY, Z: pocketRoot.Z + Local.Z);
		}

		public static (float X, float Y, float Z) ToLocal((float X, float Y, float Z) world, (float X, float Y, float Z) pocketRoot)
		{
			return (X: world.X - pocketRoot.X, Y: world.Y - pocketRoot.Y, Z: world.Z - pocketRoot.Z);
		}

		public static bool IsInsideFrame((float X, float Y, float Z) local)
		{
			if (Math.Abs(local.X) <= 7f && Math.Abs(local.Z) <= 5f && local.Y >= -2f)
			{
				return local.Y <= 4.5f;
			}
			return false;
		}
	}
	public sealed class Chapter3SyndicateHqPresence : IChapter3HqPresence
	{
		private readonly Func<bool> _chapterActive;

		private readonly Func<bool> _playerInsideHq;

		public bool ChapterActive
		{
			get
			{
				try
				{
					return _chapterActive();
				}
				catch
				{
					return false;
				}
			}
		}

		public bool PlayerInsideHq
		{
			get
			{
				try
				{
					return _playerInsideHq();
				}
				catch
				{
					return false;
				}
			}
		}

		public Chapter3SyndicateHqPresence(Func<bool> chapterActive, Func<bool> playerInsideHq)
		{
			_chapterActive = chapterActive ?? throw new ArgumentNullException("chapterActive");
			_playerInsideHq = playerInsideHq ?? throw new ArgumentNullException("playerInsideHq");
		}
	}
	public sealed class Chapter3ArthurNpc : NPC
	{
		public override bool IsPhysical => true;

		protected override void ConfigurePrefab(NPCPrefabBuilder builder)
		{
			if (builder != null)
			{
				builder.WithIdentity("oc_chapter3_arthur", "Arthur", "Selby");
				Chapter3ArthurAppearance.ApplyTo(builder);
			}
		}
	}
	public interface IChapter3ArthurPhone
	{
		bool TryCall(Chapter3ArthurVisitKind kind, IReadOnlyList<string> stages, int chapterDay, out string reason);
	}
	public static class Chapter3ArthurPlacement
	{
		public const float ComeMinMetres = 20f;

		public const float ComeMaxMetres = 30f;

		public const float LeaveMetres = 30f;

		public static Chapter3ArthurCandidate? SelectComeCandidate(IEnumerable<Chapter3ArthurCandidate> candidates)
		{
			if (candidates == null)
			{
				return null;
			}
			Chapter3ArthurCandidate[] array = candidates.Where((Chapter3ArthurCandidate candidate) => candidate?.Reachable ?? false).ToArray();
			if (array.Length == 0)
			{
				return null;
			}
			return (from candidate in array
				orderby (!InBand(candidate.DistanceToPlayer)) ? 1 : 0, (!candidate.BehindPlayer) ? 1 : 0, Math.Abs(candidate.DistanceToPlayer - 25f)
				select candidate).First();
		}

		public static Chapter3ArthurCandidate? SelectLeaveCandidate(IEnumerable<Chapter3ArthurCandidate> candidates)
		{
			if (candidates == null)
			{
				return null;
			}
			Chapter3ArthurCandidate[] array = candidates.Where((Chapter3ArthurCandidate candidate) => candidate?.Reachable ?? false).ToArray();
			if (array.Length == 0)
			{
				return null;
			}
			return (from candidate in array
				orderby (!candidate.BehindPlayer) ? 1 : 0, Math.Abs(candidate.DistanceToPlayer - 30f)
				select candidate).First();
		}

		private static bool InBand(float distance)
		{
			if (distance >= 20f)
			{
				return distance <= 30f;
			}
			return false;
		}
	}
	public static class Chapter3ArthurResponseFilter
	{
		private static int _impactFlag;

		public static bool ShouldSuppress(string? npcId)
		{
			return string.Equals(npcId, "oc_chapter3_arthur", StringComparison.Ordinal);
		}

		public static void NoteImpact()
		{
			Interlocked.Exchange(ref _impactFlag, 1);
		}

		public static bool PollImpact()
		{
			return Interlocked.Exchange(ref _impactFlag, 0) == 1;
		}
	}
	internal static class Chapter3ArthurResponsePatch
	{
		public static bool Apply(Harmony harmony, Action<string>? log = null)
		{
			if (log == null)
			{
				log = delegate
				{
				};
			}
			return (byte)(1u & (TryPatch(harmony, log, typeof(NPC), "ReceiveImpact", new Type[1] { typeof(Impact) }, "ReceiveImpactPrefix") ? 1u : 0u) & (TryPatch(harmony, log, typeof(NPCResponses), "ImpactReceived", new Type[1] { typeof(Impact) }, "ImpactReceivedPrefix") ? 1u : 0u) & (TryPatch(harmony, log, typeof(NPCHealth), "TakeDamage", new Type[2]
			{
				typeof(float),
				typeof(bool)
			}, "TakeDamagePrefix") ? 1u : 0u) & (TryPatch(harmony, log, typeof(NPCHealth), "KnockOut", Type.EmptyTypes, "KnockOutPrefix") ? 1u : 0u) & (TryPatch(harmony, log, typeof(NPCHealth), "Die", Type.EmptyTypes, "DiePrefix") ? 1u : 0u)) != 0;
		}

		private static bool TryPatch(Harmony harmony, Action<string> log, Type targetType, string methodName, Type[] argumentTypes, string prefixName)
		{
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Expected O, but got Unknown
			try
			{
				MethodInfo methodInfo = AccessTools.Method(targetType, methodName, argumentTypes, (Type[])null);
				if ((object)methodInfo == null)
				{
					log($"Chapter 3 Arthur response patch missed {targetType.Name}.{methodName}; Arthur may react like a native NPC.");
					return false;
				}
				MethodInfo methodInfo2 = AccessTools.Method(typeof(Chapter3ArthurResponsePatch), prefixName, (Type[])null, (Type[])null);
				if ((object)methodInfo2 == null)
				{
					log("Chapter 3 Arthur response patch missed its own " + prefixName + ".");
					return false;
				}
				harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				return true;
			}
			catch (Exception ex)
			{
				log($"Chapter 3 Arthur response patch failed on {targetType.Name}.{methodName}: {ex.GetType().Name}.");
				return false;
			}
		}

		private static bool ReceiveImpactPrefix(NPC __instance, Impact __0)
		{
			if (!IsArthurNpc(__instance))
			{
				return true;
			}
			Chapter3ArthurResponseFilter.NoteImpact();
			return false;
		}

		private static bool ImpactReceivedPrefix(NPCResponses __instance, Impact __0)
		{
			if (!IsArthurResponses(__instance))
			{
				return true;
			}
			Chapter3ArthurResponseFilter.NoteImpact();
			return false;
		}

		private static void TakeDamagePrefix(NPCHealth __instance, ref float __0)
		{
			if (IsArthurHealth(__instance))
			{
				__0 = 0f;
			}
		}

		private static bool KnockOutPrefix(NPCHealth __instance)
		{
			return !IsArthurHealth(__instance);
		}

		private static bool DiePrefix(NPCHealth __instance)
		{
			return !IsArthurHealth(__instance);
		}

		private static bool IsArthurNpc(NPC? npc)
		{
			try
			{
				return npc != null && Chapter3ArthurResponseFilter.ShouldSuppress(npc.ID);
			}
			catch
			{
				return false;
			}
		}

		private static bool IsArthurHealth(NPCHealth? health)
		{
			try
			{
				return health != null && IsArthurNpc(health._npc);
			}
			catch
			{
				return false;
			}
		}

		private static bool IsArthurResponses(NPCResponses? responses)
		{
			try
			{
				return responses != null && IsArthurNpc(responses.npc);
			}
			catch
			{
				return false;
			}
		}
	}
	public sealed record Chapter3ArthurVisitConditions(bool OnFoot, bool Outdoors, bool ClearOfPursuit, string Detail)
	{
		public bool Met
		{
			get
			{
				if (OnFoot && Outdoors)
				{
					return ClearOfPursuit;
				}
				return false;
			}
		}

		public static Chapter3ArthurVisitConditions Clear(string detail = "on foot, outdoors, clear of pursuit")
		{
			return new Chapter3ArthurVisitConditions(OnFoot: true, Outdoors: true, ClearOfPursuit: true, detail);
		}

		public static Chapter3ArthurVisitConditions Blocked(bool onFoot, bool outdoors, bool clearOfPursuit, string detail)
		{
			return new Chapter3ArthurVisitConditions(onFoot, outdoors, clearOfPursuit, detail);
		}
	}
	public interface IChapter3ArthurVisitConditions
	{
		bool TryRead(out Chapter3ArthurVisitConditions conditions);
	}
	public enum Chapter3ArthurVisitOutcome
	{
		Parked,
		Arrived,
		SpawnPending,
		ReadFailed,
		BoundExpired,
		WalkReissued,
		HqPlaced,
		Attacked
	}
	public sealed record Chapter3ArthurVisitStep(Chapter3ArthurVisitOutcome Outcome, IReadOnlyList<string> Lines);
	public sealed class Chapter3ArthurVisitPump
	{
		public const float RetryIntervalSeconds = 1f;

		public const float MaxSeconds = 90f;

		public const float LeaveSeconds = 30f;

		public const float ComeSeconds = 30f;

		public const float ArrivedMetres = 2.5f;

		public const float LeaveParkMetres = 25f;

		public const float WalkGraceSeconds = 1f;

		public const int MaxWalkResumes = 2;

		public const float HqAttemptIntervalSeconds = 1f;

		public const float AttackDropHealth = 1f;

		public const float AttackIncidentSeconds = 10f;

		private const int MaxDetailLength = 160;

		private readonly Func<float> _realtimeSinceStartup;

		private bool _reconcilePending;

		private bool _failureReported;

		private bool _verifyDone;

		private bool _preSpawnMoveLogged;

		private float _deadline;

		private readonly IntervalGate _retryGate;

		private float _leaveDeadline;

		private float _comeDeadline;

		private float _walkIssuedAt;

		private int _resumesLeft = 2;

		private readonly IntervalGate _hqAttemptGate;

		private readonly IntervalGate _hqMaintainGate;

		private bool _hqInteriorAbsent;

		private float _attackBaseline = float.NaN;

		private float _attackLastHealth = float.NaN;

		private float _attackLastDropAt;

		private bool _attackIncidentOpen;

		public Chapter3ArthurVisitState State { get; private set; }

		public IChapter3HqPresence? HqPresence { get; set; }

		public Chapter3ArthurHqForce HqForce { get; set; }

		public Chapter3ArthurVisitPump(Func<float> realtimeSinceStartup)
		{
			_realtimeSinceStartup = realtimeSinceStartup ?? throw new ArgumentNullException("realtimeSinceStartup");
			_retryGate = new IntervalGate(1f);
			_hqAttemptGate = new IntervalGate(1f);
			_hqMaintainGate = new IntervalGate(0.25f);
		}

		public void BeginAfterLoad()
		{
			State = Chapter3ArthurVisitState.Parked;
			float num = _realtimeSinceStartup();
			_reconcilePending = true;
			_failureReported = false;
			_verifyDone = false;
			_preSpawnMoveLogged = false;
			_deadline = num + 90f;
			_retryGate.Reset(num);
			_resumesLeft = 2;
			_hqAttemptGate.Reset(num);
			_hqMaintainGate.Reset(num);
			_hqInteriorAbsent = false;
			_attackBaseline = float.NaN;
			_attackLastHealth = float.NaN;
			_attackIncidentOpen = false;
		}

		public bool BeginCome()
		{
			if (State != Chapter3ArthurVisitState.Parked && State != Chapter3ArthurVisitState.AtHq)
			{
				return false;
			}
			State = Chapter3ArthurVisitState.Coming;
			_comeDeadline = (_walkIssuedAt = _realtimeSinceStartup()) + 30f;
			_resumesLeft = 2;
			return true;
		}

		public bool BeginLeave()
		{
			if (State != Chapter3ArthurVisitState.Coming && State != Chapter3ArthurVisitState.Arrived)
			{
				return false;
			}
			State = Chapter3ArthurVisitState.Leaving;
			_leaveDeadline = (_walkIssuedAt = _realtimeSinceStartup()) + 30f;
			_resumesLeft = 2;
			return true;
		}

		public void ParkAfterBeating()
		{
			State = Chapter3ArthurVisitState.Parked;
			_resumesLeft = 2;
			_attackBaseline = float.NaN;
			_attackLastHealth = float.NaN;
			_attackIncidentOpen = false;
		}

		public void CancelLoadReconcile()
		{
			_reconcilePending = false;
		}

		public Chapter3ArthurVisitStep? Pump(IChapter3ArthurWorld? world)
		{
			if (world == null || !world.HasAuthority)
			{
				return null;
			}
			if (_reconcilePending)
			{
				return PumpReconcile(world);
			}
			bool flag = WantHq();
			Chapter3ArthurVisitState state = State;
			if ((uint)(state - 1) <= 2u)
			{
				if (flag)
				{
					return PumpEndVisitForHq(world);
				}
				return State switch
				{
					Chapter3ArthurVisitState.Coming => PumpComing(world), 
					Chapter3ArthurVisitState.Arrived => PumpArrived(world), 
					_ => PumpLeaving(world), 
				};
			}
			if (State == Chapter3ArthurVisitState.AtHq)
			{
				if (!flag)
				{
					State = Chapter3ArthurVisitState.Parked;
					string reason;
					Chapter3ArthurMutationStatus value = world.TryParkArthur(out reason);
					return new Chapter3ArthurVisitStep(Chapter3ArthurVisitOutcome.Parked, new string[1] { $"left the HQ spot; park {value}: {reason}" });
				}
				return PumpAtHq(world);
			}
			if (flag)
			{
				return PumpParkedWantHq(world);
			}
			world.PollArthurImpact();
			return null;
		}

		private Chapter3ArthurVisitStep? PumpReconcile(IChapter3ArthurWorld world)
		{
			float num = _realtimeSinceStartup();
			if (num >= _deadline)
			{
				_reconcilePending = false;
				return new Chapter3ArthurVisitStep(Chapter3ArthurVisitOutcome.BoundExpired, new string[1] { $"gave up after {90f} seconds; Arthur never spawned, left untouched." });
			}
			if (!_retryGate.TryPass(num))
			{
				return null;
			}
			Chapter3ArthurSnapshot snapshot;
			Chapter3ArthurReadStatus chapter3ArthurReadStatus = TryRead(world, out snapshot);
			if (chapter3ArthurReadStatus != Chapter3ArthurReadStatus.Ready || (object)snapshot == null)
			{
				return ReportFailureOnce($"the Arthur read status was {chapter3ArthurReadStatus}.");
			}
			if (!snapshot.Present)
			{
				return ReportFailureOnce("no Arthur contact constructed yet.");
			}
			List<string> list = new List<string>();
			if (!_verifyDone)
			{
				_verifyDone = true;
				string reason;
				Chapter3ArthurMutationStatus value = world.TryVerifyAppearancePaths(out reason);
				list.Add($"appearance paths {value}: {reason}");
			}
			if (!snapshot.Spawned)
			{
				string reason2;
				Chapter3ArthurMutationStatus value2 = world.TryMoveOutOfSight(out reason2);
				if (!_preSpawnMoveLogged)
				{
					_preSpawnMoveLogged = true;
					list.Add($"pre-spawn move {value2}: {reason2}");
				}
				if (list.Count == 0)
				{
					return null;
				}
				return new Chapter3ArthurVisitStep(Chapter3ArthurVisitOutcome.SpawnPending, list);
			}
			_reconcilePending = false;
			State = Chapter3ArthurVisitState.Parked;
			if (snapshot.RegisteredCount > 1)
			{
				string reason3;
				Chapter3ArthurMutationStatus value3 = world.TryDedupeArthur(out reason3);
				list.Add($"dedupe {value3}: {reason3}");
			}
			string reason4;
			Chapter3ArthurMutationStatus value4 = world.TryParkArthur(out reason4);
			list.Add($"park {value4}: {reason4}");
			return new Chapter3ArthurVisitStep(Chapter3ArthurVisitOutcome.Parked, list);
		}

		private Chapter3ArthurVisitStep? ReportFailureOnce(string line)
		{
			if (_failureReported)
			{
				return null;
			}
			_failureReported = true;
			return new Chapter3ArthurVisitStep(Chapter3ArthurVisitOutcome.ReadFailed, new string[1] { Truncate(line) });
		}

		private Chapter3ArthurVisitStep? PumpComing(IChapter3ArthurWorld world)
		{
			float num = _realtimeSinceStartup();
			if (TryRead(world, out Chapter3ArthurSnapshot snapshot) != Chapter3ArthurReadStatus.Ready || (object)snapshot == null || !snapshot.Present || !snapshot.Spawned)
			{
				return null;
			}
			Chapter3ArthurVisitStep chapter3ArthurVisitStep = CheckAttacked(snapshot, "visit", num, world.PollArthurImpact());
			if ((object)chapter3ArthurVisitStep != null)
			{
				return chapter3ArthurVisitStep;
			}
			if (num < _walkIssuedAt + 1f)
			{
				return null;
			}
			if (snapshot.DistanceToPlayer <= 2.5f)
			{
				State = Chapter3ArthurVisitState.Arrived;
				string reason;
				Chapter3ArthurMutationStatus value = world.TryFacePlayer(out reason);
				return new Chapter3ArthurVisitStep(Chapter3ArthurVisitOutcome.Arrived, new string[1] { $"arrived {snapshot.DistanceToPlayer:0.0} m from the player; face {value}: {reason}" });
			}
			if (num >= _comeDeadline)
			{
				State = Chapter3ArthurVisitState.Arrived;
				string reason2;
				Chapter3ArthurMutationStatus value2 = world.TryFacePlayer(out reason2);
				return new Chapter3ArthurVisitStep(Chapter3ArthurVisitOutcome.Arrived, new string[1] { $"come bound expired after {30f} seconds; stopped and faced the player where he is ({snapshot.DistanceToPlayer:0.0} m); face {value2}: {reason2}" });
			}
			if (!snapshot.Moving && _resumesLeft > 0)
			{
				_resumesLeft--;
				string reason3;
				Chapter3ArthurMutationStatus value3 = world.TryResumeWalk(out reason3);
				return new Chapter3ArthurVisitStep(Chapter3ArthurVisitOutcome.WalkReissued, new string[1] { $"stopped {snapshot.DistanceToPlayer:0.0} m out; walk re-issue {value3}: {reason3} ({_resumesLeft} left)" });
			}
			return null;
		}

		private Chapter3ArthurVisitStep? PumpArrived(IChapter3ArthurWorld world)
		{
			if (TryRead(world, out Chapter3ArthurSnapshot snapshot) != Chapter3ArthurReadStatus.Ready || (object)snapshot == null || !snapshot.Present || !snapshot.Spawned)
			{
				return null;
			}
			return CheckAttacked(snapshot, "visit", _realtimeSinceStartup(), world.PollArthurImpact());
		}

		private Chapter3ArthurVisitStep? PumpLeaving(IChapter3ArthurWorld world)
		{
			float num = _realtimeSinceStartup();
			Chapter3ArthurSnapshot snapshot;
			bool flag = TryRead(world, out snapshot) == Chapter3ArthurReadStatus.Ready && (object)snapshot != null && snapshot.Present && snapshot.Spawned;
			if (flag)
			{
				Chapter3ArthurVisitStep chapter3ArthurVisitStep = CheckAttacked(snapshot, "visit", num, world.PollArthurImpact());
				if ((object)chapter3ArthurVisitStep != null)
				{
					return chapter3ArthurVisitStep;
				}
				if (num < _walkIssuedAt + 1f)
				{
					return null;
				}
				if (snapshot.DistanceToPlayer >= 25f)
				{
					State = Chapter3ArthurVisitState.Parked;
					string reason;
					Chapter3ArthurMutationStatus value = world.TryParkArthur(out reason);
					return new Chapter3ArthurVisitStep(Chapter3ArthurVisitOutcome.Parked, new string[1] { $"reached {snapshot.DistanceToPlayer:0.0} m from the player; park {value}: {reason}" });
				}
				if (!snapshot.InPlayerView)
				{
					State = Chapter3ArthurVisitState.Parked;
					string reason2;
					Chapter3ArthurMutationStatus value2 = world.TryParkArthur(out reason2);
					return new Chapter3ArthurVisitStep(Chapter3ArthurVisitOutcome.Parked, new string[1] { $"out of the player's view; park {value2}: {reason2}" });
				}
			}
			if (num >= _leaveDeadline)
			{
				State = Chapter3ArthurVisitState.Parked;
				string reason3;
				Chapter3ArthurMutationStatus value3 = world.TryParkArthur(out reason3);
				return new Chapter3ArthurVisitStep(Chapter3ArthurVisitOutcome.Parked, new string[1] { $"leave bound expired; park {value3}: {reason3}" });
			}
			if (flag && num >= _walkIssuedAt + 1f && !snapshot.Moving && _resumesLeft > 0)
			{
				_resumesLeft--;
				string reason4;
				Chapter3ArthurMutationStatus value4 = world.TryResumeWalk(out reason4);
				return new Chapter3ArthurVisitStep(Chapter3ArthurVisitOutcome.WalkReissued, new string[1] { $"stopped {snapshot.DistanceToPlayer:0.0} m out; walk re-issue {value4}: {reason4} ({_resumesLeft} left)" });
			}
			return null;
		}

		private Chapter3ArthurVisitStep? PumpEndVisitForHq(IChapter3ArthurWorld world)
		{
			string reason;
			Chapter3ArthurMutationStatus value = world.TryParkArthur(out reason);
			string reason2;
			Chapter3ArthurMutationStatus chapter3ArthurMutationStatus = world.TryPlaceAtHq(out reason2);
			if (chapter3ArthurMutationStatus == Chapter3ArthurMutationStatus.Succeeded)
			{
				State = Chapter3ArthurVisitState.AtHq;
				_hqInteriorAbsent = false;
				_hqMaintainGate.Reset(_realtimeSinceStartup() + 0.25f);
				return new Chapter3ArthurVisitStep(Chapter3ArthurVisitOutcome.HqPlaced, new string[1] { $"visit ended: the player entered the HQ; park {value}: {reason}; place {chapter3ArthurMutationStatus}: {reason2}" });
			}
			State = Chapter3ArthurVisitState.Parked;
			_hqAttemptGate.Reset(_realtimeSinceStartup() + 1f);
			return new Chapter3ArthurVisitStep(Chapter3ArthurVisitOutcome.Parked, new string[1] { $"visit ended: the player entered the HQ; park {value}: {reason}; HQ place {chapter3ArthurMutationStatus}: {reason2}" });
		}

		private Chapter3ArthurVisitStep? PumpParkedWantHq(IChapter3ArthurWorld world)
		{
			float num = _realtimeSinceStartup();
			if (!_hqAttemptGate.TryPass(num))
			{
				return null;
			}
			if (TryRead(world, out Chapter3ArthurSnapshot snapshot) != Chapter3ArthurReadStatus.Ready || (object)snapshot == null || !snapshot.Present || !snapshot.Spawned)
			{
				return null;
			}
			if (world.TryPlaceAtHq(out string reason) != Chapter3ArthurMutationStatus.Succeeded)
			{
				return null;
			}
			State = Chapter3ArthurVisitState.AtHq;
			_hqInteriorAbsent = false;
			_hqMaintainGate.Reset(num + 0.25f);
			return new Chapter3ArthurVisitStep(Chapter3ArthurVisitOutcome.HqPlaced, new string[1] { "placed at the HQ spot: " + reason });
		}

		private Chapter3ArthurVisitStep? PumpAtHq(IChapter3ArthurWorld world)
		{
			float num = _realtimeSinceStartup();
			if (!_hqMaintainGate.TryPass(num))
			{
				return null;
			}
			if (TryRead(world, out Chapter3ArthurSnapshot snapshot) != Chapter3ArthurReadStatus.Ready || (object)snapshot == null)
			{
				return null;
			}
			if (!snapshot.Present || !snapshot.Spawned)
			{
				State = Chapter3ArthurVisitState.Parked;
				string reason;
				Chapter3ArthurMutationStatus value = world.TryParkArthur(out reason);
				return new Chapter3ArthurVisitStep(Chapter3ArthurVisitOutcome.Parked, new string[1] { $"lost the HQ contact; park {value}: {reason}" });
			}
			Chapter3ArthurVisitStep chapter3ArthurVisitStep = CheckAttacked(snapshot, "HQ", num, world.PollArthurImpact());
			if ((object)chapter3ArthurVisitStep != null)
			{
				return chapter3ArthurVisitStep;
			}
			if (world.TryPlaceAtHq(out string reason2) == Chapter3ArthurMutationStatus.Succeeded)
			{
				Chapter3ArthurVisitStep result = null;
				if (_hqInteriorAbsent)
				{
					_hqInteriorAbsent = false;
					result = new Chapter3ArthurVisitStep(Chapter3ArthurVisitOutcome.HqPlaced, new string[1] { "re-placed after the interior rebuild: " + reason2 });
				}
				if (PlayerInside() && snapshot.DistanceToPlayer <= 6f)
				{
					world.TryFacePlayerAtHq(out string _);
				}
				return result;
			}
			if (_hqInteriorAbsent)
			{
				return null;
			}
			_hqInteriorAbsent = true;
			return new Chapter3ArthurVisitStep(Chapter3ArthurVisitOutcome.HqPlaced, new string[1] { "the HQ interior is gone; holding position (" + reason2 + ")" });
		}

		private Chapter3ArthurVisitStep? CheckAttacked(Chapter3ArthurSnapshot snapshot, string context, float now, bool impactObserved)
		{
			if (float.IsNaN(snapshot.Health))
			{
				return null;
			}
			if (float.IsNaN(_attackBaseline))
			{
				_attackBaseline = snapshot.Health;
				_attackLastHealth = snapshot.Health;
				return null;
			}
			if (impactObserved)
			{
				_attackLastDropAt = now;
				_attackLastHealth = snapshot.Health;
				if (_attackIncidentOpen)
				{
					return null;
				}
				_attackIncidentOpen = true;
				return new Chapter3ArthurVisitStep(Chapter3ArthurVisitOutcome.Attacked, new string[2]
				{
					"Chapter 3 Arthur was attacked (" + context + ").",
					"Chapter 3 Arthur native reaction suppressed (ImpactReceived)."
				});
			}
			if (snapshot.Health < _attackLastHealth - 1f)
			{
				_attackLastDropAt = now;
				_attackLastHealth = snapshot.Health;
				if (_attackIncidentOpen)
				{
					return null;
				}
				_attackIncidentOpen = true;
				return new Chapter3ArthurVisitStep(Chapter3ArthurVisitOutcome.Attacked, new string[1] { "Chapter 3 Arthur was attacked (" + context + ")." });
			}
			_attackLastHealth = snapshot.Health;
			if (snapshot.Health > _attackBaseline)
			{
				_attackBaseline = snapshot.Health;
			}
			if (snapshot.Health >= _attackBaseline)
			{
				_attackIncidentOpen = false;
				return null;
			}
			if (_attackIncidentOpen && now - _attackLastDropAt >= 10f)
			{
				_attackIncidentOpen = false;
				_attackBaseline = snapshot.Health;
			}
			return null;
		}

		private bool WantHq()
		{
			if (HqForce == Chapter3ArthurHqForce.On)
			{
				return true;
			}
			if (HqForce == Chapter3ArthurHqForce.Off)
			{
				return false;
			}
			try
			{
				return HqPresence != null && HqPresence.ChapterActive && HqPresence.PlayerInsideHq;
			}
			catch
			{
				return false;
			}
		}

		private bool PlayerInside()
		{
			if (HqForce == Chapter3ArthurHqForce.On)
			{
				return true;
			}
			if (HqForce == Chapter3ArthurHqForce.Off)
			{
				return false;
			}
			try
			{
				return HqPresence != null && HqPresence.PlayerInsideHq;
			}
			catch
			{
				return false;
			}
		}

		private static Chapter3ArthurReadStatus TryRead(IChapter3ArthurWorld world, out Chapter3ArthurSnapshot? snapshot)
		{
			try
			{
				return world.TryReadArthur(out snapshot);
			}
			catch
			{
				snapshot = null;
				return Chapter3ArthurReadStatus.Faulted;
			}
		}

		private static string Truncate(string text)
		{
			if (text == null)
			{
				text = string.Empty;
			}
			if (text.Length > 160)
			{
				return text.Substring(0, 160);
			}
			return text;
		}
	}
	public interface IChapter3ArthurSpeedControl
	{
		bool TryReadSpeeds(out float moveSpeed, out float agentSpeed);

		bool TryAddBoost(float boostedSpeed, out float agentSpeedAfter);

		bool TryRemoveBoost();
	}
	public static class Chapter3ArthurWalkSpeed
	{
		public static string BeginWalk(IChapter3ArthurSpeedControl? control, bool isSpawned)
		{
			if (!isSpawned || control == null)
			{
				return string.Empty;
			}
			control.TryRemoveBoost();
			if (!control.TryReadSpeeds(out var moveSpeed, out var agentSpeed) || !IsUsableBaseline(moveSpeed))
			{
				return "walk speed left native: no usable baseline.";
			}
			float boostedSpeed = moveSpeed * 1.35f;
			if (!control.TryAddBoost(boostedSpeed, out var agentSpeedAfter))
			{
				return "walk speed left native: the boost refused.";
			}
			return $"Arthur walk speed: {agentSpeed:0.00} -> {agentSpeedAfter:0.00} m/s (x{1.35f:0.00}).";
		}

		public static void EndWalk(IChapter3ArthurSpeedControl? control, bool isSpawned)
		{
			if (isSpawned)
			{
				control?.TryRemoveBoost();
			}
		}

		public static string DescribeArrival(float distanceMetres, float elapsedSeconds)
		{
			if (elapsedSeconds > 0f)
			{
				return $"come walk averaged {distanceMetres / elapsedSeconds:0.00} m/s over {distanceMetres:0.0} m in {elapsedSeconds:0.0} s.";
			}
			return $"come walk covered {distanceMetres:0.0} m in no measurable time.";
		}

		private static bool IsUsableBaseline(float baseline)
		{
			if (float.IsFinite(baseline))
			{
				return baseline > 0f;
			}
			return false;
		}
	}
	public interface IChapter3BeatProbeWorld
	{
		bool IsHost { get; }

		bool TryReadSnapshot(out Chapter3BeatSnapshot snapshot, out string reason);

		bool TryReadInvincible(out bool on, out string reason);

		bool TrySetInvincible(bool on, out string reason);
	}
	public sealed record Chapter3BeatSlot(string Id, int Quantity);
	public sealed record Chapter3BeatSnapshot(float Health, float MaxHealth, bool IsAlive, bool IsInvincible, float Cash, float Bank, IReadOnlyList<Chapter3BeatSlot> Slots, float X, float Y, float Z, int ElapsedDays, string TimeText, string Pursuit)
	{
		public int SlotCount => Slots.Count;
	}
	public static class Chapter3BeatProbe
	{
		public const int KnockoutTimeoutSeconds = 60;

		public const int MinHurtPercent = 1;

		public const int MaxHurtPercent = 100;

		public static readonly IReadOnlyList<string> KnownTriggers = new string[4] { "Punch", "Shoot", "Nod", "GrabItem" };

		public static bool TryParsePercent(string? text, out int percent)
		{
			percent = 0;
			if (!int.TryParse(text?.Trim(), out var result))
			{
				return false;
			}
			if (result < 1 || result > 100)
			{
				return false;
			}
			percent = result;
			return true;
		}

		public static IReadOnlyList<string> DescribeSnapshot(Chapter3BeatSnapshot snapshot)
		{
			return new List<string>
			{
				$"health: {snapshot.Health:0} / {snapshot.MaxHealth:0} ({(snapshot.IsAlive ? "alive" : "dead")}, invincible {(snapshot.IsInvincible ? "on" : "off")})",
				$"cash: ${snapshot.Cash:0}, bank: ${snapshot.Bank:0}",
				DescribeSlots(snapshot.Slots),
				$"position: ({snapshot.X:0.0}, {snapshot.Y:0.0}, {snapshot.Z:0.0})",
				$"time: {snapshot.TimeText}, day {snapshot.ElapsedDays}",
				"pursuit: " + snapshot.Pursuit
			};
		}

		public static string DescribeSlots(IReadOnlyList<Chapter3BeatSlot> slots)
		{
			if (slots.Count == 0)
			{
				return "inventory: 0 slots";
			}
			string value = string.Join(", ", slots.Select((Chapter3BeatSlot slot) => $"{slot.Id} x{slot.Quantity}"));
			return $"inventory: {slots.Count} slots ({value})";
		}

		public static IReadOnlyList<string> DescribeDiff(Chapter3BeatSnapshot before, Chapter3BeatSnapshot after, bool billShown, bool timedOut)
		{
			int value = after.ElapsedDays - before.ElapsedDays;
			float value2 = after.Cash - before.Cash;
			float value3 = after.Bank - before.Bank;
			return new string[7]
			{
				timedOut ? $"knockout timed out after {60} s with no revive." : "knockout complete: the player revived through the native flow.",
				$"woke at ({after.X:0.0}, {after.Y:0.0}, {after.Z:0.0}) from ({before.X:0.0}, {before.Y:0.0}, {before.Z:0.0}).",
				$"time {before.TimeText} day {before.ElapsedDays} -> {after.TimeText} day {after.ElapsedDays} ({value:+0;-0;+0} days).",
				$"cash ${before.Cash:0} -> ${after.Cash:0} ({value2:+0;-0;+0}), bank ${before.Bank:0} -> ${after.Bank:0} ({value3:+0;-0;+0}).",
				"inventory: " + DescribeInventoryChange(before.Slots, after.Slots),
				$"health after: {after.Health:0} / {after.MaxHealth:0} ({(after.IsAlive ? "alive" : "dead")}).",
				"bill screen showed: " + (billShown ? "yes" : "no") + "."
			};
		}

		public static string DescribeInventoryChange(IReadOnlyList<Chapter3BeatSlot> before, IReadOnlyList<Chapter3BeatSlot> after)
		{
			Dictionary<string, int> dictionary = (from slot in before
				group slot by slot.Id).ToDictionary((IGrouping<string, Chapter3BeatSlot> group) => group.Key, (IGrouping<string, Chapter3BeatSlot> group) => group.Sum((Chapter3BeatSlot slot) => slot.Quantity));
			Dictionary<string, int> dictionary2 = (from slot in after
				group slot by slot.Id).ToDictionary((IGrouping<string, Chapter3BeatSlot> group) => group.Key, (IGrouping<string, Chapter3BeatSlot> group) => group.Sum((Chapter3BeatSlot slot) => slot.Quantity));
			List<string> list = new List<string>();
			foreach (string item in dictionary.Keys.Union(dictionary2.Keys).OrderBy<string, string>((string id) => id, StringComparer.Ordinal))
			{
				dictionary.TryGetValue(item, out var value);
				dictionary2.TryGetValue(item, out var value2);
				if (value != value2)
				{
					list.Add($"{item} {value} -> {value2}");
				}
			}
			if (list.Count != 0)
			{
				return $"{before.Count} -> {after.Count} slots ({string.Join(", ", list)})";
			}
			return $"{before.Count} slots, unchanged";
		}
	}
	public sealed class Chapter3BeatInvincibleProbe
	{
		private readonly IChapter3BeatProbeWorld _world;

		private bool _setByProbe;

		public Chapter3BeatInvincibleProbe(IChapter3BeatProbeWorld world)
		{
			_world = world ?? throw new ArgumentNullException("world");
		}

		public IReadOnlyList<string> TurnOn()
		{
			if (_world.TryReadInvincible(out bool on, out string reason))
			{
				if (!on)
				{
					if (_world.TrySetInvincible(on: true, out reason))
					{
						_setByProbe = true;
						return new string[1] { "Chapter 3 QA beat probe invincible: on." };
					}
					return new string[1] { "Chapter 3 QA beat probe invincible refused: " + reason };
				}
				return new string[1] { "Chapter 3 QA beat probe invincible: already on, left as found; this probe will not turn it off." };
			}
			return new string[1] { "Chapter 3 QA beat probe invincible refused: " + reason };
		}

		public IReadOnlyList<string> TurnOff()
		{
			if (!_setByProbe)
			{
				if (_world.TryReadInvincible(out bool on, out string reason))
				{
					if (on)
					{
						return new string[1] { "Chapter 3 QA beat probe invincible refused: on, but not by this probe; left on." };
					}
					return new string[1] { "Chapter 3 QA beat probe invincible: already off." };
				}
				return new string[1] { "Chapter 3 QA beat probe invincible refused: " + reason };
			}
			if (_world.TrySetInvincible(on: false, out string reason2))
			{
				_setByProbe = false;
				return new string[1] { "Chapter 3 QA beat probe invincible: off, restored." };
			}
			return new string[1] { "Chapter 3 QA beat probe invincible refused: " + reason2 };
		}
	}
	public enum Chapter3BindState
	{
		Binding,
		Bound
	}
	public sealed record Chapter3CheckpointOfficerEntry(int RosterHandle, Chapter3BindState BindState, string ActiveBehaviour, double? DistanceM);
	public sealed record Chapter3CheckpointStatusEntry(string Label, string? WorldHandle, bool Spawned, IReadOnlyList<Chapter3CheckpointOfficerEntry> Officers);
	public sealed record Chapter3CheckpointSnapshot(LocalPressureTier? Tier, bool Protected, Chapter3CheckpointTarget Target, IReadOnlyList<string> ActiveLabels, IReadOnlyList<Chapter3CheckpointStatusEntry> Managed, IReadOnlyList<Chapter3CheckpointStatusEntry> Tests, string? AssertedNative);
	public interface IChapter3CheckpointHost
	{
		Chapter3State? State { get; }

		Chapter3CheckpointTarget ReadCheckpointTarget();

		bool TryWriteCheckpointTarget(Chapter3CheckpointTarget target);
	}
	public sealed class Chapter3CheckpointService : IDisposable
	{
		private sealed class ManagedCheckpoint
		{
			public string Label { get; set; } = string.Empty;

			public string WorldHandle { get; set; } = string.Empty;

			public Chapter3CheckpointSpot Spot { get; set; } = new Chapter3CheckpointSpot(string.Empty, 0f, 0f, 0f, 0f);

			public string OwnerPrefix { get; set; } = "checkpoint";

			public int[] OfficerHandles { get; set; } = new int[2] { -1, -1 };

			public Chapter3BindState[] OfficerBindState { get; set; } = new Chapter3BindState[2];

			public string[] OfficerActiveName { get; set; } = new string[2] { "unknown", "unknown" };

			public double?[] OfficerDistanceM { get; set; } = new double?[2];

			public double?[] BindStartMinutes { get; set; } = new double?[2];

			public IReadOnlyList<Chapter3StandPoint>? StandPoints { get; set; }
		}

		private const double PickHourMinutes = 360.0;

		internal const int OfficersPerCheckpoint = 2;

		private const int NoHandle = -1;

		private const string ManagedOwnerPrefix = "checkpoint";

		private const string TestOwnerPrefix = "checkpoint-test";

		private const double BindNearMeters = 3.0;

		private const double BindTimeoutGameMinutes = 20.0;

		private readonly IChapter3CheckpointHost _runtime;

		private readonly Release1ChiefService _chief;

		private readonly IProductionActivityMissionWorld _world;

		private readonly IChapter3CheckpointWorld _checkpoints;

		private readonly OcOfficerRosterService _roster;

		private readonly Action<string> _log;

		private readonly GameHourGate _throttle = new GameHourGate();

		private readonly Dictionary<string, ManagedCheckpoint> _managed = new Dictionary<string, ManagedCheckpoint>(StringComparer.Ordinal);

		private readonly Dictionary<string, ManagedCheckpoint> _tests = new Dictionary<string, ManagedCheckpoint>(StringComparer.Ordinal);

		private readonly OnceLog _warned;

		private IReadOnlyList<string> _activeLabels = Array.Empty<string>();

		private double? _lastStructuralMinute;

		private string? _assertedNative;

		private bool _needsPostLoadPick;

		private bool _disposed;

		public Chapter3CheckpointService(IChapter3CheckpointHost runtime, Release1ChiefService chief, IProductionActivityMissionWorld world, IChapter3CheckpointWorld checkpoints, OcOfficerRosterService roster, Action<string>? log = null)
		{
			_runtime = runtime ?? throw new ArgumentNullException("runtime");
			_chief = chief ?? throw new ArgumentNullException("chief");
			_world = world ?? throw new ArgumentNullException("world");
			_checkpoints = checkpoints ?? throw new ArgumentNullException("checkpoints");
			_roster = roster ?? throw new ArgumentNullException("roster");
			_log = log ?? ((Action<string>)delegate
			{
			});
			_warned = new OnceLog(_log);
		}

		public void Update()
		{
			if (_disposed || !IsHost())
			{
				return;
			}
			double totalMinutes;
			double? num = ((_world.TryReadCanonicalTotalMinutes(out totalMinutes) == Release1SmallCourtesyWorldReadStatus.Ready) ? new double?(totalMinutes) : ((double?)null));
			if (!_throttle.TryPass(num, _runtime.State?.Revision ?? (-1)))
			{
				return;
			}
			int? obj;
			if (num.HasValue)
			{
				double valueOrDefault = num.GetValueOrDefault();
				obj = (int)Math.Floor(valueOrDefault / 1440.0);
			}
			else
			{
				obj = null;
			}
			int? today = obj;
			MaybePick(num, today);
			Reconcile(num);
			foreach (ManagedCheckpoint value in _tests.Values)
			{
				EnsureOfficers(value, num);
			}
		}

		public void OnSaveStart()
		{
			if (!_disposed)
			{
				_throttle.Clear();
			}
		}

		public void OnSaveComplete()
		{
			if (!_disposed)
			{
				_throttle.Clear();
				MarkBindsStale(_managed);
				MarkBindsStale(_tests);
			}
		}

		private static void MarkBindsStale(Dictionary<string, ManagedCheckpoint> set)
		{
			foreach (ManagedCheckpoint value in set.Values)
			{
				for (int i = 0; i < 2; i++)
				{
					value.OfficerBindState[i] = Chapter3BindState.Binding;
					value.BindStartMinutes[i] = null;
					value.OfficerActiveName[i] = "unknown";
					value.OfficerDistanceM[i] = null;
				}
			}
		}

		public void OnPreLoad()
		{
			if (!_disposed)
			{
				ClearLocal();
			}
		}

		public void OnLoadComplete()
		{
			if (!_disposed)
			{
				_throttle.Clear();
				_needsPostLoadPick = true;
			}
		}

		public void Dispose()
		{
			if (!_disposed)
			{
				_disposed = true;
				ClearLocal();
			}
		}

		public Chapter3QaResult QaSpawnTest(string label)
		{
			if (_disposed)
			{
				return new Chapter3QaResult(Ok: false, "Chapter 3 QA checkpoint test refused: Chapter 3 is not active.");
			}
			if (string.IsNullOrWhiteSpace(label))
			{
				return new Chapter3QaResult(Ok: false, "Chapter 3 QA checkpoint test refused: a label is required.");
			}
			if (!IsHost())
			{
				return new Chapter3QaResult(Ok: false, "Chapter 3 QA checkpoint test refused: not host.");
			}
			Chapter3CheckpointSpot chapter3CheckpointSpot = Chapter3CheckpointSpots.Baked.FirstOrDefault((Chapter3CheckpointSpot entry) => string.Equals(entry.Label, label, StringComparison.Ordinal));
			if ((object)chapter3CheckpointSpot == null)
			{
				return new Chapter3QaResult(Ok: false, "Chapter 3 QA checkpoint test refused: unknown spot '" + label + "'.");
			}
			if (_tests.ContainsKey(label))
			{
				return new Chapter3QaResult(Ok: false, "Chapter 3 QA checkpoint test refused: a test checkpoint '" + label + "' already exists.");
			}
			if (!TrySpawnInto(_tests, "checkpoint-test", label, chapter3CheckpointSpot))
			{
				return new Chapter3QaResult(Ok: false, "Chapter 3 QA checkpoint test refused: the spawn failed for '" + label + "'.");
			}
			return new Chapter3QaResult(Ok: true, "Test checkpoint spawned: " + label + ".");
		}

		public Chapter3QaResult QaSpawnTestAt(string label, float x, float y, float z, float yawDegrees)
		{
			if (_disposed)
			{
				return new Chapter3QaResult(Ok: false, "Chapter 3 QA checkpoint test refused: Chapter 3 is not active.");
			}
			if (string.IsNullOrWhiteSpace(label))
			{
				return new Chapter3QaResult(Ok: false, "Chapter 3 QA checkpoint test refused: a label is required.");
			}
			if (!IsHost())
			{
				return new Chapter3QaResult(Ok: false, "Chapter 3 QA checkpoint test refused: not host.");
			}
			if (_tests.ContainsKey(label))
			{
				return new Chapter3QaResult(Ok: false, "Chapter 3 QA checkpoint test refused: a test checkpoint '" + label + "' already exists.");
			}
			if (!TrySpawnInto(_tests, "checkpoint-test", label, new Chapter3CheckpointSpot(label, x, y, z, yawDegrees)))
			{
				return new Chapter3QaResult(Ok: false, "Chapter 3 QA checkpoint test refused: the spawn failed for '" + label + "'.");
			}
			return new Chapter3QaResult(Ok: true, "Test checkpoint spawned: " + label + ".");
		}

		public Chapter3QaResult QaSpotHere(string label)
		{
			if (_disposed)
			{
				return new Chapter3QaResult(Ok: false, "Chapter 3 QA checkpoint spot here refused: Chapter 3 is not active.");
			}
			if (string.IsNullOrWhiteSpace(label))
			{
				return new Chapter3QaResult(Ok: false, "Chapter 3 QA checkpoint spot here refused: a label is required.");
			}
			if (!IsHost())
			{
				return new Chapter3QaResult(Ok: false, "Chapter 3 QA checkpoint spot here refused: not host.");
			}
			if (TryReadCameraPose(out Chapter3CameraPose pose) != Chapter3CheckpointWorldStatus.Ok)
			{
				return new Chapter3QaResult(Ok: false, "Chapter 3 QA checkpoint spot here refused: the camera pose could not be read.");
			}
			string text = string.Format(CultureInfo.InvariantCulture, "new Chapter3CheckpointSpot(\"{0}\", {1:F2}f, {2:F2}f, {3:F2}f, {4:F2}f),", label, pose.X, pose.Y, pose.Z, pose.YawDegrees);
			Chapter3QaResult chapter3QaResult = QaSpawnTestAt(label, pose.X, pose.Y, pose.Z, pose.YawDegrees);
			return new Chapter3QaResult(chapter3QaResult.Ok, chapter3QaResult.Ok ? (text + " Test checkpoint spawned: " + label + ".") : (text + " Test checkpoint spawn failed: " + chapter3QaResult.Message));
		}

		public Chapter3QaResult QaClearTests()
		{
			if (_disposed)
			{
				return new Chapter3QaResult(Ok: false, "Chapter 3 QA checkpoint clear refused: Chapter 3 is not active.");
			}
			int num = 0;
			List<string> list = new List<string>();
			foreach (string item in _tests.Keys.OrderBy<string, string>((string label) => label, StringComparer.Ordinal).ToList())
			{
				if (TryRemoveFrom(_tests, item))
				{
					num++;
				}
				else
				{
					list.Add(item);
				}
			}
			if (list.Count != 0)
			{
				return new Chapter3QaResult(Ok: false, "Chapter 3 QA checkpoint clear refused: " + string.Join(", ", list) + " could not be removed.");
			}
			return new Chapter3QaResult(Ok: true, $"Cleared {num} test checkpoint(s).");
		}

		public Chapter3QaResult QaPickNow()
		{
			if (_disposed)
			{
				return new Chapter3QaResult(Ok: false, "Chapter 3 QA checkpoint pick refused: Chapter 3 is not active.");
			}
			if (!IsHost())
			{
				return new Chapter3QaResult(Ok: false, "Chapter 3 QA checkpoint pick refused: not host.");
			}
			if (_world.TryReadCanonicalTotalMinutes(out var totalMinutes) != Release1SmallCourtesyWorldReadStatus.Ready)
			{
				return new Chapter3QaResult(Ok: false, "Chapter 3 QA checkpoint pick refused: the clock could not be read.");
			}
			return PickCore((int)Math.Floor(totalMinutes / 1440.0));
		}

		public IReadOnlyList<string> QaStatus()
		{
			try
			{
				return QaStatusCore();
			}
			catch (Exception ex)
			{
				return new string[1] { "checkpoint status unavailable: " + ex.GetType().Name + "." };
			}
		}

		public Chapter3CheckpointSnapshot Snapshot()
		{
			if (_disposed)
			{
				return new Chapter3CheckpointSnapshot(null, Protected: false, new Chapter3CheckpointTarget(null, null), Array.Empty<string>(), Array.Empty<Chapter3CheckpointStatusEntry>(), Array.Empty<Chapter3CheckpointStatusEntry>(), null);
			}
			return new Chapter3CheckpointSnapshot(_chief.ReadTier(), _chief.IsProtected(), _runtime.ReadCheckpointTarget(), _activeLabels, StatusEntries(_managed), StatusEntries(_tests), _assertedNative);
		}

		private IReadOnlyList<string> QaStatusCore()
		{
			if (_disposed)
			{
				return new string[1] { "checkpoints: the service is disposed." };
			}
			Chapter3CheckpointSnapshot chapter3CheckpointSnapshot = Snapshot();
			string value = chapter3CheckpointSnapshot.Target.PropertyCode ?? "none";
			int? pickDay = chapter3CheckpointSnapshot.Target.PickDay;
			object obj;
			if (pickDay.HasValue)
			{
				int valueOrDefault = pickDay.GetValueOrDefault();
				obj = $" (day {valueOrDefault})";
			}
			else
			{
				obj = string.Empty;
			}
			string value2 = (string)obj;
			List<string> list = new List<string>
			{
				$"checkpoints: tier {chapter3CheckpointSnapshot.Tier?.ToString() ?? "unknown"}, protected {(chapter3CheckpointSnapshot.Protected ? "yes" : "no")}, target {value}{value2}.",
				"checkpoints: active " + ((chapter3CheckpointSnapshot.ActiveLabels.Count == 0) ? "none" : string.Join(", ", chapter3CheckpointSnapshot.ActiveLabels)) + "."
			};
			foreach (Chapter3CheckpointStatusEntry item in chapter3CheckpointSnapshot.Managed)
			{
				list.AddRange(DescribeEntry(item, test: false));
				list.AddRange(DescribeOfficerDiagnostics(item));
			}
			foreach (Chapter3CheckpointStatusEntry test in chapter3CheckpointSnapshot.Tests)
			{
				list.AddRange(DescribeEntry(test, test: true));
				list.AddRange(DescribeOfficerDiagnostics(test));
			}
			list.Add((chapter3CheckpointSnapshot.AssertedNative == null) ? "checkpoints: no native asserted." : ("checkpoints: native " + chapter3CheckpointSnapshot.AssertedNative + " asserted."));
			if (chapter3CheckpointSnapshot.AssertedNative != null && _roster.TryReadNativeLeak(chapter3CheckpointSnapshot.AssertedNative, out var leaked))
			{
				if (leaked)
				{
					WarnOnce("native-leak-" + chapter3CheckpointSnapshot.AssertedNative, "Checkpoint native " + chapter3CheckpointSnapshot.AssertedNative + " lists an OC clone in its AssignedNPCs.");
					list.Add("checkpoints: native " + chapter3CheckpointSnapshot.AssertedNative + " lists an OC clone!");
				}
				else
				{
					ClearWarn("native-leak-" + chapter3CheckpointSnapshot.AssertedNative);
				}
			}
			return list;
		}

		private static IEnumerable<string> DescribeEntry(Chapter3CheckpointStatusEntry entry, bool test)
		{
			int count = entry.Officers.Count;
			int value = entry.Officers.Count((Chapter3CheckpointOfficerEntry officer) => officer.BindState == Chapter3BindState.Bound);
			string value2 = (test ? " (test)" : string.Empty);
			yield return $"checkpoint {entry.Label}{value2}: {(entry.Spawned ? "spawned" : "missing")}, officers {count} held, {value} bound.";
			foreach (Chapter3CheckpointOfficerEntry officer in entry.Officers)
			{
				double? distanceM = officer.DistanceM;
				string value3 = ((!distanceM.HasValue) ? "distance unknown" : (distanceM.GetValueOrDefault().ToString("F1", CultureInfo.InvariantCulture) + " m from stand"));
				yield return $"checkpoint {entry.Label} officer {officer.RosterHandle}: {officer.BindState}, active {officer.ActiveBehaviour}, {value3}.";
			}
		}

		private IEnumerable<string> DescribeOfficerDiagnostics(Chapter3CheckpointStatusEntry entry)
		{
			if (entry.WorldHandle == null || TryReadSpawnedNative(entry.WorldHandle, out object native) != Chapter3CheckpointWorldStatus.Ok || native == null)
			{
				yield break;
			}
			foreach (Chapter3CheckpointOfficerEntry officer in entry.Officers)
			{
				if (officer.RosterHandle != -1 && _roster.TryReadBehaviourDiagnostics(officer.RosterHandle, native, out OcOfficerBehaviourDiagnostics diagnostics))
				{
					string value = ((diagnostics.EnabledTopFirst.Count == 0) ? "none" : string.Join(", ", diagnostics.EnabledTopFirst.Select((OcOfficerBehaviourInfo info) => $"{info.Name} p{info.Priority}")));
					yield return $"checkpoint {entry.Label} officer {officer.RosterHandle} stack: {value}; active {diagnostics.ActiveName}.";
					string value2 = diagnostics.Checkpoint.Kind switch
					{
						OcCheckpointKind.Ours => "OC", 
						OcCheckpointKind.Native => "native", 
						OcCheckpointKind.None => "none", 
						_ => "unknown", 
					};
					yield return $"checkpoint {entry.Label} officer {officer.RosterHandle} checkpoint: enabled {diagnostics.Checkpoint.Enabled}, active {diagnostics.Checkpoint.Active}, assigned {diagnostics.Checkpoint.Assigned}, target {value2}.";
					diagnostics = null;
				}
			}
		}

		private static IReadOnlyList<Chapter3CheckpointStatusEntry> StatusEntries(Dictionary<string, ManagedCheckpoint> set)
		{
			return (from entry in set.Values.OrderBy<ManagedCheckpoint, string>((ManagedCheckpoint entry) => entry.Label, StringComparer.Ordinal)
				select new Chapter3CheckpointStatusEntry(entry.Label, entry.WorldHandle, Spawned: true, HeldOfficers(entry))).ToList();
		}

		private void MaybePick(double? minutes, int? today)
		{
			if (!today.HasValue || !minutes.HasValue)
			{
				return;
			}
			if (_runtime.ReadCheckpointTarget().PickDay == today)
			{
				_needsPostLoadPick = false;
			}
			else if (_needsPostLoadPick || !(minutes.Value - (double)today.Value * 1440.0 < 360.0))
			{
				Chapter3QaResult chapter3QaResult = PickCore(today.Value);
				if (chapter3QaResult.Ok)
				{
					_needsPostLoadPick = false;
					_log(chapter3QaResult.Message);
				}
			}
		}

		private Chapter3QaResult PickCore(int today)
		{
			if (_world.TryReadProductionActivity(out Release1ProductionActivitySnapshot activity) != Release1SmallCourtesyWorldReadStatus.Ready)
			{
				WarnOnce("pick-snapshot", "Checkpoint pick skipped: the production snapshot could not be read.");
				return new Chapter3QaResult(Ok: false, "Checkpoint pick skipped: the production snapshot could not be read.");
			}
			string lastVisitedCode = null;
			if (TryReadLastVisited(out string propertyCode) != Chapter3CheckpointWorldStatus.Ok || propertyCode == null)
			{
				WarnOnce("pick-lastvisited", "Checkpoint pick runs without the last-visited property; ties fall back to code order.");
			}
			else
			{
				lastVisitedCode = propertyCode;
			}
			string text = Chapter3CheckpointPlanner.PickTarget((from property in activity.Properties
				where (object)property != null
				select new Chapter3CheckpointScoredProperty(property.PropertyCode, property.Employees.Count, property.Stations.Count)).ToList(), lastVisitedCode);
			if (!_runtime.TryWriteCheckpointTarget(new Chapter3CheckpointTarget(text, today)))
			{
				WarnOnce("pick-write", "Checkpoint pick could not be recorded.");
				return new Chapter3QaResult(Ok: false, "Checkpoint pick could not be recorded.");
			}
			ClearWarn("pick-snapshot");
			ClearWarn("pick-write");
			if (text != null)
			{
				return new Chapter3QaResult(Ok: true, $"Checkpoint target picked: {text} (day {today}).");
			}
			return new Chapter3QaResult(Ok: true, $"Checkpoint pick day {today}: no owned property.");
		}

		private void Reconcile(double? minutes)
		{
			LocalPressureTier? localPressureTier = _chief.ReadTier();
			if (!localPressureTier.HasValue)
			{
				return;
			}
			Chapter3CheckpointActiveSet desired;
			if (!_chief.IsProtected() && (localPressureTier == LocalPressureTier.Watched || localPressureTier == LocalPressureTier.Critical))
			{
				Chapter3CheckpointTarget chapter3CheckpointTarget = _runtime.ReadCheckpointTarget();
				if (chapter3CheckpointTarget.PropertyCode == null)
				{
					desired = new Chapter3CheckpointActiveSet(Array.Empty<string>(), null);
				}
				else
				{
					if (!TryResolveTargetPosition(chapter3CheckpointTarget.PropertyCode, out var targetX, out var targetZ))
					{
						return;
					}
					List<Chapter3CheckpointNativeSite> list = new List<Chapter3CheckpointNativeSite>();
					if (TryReadNativePositions(out IReadOnlyList<Chapter3NativeCheckpointPosition> positions) != Chapter3CheckpointWorldStatus.Ok)
					{
						WarnOnce("reconcile-natives", "Checkpoint reconcile runs without native positions; no native is asserted.");
					}
					else
					{
						list.AddRange(from site in positions
							where (object)site != null
							select new Chapter3CheckpointNativeSite(site.Location, site.X, site.Z));
					}
					desired = Chapter3CheckpointPlanner.ActiveSet(targetX, targetZ, localPressureTier.Value, isProtected: false, Chapter3CheckpointSpots.Baked, list);
				}
			}
			else
			{
				desired = new Chapter3CheckpointActiveSet(Array.Empty<string>(), null);
			}
			_activeLabels = desired.OcLabels;
			AssertNative(desired.NativeLabel);
			double? obj;
			if (minutes.HasValue)
			{
				double valueOrDefault = minutes.GetValueOrDefault();
				obj = Math.Floor(valueOrDefault);
			}
			else
			{
				obj = null;
			}
			double? num = obj;
			if (!num.HasValue || _lastStructuralMinute != num)
			{
				bool flag = false;
				foreach (string ocLabel in desired.OcLabels)
				{
					if (!_managed.ContainsKey(ocLabel))
					{
						if (TrySpawnManaged(ocLabel))
						{
							_lastStructuralMinute = num;
						}
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					using List<string>.Enumerator enumerator2 = _managed.Keys.Where((string label) => !desired.OcLabels.Contains<string>(label, StringComparer.Ordinal)).OrderBy<string, string>((string label) => label, StringComparer.Ordinal).ToList()
						.GetEnumerator();
					if (enumerator2.MoveNext())
					{
						string current2 = enumerator2.Current;
						if (TryDespawnManaged(current2))
						{
							_lastStructuralMinute = num;
						}
					}
				}
			}
			foreach (ManagedCheckpoint value in _managed.Values)
			{
				EnsureOfficers(value, minutes);
			}
		}

		private void AssertNative(string? label)
		{
			if (label == null)
			{
				_assertedNative = null;
				return;
			}
			if (TrySetNative(label, enabled: true) != Chapter3CheckpointWorldStatus.Ok)
			{
				WarnOnce("native-" + label, "Checkpoint native assert failed for " + label + ".");
			}
			else
			{
				ClearWarn("native-" + label);
			}
			_assertedNative = label;
		}

		private bool TrySpawnManaged(string label)
		{
			Chapter3CheckpointSpot chapter3CheckpointSpot = Chapter3CheckpointSpots.Baked.FirstOrDefault((Chapter3CheckpointSpot entry) => string.Equals(entry.Label, label, StringComparison.Ordinal));
			if ((object)chapter3CheckpointSpot == null)
			{
				return false;
			}
			return TrySpawnInto(_managed, "checkpoint", label, chapter3CheckpointSpot);
		}

		private bool TrySpawnInto(Dictionary<string, ManagedCheckpoint> set, string ownerPrefix, string label, Chapter3CheckpointSpot spot)
		{
			if (TrySpawn(label, spot, out string handle) != Chapter3CheckpointWorldStatus.Ok || string.IsNullOrEmpty(handle))
			{
				WarnOnce("spawn-" + label, "Checkpoint spawn failed for " + label + ".");
				return false;
			}
			ClearWarn("spawn-" + label);
			set[label] = new ManagedCheckpoint
			{
				Label = label,
				WorldHandle = handle,
				Spot = spot,
				OwnerPrefix = ownerPrefix,
				OfficerHandles = new int[2] { -1, -1 }
			};
			return true;
		}

		private bool TryDespawnManaged(string label)
		{
			return TryRemoveFrom(_managed, label);
		}

		private bool TryRemoveFrom(Dictionary<string, ManagedCheckpoint> set, string label)
		{
			if (!set.TryGetValue(label, out ManagedCheckpoint value))
			{
				return true;
			}
			ReleaseOfficers(value);
			if (TryDespawn(value.WorldHandle) != Chapter3CheckpointWorldStatus.Ok)
			{
				WarnOnce("despawn-" + label, "Checkpoint despawn failed for " + label + ".");
				return false;
			}
			ClearWarn("despawn-" + label);
			set.Remove(label);
			return true;
		}

		private void ReleaseOfficers(ManagedCheckpoint managed)
		{
			for (int i = 0; i < managed.OfficerHandles.Length; i++)
			{
				if (managed.OfficerHandles[i] != -1)
				{
					_roster.Release(managed.OfficerHandles[i]);
				}
				managed.OfficerHandles[i] = -1;
				managed.OfficerBindState[i] = Chapter3BindState.Binding;
				managed.OfficerActiveName[i] = "unknown";
				managed.OfficerDistanceM[i] = null;
				managed.BindStartMinutes[i] = null;
			}
		}

		private void EnsureOfficers(ManagedCheckpoint managed, double? minutes)
		{
			if (managed.StandPoints == null)
			{
				if (TryReadStandPoints(managed.WorldHandle, out IReadOnlyList<Chapter3StandPoint> points) != Chapter3CheckpointWorldStatus.Ok || points.Count == 0)
				{
					WarnOnce("standpoints-" + managed.Label, "Checkpoint " + managed.Label + ": stand points unreadable; officers wait.");
					return;
				}
				ClearWarn("standpoints-" + managed.Label);
				managed.StandPoints = points;
			}
			int i;
			for (i = 0; i < 2; i++)
			{
				Chapter3StandPoint chapter3StandPoint = managed.StandPoints[i % managed.StandPoints.Count];
				OcOfficerPosition ocOfficerPosition = new OcOfficerPosition(chapter3StandPoint.X, chapter3StandPoint.Y, chapter3StandPoint.Z, managed.Spot.YawDegrees);
				if (managed.OfficerHandles[i] != -1 && !_roster.Snapshot().Any((OcOfficerSlotSnapshot slot) => slot.Handle == managed.OfficerHandles[i] && slot.OwnerKey == $"{managed.OwnerPrefix}:{managed.Label}:{i}"))
				{
					managed.OfficerHandles[i] = -1;
					managed.OfficerBindState[i] = Chapter3BindState.Binding;
					managed.BindStartMinutes[i] = null;
					managed.OfficerActiveName[i] = "unknown";
					managed.OfficerDistanceM[i] = null;
				}
				if (managed.OfficerHandles[i] == -1)
				{
					int handle;
					OcOfficerRequestStatus ocOfficerRequestStatus = _roster.TryRequest($"{managed.OwnerPrefix}:{managed.Label}:{i}", ocOfficerPosition, out handle);
					if (ocOfficerRequestStatus != OcOfficerRequestStatus.Accepted)
					{
						WarnOnce("officers-" + managed.Label, $"Checkpoint {managed.Label}: officer request refused ({ocOfficerRequestStatus}).");
						break;
					}
					ClearWarn("officers-" + managed.Label);
					managed.OfficerHandles[i] = handle;
				}
				if (managed.OfficerBindState[i] == Chapter3BindState.Bound)
				{
					continue;
				}
				if (TryReadSpawnedNative(managed.WorldHandle, out object native) != Chapter3CheckpointWorldStatus.Ok || native == null)
				{
					WarnOnce("bind-" + managed.Label, "Checkpoint " + managed.Label + ": the spawned checkpoint could not be read for binding.");
					continue;
				}
				OcOfficerBindStatus ocOfficerBindStatus = _roster.TryBindToCheckpoint(managed.OfficerHandles[i], native, ocOfficerPosition);
				double? num;
				switch (ocOfficerBindStatus)
				{
				case OcOfficerBindStatus.Bound:
				{
					ref double? reference = ref managed.BindStartMinutes[i];
					num = reference;
					if (!num.HasValue)
					{
						reference = minutes;
					}
					ClearWarn("bind-" + managed.Label);
					break;
				}
				default:
					WarnOnce("bind-" + managed.Label, $"Checkpoint {managed.Label}: officer bind failed ({ocOfficerBindStatus}).");
					break;
				case OcOfficerBindStatus.SlotNotActive:
					break;
				}
				string activeBehaviour;
				bool checkpointActive;
				bool flag = _roster.TryReadBehaviourState(managed.OfficerHandles[i], out activeBehaviour, out checkpointActive);
				if (flag)
				{
					managed.OfficerActiveName[i] = activeBehaviour;
				}
				OcOfficerBoundState state;
				bool flag2 = _roster.TryReadBoundState(managed.OfficerHandles[i], native, out state);
				bool flag3 = flag2 && state.CheckpointKind == OcCheckpointKind.Ours;
				double?[] officerDistanceM;
				int num2;
				double value;
				if (_roster.TryReadClonePosition(managed.OfficerHandles[i], out var position))
				{
					officerDistanceM = managed.OfficerDistanceM;
					num2 = i;
					if (flag2)
					{
						OcOfficerPosition? standPoint = state.StandPoint;
						if (standPoint.HasValue)
						{
							value = DistanceM(stand: standPoint.GetValueOrDefault(), clone: position);
							goto IL_04fd;
						}
					}
					value = DistanceM(position, chapter3StandPoint);
					goto IL_04fd;
				}
				goto IL_0507;
				IL_0507:
				if (flag2 && state.CheckpointKind == OcCheckpointKind.Native)
				{
					WarnOnce($"native-leak-{managed.Label}-{i}", $"Checkpoint {managed.Label} officer {i} sits on a native checkpoint.");
				}
				if (flag2 && state.CheckpointEnabled && flag && !checkpointActive && !string.IsNullOrWhiteSpace(activeBehaviour) && !activeBehaviour.Contains("checkpoint", StringComparison.OrdinalIgnoreCase))
				{
					WarnOnce($"priority-{managed.Label}-{i}", $"Checkpoint {managed.Label} officer {i}: checkpoint enabled but {activeBehaviour} outranks the checkpoint.");
				}
				if (flag && checkpointActive && flag3)
				{
					num = managed.OfficerDistanceM[i];
					if (num.HasValue)
					{
						double valueOrDefault = num.GetValueOrDefault();
						if (valueOrDefault <= 3.0)
						{
							managed.OfficerBindState[i] = Chapter3BindState.Bound;
							ClearWarn($"timeout-{managed.Label}-{i}");
							ClearWarn($"priority-{managed.Label}-{i}");
							ClearWarn($"native-leak-{managed.Label}-{i}");
							continue;
						}
					}
				}
				num = managed.BindStartMinutes[i];
				if (!num.HasValue)
				{
					continue;
				}
				double valueOrDefault2 = num.GetValueOrDefault();
				if (minutes.HasValue)
				{
					double valueOrDefault3 = minutes.GetValueOrDefault();
					if (valueOrDefault3 - valueOrDefault2 >= 20.0)
					{
						WarnOnce($"timeout-{managed.Label}-{i}", $"Checkpoint {managed.Label} officer {i}: bind timed out; re-binding.");
						managed.BindStartMinutes[i] = valueOrDefault3;
					}
				}
				continue;
				IL_04fd:
				officerDistanceM[num2] = value;
				goto IL_0507;
			}
		}

		private bool TryResolveTargetPosition(string code, out float targetX, out float targetZ)
		{
			targetX = 0f;
			targetZ = 0f;
			if (TryReadOwnedPositions(out IReadOnlyList<Chapter3OwnedPropertyPosition> positions) != Chapter3CheckpointWorldStatus.Ok)
			{
				WarnOnce("reconcile-positions", "Checkpoint reconcile skipped: owned property positions could not be read.");
				return false;
			}
			Chapter3OwnedPropertyPosition chapter3OwnedPropertyPosition = positions.FirstOrDefault((Chapter3OwnedPropertyPosition entry) => (object)entry != null && string.Equals(entry.PropertyCode, code, StringComparison.Ordinal));
			if ((object)chapter3OwnedPropertyPosition == null)
			{
				WarnOnce("target-missing-" + code, "Checkpoint reconcile skipped: the target " + code + " has no world position.");
				return false;
			}
			ClearWarn("reconcile-positions");
			ClearWarn("target-missing-" + code);
			targetX = chapter3OwnedPropertyPosition.X;
			targetZ = chapter3OwnedPropertyPosition.Z;
			return true;
		}

		private void ClearLocal()
		{
			_managed.Clear();
			_tests.Clear();
			_warned.ClearAll();
			_throttle.Clear();
			_activeLabels = Array.Empty<string>();
			_lastStructuralMinute = null;
			_assertedNative = null;
			_needsPostLoadPick = false;
		}

		private static IReadOnlyList<Chapter3CheckpointOfficerEntry> HeldOfficers(ManagedCheckpoint managed)
		{
			List<Chapter3CheckpointOfficerEntry> list = new List<Chapter3CheckpointOfficerEntry>(2);
			for (int i = 0; i < 2; i++)
			{
				if (managed.OfficerHandles[i] != -1)
				{
					list.Add(new Chapter3CheckpointOfficerEntry(managed.OfficerHandles[i], managed.OfficerBindState[i], managed.OfficerActiveName[i], managed.OfficerDistanceM[i]));
				}
			}
			return list;
		}

		private static double DistanceM(OcOfficerPosition clone, OcOfficerPosition stand)
		{
			float num = clone.X - stand.X;
			float num2 = clone.Y - stand.Y;
			float num3 = clone.Z - stand.Z;
			return Math.Sqrt(num * num + num2 * num2 + num3 * num3);
		}

		private static double DistanceM(OcOfficerPosition clone, Chapter3StandPoint stand)
		{
			float num = clone.X - stand.X;
			float num2 = clone.Y - stand.Y;
			float num3 = clone.Z - stand.Z;
			return Math.Sqrt(num * num + num2 * num2 + num3 * num3);
		}

		private void WarnOnce(string cause, string line)
		{
			_warned.Report(cause, line);
		}

		private void ClearWarn(string cause)
		{
			_warned.Clear(cause);
		}

		private bool IsHost()
		{
			try
			{
				return _checkpoints.IsHost;
			}
			catch
			{
				return false;
			}
		}

		private Chapter3CheckpointWorldStatus TryReadLastVisited(out string? propertyCode)
		{
			try
			{
				return _checkpoints.TryReadLastVisitedPropertyCode(out propertyCode);
			}
			catch
			{
				propertyCode = null;
				return Chapter3CheckpointWorldStatus.Failed;
			}
		}

		private Chapter3CheckpointWorldStatus TryReadOwnedPositions(out IReadOnlyList<Chapter3OwnedPropertyPosition> positions)
		{
			try
			{
				return _checkpoints.TryReadOwnedPropertyPositions(out positions);
			}
			catch
			{
				positions = Array.Empty<Chapter3OwnedPropertyPosition>();
				return Chapter3CheckpointWorldStatus.Failed;
			}
		}

		private Chapter3CheckpointWorldStatus TryReadNativePositions(out IReadOnlyList<Chapter3NativeCheckpointPosition> positions)
		{
			try
			{
				return _checkpoints.TryReadNativeCheckpointPositions(out positions);
			}
			catch
			{
				positions = Array.Empty<Chapter3NativeCheckpointPosition>();
				return Chapter3CheckpointWorldStatus.Failed;
			}
		}

		private Chapter3CheckpointWorldStatus TrySpawn(string label, Chapter3CheckpointSpot spot, out string? handle)
		{
			try
			{
				return _checkpoints.TrySpawnCheckpoint(label, spot.X, spot.Y, spot.Z, spot.YawDegrees, out handle);
			}
			catch
			{
				handle = null;
				return Chapter3CheckpointWorldStatus.Failed;
			}
		}

		private Chapter3CheckpointWorldStatus TryDespawn(string handle)
		{
			try
			{
				return _checkpoints.TryDespawnCheckpoint(handle);
			}
			catch
			{
				return Chapter3CheckpointWorldStatus.Failed;
			}
		}

		private Chapter3CheckpointWorldStatus TryReadStandPoints(string handle, out IReadOnlyList<Chapter3StandPoint> points)
		{
			try
			{
				return _checkpoints.TryReadStandPoints(handle, out points);
			}
			catch
			{
				points = Array.Empty<Chapter3StandPoint>();
				return Chapter3CheckpointWorldStatus.Failed;
			}
		}

		private Chapter3CheckpointWorldStatus TryReadSpawnedNative(string handle, out object? native)
		{
			try
			{
				return _checkpoints.TryReadSpawnedNative(handle, out native);
			}
			catch
			{
				native = null;
				return Chapter3CheckpointWorldStatus.Failed;
			}
		}

		private Chapter3CheckpointWorldStatus TrySetNative(string location, bool enabled)
		{
			try
			{
				return _checkpoints.TrySetNativeCheckpoint(location, enabled);
			}
			catch
			{
				return Chapter3CheckpointWorldStatus.Failed;
			}
		}

		private Chapter3CheckpointWorldStatus TryReadCameraPose(out Chapter3CameraPose pose)
		{
			try
			{
				return _checkpoints.TryReadPlayerCameraPose(out pose);
			}
			catch
			{
				pose = new Chapter3CameraPose(0f, 0f, 0f, 0f);
				return Chapter3CheckpointWorldStatus.Failed;
			}
		}
	}
	public sealed class Chapter3DayClockAdapter : IChapter3DayClock, IDisposable
	{
		private readonly Action<string> _log;

		private Action? _dayPassHandler;

		private Action? _weekPassHandler;

		private bool _lifecycleSubscribed;

		private bool _disposed;

		public event Action? DayPassed;

		public event Action? WeekPassed;

		public Chapter3DayClockAdapter(Action<string>? log = null)
		{
			_log = log ?? OrganizedCrimeLog.Warning;
			SubscribeLifecycleEvents();
		}

		public bool TryReadElapsedDa