Decompiled source of FlockFocus v0.1.0

plugins/FlockFocus.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using MMTools;
using Microsoft.CodeAnalysis;
using Rewired;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("FlockFocus")]
[assembly: AssemblyDescription("Player camera focus controls for Cult of the Lamb")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("FlockFocus")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("4A42DA4C-3665-499C-A66C-D5A63C1D3105")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace FlockFocus
{
	[BepInPlugin("com.cotl.flockfocus", "FlockFocus", "0.1.0")]
	public sealed class FlockFocusPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.cotl.flockfocus";

		public const string PluginName = "FlockFocus";

		public const string PluginVersion = "0.1.0";

		internal static ManualLogSource Log;

		internal static FlockFocusController Controller;

		private Harmony _harmony;

		public static bool IsFocusActive
		{
			get
			{
				if ((Object)(object)Controller != (Object)null)
				{
					return Controller.ShouldFocus;
				}
				return false;
			}
		}

		public static bool ShouldHideIndicatorsNow
		{
			get
			{
				if (FlockFocusConfig.HidePlayerIndicatorsWhileFocused.Value)
				{
					return IsFocusActive;
				}
				return false;
			}
		}

		private void Awake()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Expected O, but got Unknown
			//IL_008e: Expected O, but got Unknown
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			FlockFocusConfig.Bind(((BaseUnityPlugin)this).Config);
			GameObject val = new GameObject("FlockFocusController");
			Object.DontDestroyOnLoad((Object)val);
			Controller = val.AddComponent<FlockFocusController>();
			_harmony = new Harmony("com.cotl.flockfocus");
			_harmony.Patch((MethodBase)AccessTools.Method(typeof(CameraFollowTarget), "LateUpdate", (Type[])null, (Type[])null), new HarmonyMethod(typeof(CameraFollowTargetPatch), "Prefix", (Type[])null), new HarmonyMethod(typeof(CameraFollowTargetPatch), "Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			HarmonyMethod val2 = new HarmonyMethod(typeof(PlayerFarmingIndicatorPatch), "Postfix", (Type[])null);
			val2.priority = 0;
			_harmony.Patch((MethodBase)AccessTools.Method(typeof(PlayerFarming), "Update", (Type[])null, (Type[])null), (HarmonyMethod)null, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			Log.LogInfo((object)"FlockFocus loaded.");
		}

		private void OnDestroy()
		{
			if (_harmony != null)
			{
				_harmony.UnpatchSelf();
			}
		}
	}
	internal enum ActivationMode
	{
		Hold,
		Toggle
	}
	internal enum ReleaseBehavior
	{
		ReturnToDefault,
		StayOnLastTarget,
		TimedReturn
	}
	internal enum ControllerBindingMode
	{
		UnityJoystickButtons,
		RewiredActionIds,
		RewiredTemplateAxes,
		RewiredTemplateButtons
	}
	internal enum ActivationSource
	{
		None,
		Keyboard,
		Controller
	}
	internal static class FlockFocusConfig
	{
		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<ActivationMode> ActivationMode;

		internal static ConfigEntry<float> FocusZoom;

		internal static ConfigEntry<bool> DefaultZoomRestore;

		internal static ConfigEntry<float> PanSpeedMultiplier;

		internal static ConfigEntry<ReleaseBehavior> ReleaseBehavior;

		internal static ConfigEntry<float> TimedReturnSeconds;

		internal static ConfigEntry<bool> AllowKeyboard;

		internal static ConfigEntry<string> KeyboardKey;

		internal static ConfigEntry<string> KeyboardModifierKey;

		internal static ConfigEntry<bool> AllowControllers;

		internal static ConfigEntry<ControllerBindingMode> ControllerBindingMode;

		internal static ConfigEntry<bool> ControllerRequireCombo;

		internal static ConfigEntry<int> ControllerPrimaryButton;

		internal static ConfigEntry<int> ControllerModifierButton;

		internal static ConfigEntry<float> ControllerAxisThreshold;

		internal static ConfigEntry<bool> HidePlayerIndicatorsWhileFocused;

		internal static ConfigEntry<bool> DisableDuringScriptedCamera;

		internal static ConfigEntry<bool> DisableDuringConversations;

		internal static ConfigEntry<bool> DebugLogging;

		internal static void Bind(ConfigFile config)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Expected O, but got Unknown
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Expected O, but got Unknown
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Expected O, but got Unknown
			Enabled = config.Bind<bool>("General", "Enabled", true, "Enable FlockFocus camera authority.");
			ActivationMode = config.Bind<ActivationMode>("Input", "ActivationMode", FlockFocus.ActivationMode.Toggle, "Hold or Toggle.");
			FocusZoom = config.Bind<float>("Camera", "FocusZoom", 10f, new ConfigDescription("Camera target zoom while focused. Set 0 or less to keep vanilla zoom.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 25f), Array.Empty<object>()));
			DefaultZoomRestore = config.Bind<bool>("Camera", "DefaultZoomRestore", true, "Restore the vanilla target zoom after the focus frame/release.");
			PanSpeedMultiplier = config.Bind<float>("Camera", "PanSpeedMultiplier", 1.25f, new ConfigDescription("Temporary camera MoveSpeed multiplier while focused.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f), Array.Empty<object>()));
			ReleaseBehavior = config.Bind<ReleaseBehavior>("Input", "ReleaseBehavior", FlockFocus.ReleaseBehavior.ReturnToDefault, "ReturnToDefault, StayOnLastTarget, or TimedReturn.");
			TimedReturnSeconds = config.Bind<float>("Input", "TimedReturnSeconds", 1.5f, new ConfigDescription("Seconds to keep focus after release when ReleaseBehavior is TimedReturn.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>()));
			AllowKeyboard = config.Bind<bool>("Keyboard", "AllowKeyboard", true, "Allow keyboard activation.");
			KeyboardKey = config.Bind<string>("Keyboard", "KeyboardKey", "LeftAlt", "Unity KeyCode name for keyboard focus. Examples: LeftAlt, Tab, Mouse3.");
			KeyboardModifierKey = config.Bind<string>("Keyboard", "KeyboardModifierKey", "", "Optional second Unity KeyCode that must be held with KeyboardKey.");
			AllowControllers = config.Bind<bool>("Controller", "AllowControllers", true, "Allow controller activation.");
			ControllerBindingMode = config.Bind<ControllerBindingMode>("Controller", "ControllerBindingMode", FlockFocus.ControllerBindingMode.RewiredTemplateAxes, "UnityJoystickButtons reads physical joystick buttons. RewiredActionIds reads game action ids. RewiredTemplateAxes reads standardized gamepad axes such as triggers. RewiredTemplateButtons reads standardized gamepad buttons such as stick clicks.");
			ControllerRequireCombo = config.Bind<bool>("Controller", "ControllerRequireCombo", false, "Require both controller buttons to be held.");
			ControllerPrimaryButton = config.Bind<int>("Controller", "ControllerPrimaryButton", 11, "Unity joystick button index, Rewired action id, or Rewired gamepad template axis id. Default 11 is left trigger for RewiredTemplateAxes.");
			ControllerModifierButton = config.Bind<int>("Controller", "ControllerModifierButton", -1, "Second Unity joystick button index, Rewired action id, or Rewired gamepad template axis id. Use -1 to disable.");
			ControllerAxisThreshold = config.Bind<float>("Controller", "ControllerAxisThreshold", 0.55f, new ConfigDescription("How far an axis must be pressed for RewiredTemplateAxes mode.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 1f), Array.Empty<object>()));
			HidePlayerIndicatorsWhileFocused = config.Bind<bool>("Visuals", "HidePlayerIndicatorsWhileFocused", true, "Temporarily disable the game's Coop Visual Indicators setting while FlockFocus is active.");
			DisableDuringScriptedCamera = config.Bind<bool>("Safety", "DisableDuringScriptedCamera", true, "Do nothing while the game is using a scripted TargetCamera, photo mode, or letterbox camera sequence.");
			DisableDuringConversations = config.Bind<bool>("Safety", "DisableDuringConversations", true, "Do nothing while MMConversation is playing.");
			DebugLogging = config.Bind<bool>("Debug", "DebugLogging", false, "Verbose FlockFocus logs.");
		}
	}
	internal sealed class FlockFocusController : MonoBehaviour
	{
		private PlayerFarming _authority;

		private ActivationSource _source;

		private bool _active;

		private float _releaseAt = -1f;

		private KeyCode _keyboardKey = (KeyCode)308;

		private KeyCode _keyboardModifier;

		private string _lastKeyboardKeyRaw;

		private string _lastKeyboardModifierRaw;

		private readonly Dictionary<int, bool> _lastControllerHeld = new Dictionary<int, bool>();

		internal bool ShouldFocus
		{
			get
			{
				if (!_active)
				{
					return false;
				}
				if (_releaseAt > 0f && Time.unscaledTime >= _releaseAt)
				{
					ClearAuthority("timed return");
					return false;
				}
				if (!IsValidPlayer(_authority))
				{
					ClearAuthority("authority missing");
					return false;
				}
				return true;
			}
		}

		internal PlayerFarming Authority => _authority;

		private void Update()
		{
			if (!FlockFocusConfig.Enabled.Value)
			{
				ClearAuthority("disabled");
				return;
			}
			RefreshKeyboardCodes();
			HandleKeyboard();
			HandleControllers();
			HandleHoldRelease();
		}

		private void LateUpdate()
		{
			PlayerFarmingIndicatorPatch.ApplyGlobalSuppression();
		}

		private void RefreshKeyboardCodes()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			if (_lastKeyboardKeyRaw != FlockFocusConfig.KeyboardKey.Value)
			{
				_lastKeyboardKeyRaw = FlockFocusConfig.KeyboardKey.Value;
				_keyboardKey = ParseKeyCode(_lastKeyboardKeyRaw, (KeyCode)308);
			}
			if (_lastKeyboardModifierRaw != FlockFocusConfig.KeyboardModifierKey.Value)
			{
				_lastKeyboardModifierRaw = FlockFocusConfig.KeyboardModifierKey.Value;
				_keyboardModifier = ParseKeyCode(_lastKeyboardModifierRaw, (KeyCode)0);
			}
		}

		private void HandleKeyboard()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			if (FlockFocusConfig.AllowKeyboard.Value && (int)_keyboardKey != 0 && ((int)_keyboardModifier == 0 || Input.GetKey(_keyboardModifier)) && Input.GetKeyDown(_keyboardKey))
			{
				PlayerFarming val = FindKeyboardPlayer();
				if ((Object)(object)val == (Object)null)
				{
					DebugLog("Keyboard focus ignored: no keyboard-owned player found.");
				}
				else
				{
					Activate(val, ActivationSource.Keyboard);
				}
			}
		}

		private void HandleControllers()
		{
			if (!FlockFocusConfig.AllowControllers.Value)
			{
				return;
			}
			foreach (PlayerFarming item in EnumeratePlayers())
			{
				if (IsValidPlayer(item))
				{
					GetControllerComboState(item, out var pressed, out var _, updateEdgeState: true);
					if (pressed)
					{
						Activate(item, ActivationSource.Controller);
					}
				}
			}
		}

		private void HandleHoldRelease()
		{
			if (_active && FlockFocusConfig.ActivationMode.Value == ActivationMode.Hold)
			{
				bool held = false;
				if (_source == ActivationSource.Keyboard)
				{
					held = IsKeyboardHeld();
				}
				else if (_source == ActivationSource.Controller && IsValidPlayer(_authority))
				{
					GetControllerComboState(_authority, out var _, out held, updateEdgeState: false);
				}
				if (!held)
				{
					Release();
				}
			}
		}

		private bool IsKeyboardHeld()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			if ((int)_keyboardKey == 0)
			{
				return false;
			}
			if ((int)_keyboardModifier == 0 || Input.GetKey(_keyboardModifier))
			{
				return Input.GetKey(_keyboardKey);
			}
			return false;
		}

		private void Activate(PlayerFarming player, ActivationSource source)
		{
			if (IsValidPlayer(player))
			{
				if (FlockFocusConfig.ActivationMode.Value == ActivationMode.Toggle && _active && (Object)(object)_authority == (Object)(object)player)
				{
					ClearAuthority("toggle off");
					return;
				}
				_authority = player;
				_source = source;
				_active = true;
				_releaseAt = -1f;
				DebugLog("Authority -> P" + (player.playerID + 1) + " via " + source);
			}
		}

		private void Release()
		{
			switch (FlockFocusConfig.ReleaseBehavior.Value)
			{
			case ReleaseBehavior.StayOnLastTarget:
				_releaseAt = -1f;
				break;
			case ReleaseBehavior.TimedReturn:
				_releaseAt = Time.unscaledTime + Mathf.Max(0f, FlockFocusConfig.TimedReturnSeconds.Value);
				break;
			default:
				ClearAuthority("released");
				break;
			}
		}

		private void ClearAuthority(string reason)
		{
			if (_active)
			{
				DebugLog("Cleared focus: " + reason);
			}
			_authority = null;
			_source = ActivationSource.None;
			_active = false;
			_releaseAt = -1f;
		}

		private void GetControllerComboState(PlayerFarming player, out bool pressed, out bool held, bool updateEdgeState)
		{
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			pressed = false;
			held = false;
			if ((Object)(object)player == (Object)null)
			{
				return;
			}
			int value = FlockFocusConfig.ControllerPrimaryButton.Value;
			int value2 = FlockFocusConfig.ControllerModifierButton.Value;
			bool flag = FlockFocusConfig.ControllerRequireCombo.Value && value2 >= 0;
			bool flag2;
			bool flag3;
			bool flag4;
			bool flag5;
			if (FlockFocusConfig.ControllerBindingMode.Value == ControllerBindingMode.RewiredTemplateAxes)
			{
				flag2 = value >= 0 && SafeGetTemplateAxis(player, value);
				flag3 = false;
				flag4 = !flag || SafeGetTemplateAxis(player, value2);
				flag5 = false;
			}
			else if (FlockFocusConfig.ControllerBindingMode.Value == ControllerBindingMode.RewiredTemplateButtons)
			{
				flag2 = value >= 0 && SafeGetTemplateButton(player, value);
				flag3 = false;
				flag4 = !flag || SafeGetTemplateButton(player, value2);
				flag5 = false;
			}
			else if (FlockFocusConfig.ControllerBindingMode.Value == ControllerBindingMode.RewiredActionIds)
			{
				Player rewiredPlayer = player.rewiredPlayer;
				if (rewiredPlayer == null)
				{
					return;
				}
				flag2 = value >= 0 && SafeGetButton(rewiredPlayer, value);
				flag3 = value >= 0 && SafeGetButtonDown(rewiredPlayer, value);
				flag4 = !flag || SafeGetButton(rewiredPlayer, value2);
				flag5 = flag && SafeGetButtonDown(rewiredPlayer, value2);
			}
			else
			{
				int joystickNumber = Mathf.Clamp(player.playerID + 1, 1, 8);
				flag2 = value >= 0 && Input.GetKey(UnityJoystickButton(joystickNumber, value));
				flag3 = value >= 0 && Input.GetKeyDown(UnityJoystickButton(joystickNumber, value));
				flag4 = !flag || Input.GetKey(UnityJoystickButton(joystickNumber, value2));
				flag5 = flag && Input.GetKeyDown(UnityJoystickButton(joystickNumber, value2));
			}
			held = (flag ? (flag2 && flag4) : flag2);
			if (FlockFocusConfig.ControllerBindingMode.Value == ControllerBindingMode.RewiredTemplateAxes || FlockFocusConfig.ControllerBindingMode.Value == ControllerBindingMode.RewiredTemplateButtons)
			{
				int playerID = player.playerID;
				bool flag6 = _lastControllerHeld.ContainsKey(playerID) && _lastControllerHeld[playerID];
				pressed = held && !flag6;
				if (updateEdgeState)
				{
					_lastControllerHeld[playerID] = held;
				}
			}
			else
			{
				pressed = ((!flag) ? flag3 : (held && (flag3 || flag5)));
			}
		}

		private static bool SafeGetTemplateAxis(PlayerFarming player, int templateElementId)
		{
			try
			{
				if ((Object)(object)player == (Object)null || player.rewiredPlayer == null || player.rewiredPlayer.controllers == null)
				{
					return false;
				}
				float num = Mathf.Clamp01(FlockFocusConfig.ControllerAxisThreshold.Value);
				Controller firstControllerWithTemplate = player.rewiredPlayer.controllers.GetFirstControllerWithTemplate<IGamepadTemplate>();
				if (firstControllerWithTemplate == null)
				{
					return false;
				}
				IControllerTemplate template = (IControllerTemplate)(object)firstControllerWithTemplate.GetTemplate<IGamepadTemplate>();
				IControllerTemplateAxis val = ((template != null) ? template.GetElement<IControllerTemplateAxis>(templateElementId) : null);
				return val != null && ((IControllerTemplateElement)val).exists && val.value > num;
			}
			catch
			{
				return false;
			}
		}

		private static bool SafeGetTemplateButton(PlayerFarming player, int templateElementId)
		{
			try
			{
				if ((Object)(object)player == (Object)null || player.rewiredPlayer == null || player.rewiredPlayer.controllers == null)
				{
					return false;
				}
				Controller firstControllerWithTemplate = player.rewiredPlayer.controllers.GetFirstControllerWithTemplate<IGamepadTemplate>();
				if (firstControllerWithTemplate == null)
				{
					return false;
				}
				IControllerTemplate template = (IControllerTemplate)(object)firstControllerWithTemplate.GetTemplate<IGamepadTemplate>();
				IControllerTemplateButton val = ((template != null) ? template.GetElement<IControllerTemplateButton>(templateElementId) : null);
				return val != null && ((IControllerTemplateElement)val).exists && val.value;
			}
			catch
			{
				return false;
			}
		}

		private static bool SafeGetButton(Player player, int actionId)
		{
			try
			{
				return player != null && player.GetButton(actionId);
			}
			catch
			{
				return false;
			}
		}

		private static bool SafeGetButtonDown(Player player, int actionId)
		{
			try
			{
				return player != null && player.GetButtonDown(actionId);
			}
			catch
			{
				return false;
			}
		}

		private static KeyCode UnityJoystickButton(int joystickNumber, int button)
		{
			return (KeyCode)(350 + (joystickNumber - 1) * 20 + button);
		}

		private unsafe static KeyCode ParseKeyCode(string raw, KeyCode fallback)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrWhiteSpace(raw))
			{
				return (KeyCode)0;
			}
			try
			{
				return (KeyCode)Enum.Parse(typeof(KeyCode), raw.Trim(), ignoreCase: true);
			}
			catch
			{
				FlockFocusPlugin.Log.LogWarning((object)("Invalid KeyCode '" + raw + "', using " + ((object)(*(KeyCode*)(&fallback))/*cast due to .constrained prefix*/).ToString()));
				return fallback;
			}
		}

		private static PlayerFarming FindKeyboardPlayer()
		{
			foreach (PlayerFarming item in EnumeratePlayers())
			{
				if (!IsValidPlayer(item) || item.rewiredPlayer == null)
				{
					continue;
				}
				try
				{
					if (item.rewiredPlayer.controllers != null && item.rewiredPlayer.controllers.hasKeyboard)
					{
						return item;
					}
				}
				catch
				{
					return item;
				}
			}
			if (!IsValidPlayer(PlayerFarming.Instance))
			{
				return null;
			}
			return PlayerFarming.Instance;
		}

		internal static IEnumerable<PlayerFarming> EnumeratePlayers()
		{
			if (PlayerFarming.players != null)
			{
				for (int i = 0; i < PlayerFarming.players.Count; i++)
				{
					PlayerFarming val = PlayerFarming.players[i];
					if ((Object)(object)val != (Object)null)
					{
						yield return val;
					}
				}
			}
			else if ((Object)(object)PlayerFarming.Instance != (Object)null)
			{
				yield return PlayerFarming.Instance;
			}
		}

		internal static bool IsValidPlayer(PlayerFarming player)
		{
			if ((Object)(object)player != (Object)null && (Object)(object)((Component)player).gameObject != (Object)null && ((Component)player).gameObject.activeInHierarchy)
			{
				if (!((Object)(object)player.CameraBone != (Object)null))
				{
					return (Object)(object)((Component)player).transform != (Object)null;
				}
				return true;
			}
			return false;
		}

		internal static void DebugLog(string message)
		{
			if (FlockFocusConfig.DebugLogging.Value && FlockFocusPlugin.Log != null)
			{
				FlockFocusPlugin.Log.LogInfo((object)("[FlockFocus] " + message));
			}
		}
	}
	internal sealed class CameraFocusPatchState
	{
		internal List<Target> Targets;

		internal float TargetDistance;

		internal float MoveSpeed;

		internal bool HasState;
	}
	internal static class CameraFollowTargetPatch
	{
		public static void Prefix(CameraFollowTarget __instance, ref CameraFocusPatchState __state)
		{
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Expected O, but got Unknown
			__state = null;
			FlockFocusController controller = FlockFocusPlugin.Controller;
			if ((Object)(object)controller == (Object)null || !controller.ShouldFocus || (Object)(object)__instance == (Object)null || !CanTouchCamera(__instance))
			{
				return;
			}
			PlayerFarming authority = controller.Authority;
			if (!FlockFocusController.IsValidPlayer(authority))
			{
				return;
			}
			GameObject val = (((Object)(object)authority.CameraBone != (Object)null) ? authority.CameraBone : ((Component)authority).gameObject);
			if (!((Object)(object)val == (Object)null))
			{
				__state = new CameraFocusPatchState
				{
					Targets = ((__instance.targets != null) ? new List<Target>(__instance.targets) : null),
					TargetDistance = __instance.targetDistance,
					MoveSpeed = __instance.MoveSpeed,
					HasState = true
				};
				__instance.targets = new List<Target>
				{
					new Target(val, 1f)
				};
				if (FlockFocusConfig.FocusZoom.Value > 0f)
				{
					__instance.targetDistance = FlockFocusConfig.FocusZoom.Value;
				}
				__instance.MoveSpeed = Mathf.Max(0.1f, __instance.MoveSpeed * FlockFocusConfig.PanSpeedMultiplier.Value);
			}
		}

		public static void Postfix(CameraFollowTarget __instance, CameraFocusPatchState __state)
		{
			if (!((Object)(object)__instance == (Object)null) && __state != null && __state.HasState)
			{
				__instance.targets = __state.Targets ?? new List<Target>();
				if (FlockFocusConfig.DefaultZoomRestore.Value)
				{
					__instance.targetDistance = __state.TargetDistance;
				}
				__instance.MoveSpeed = __state.MoveSpeed;
			}
		}

		private static bool CanTouchCamera(CameraFollowTarget camera)
		{
			if ((Object)(object)camera.TargetCamera != (Object)null && FlockFocusConfig.DisableDuringScriptedCamera.Value)
			{
				return false;
			}
			if (FlockFocusConfig.DisableDuringScriptedCamera.Value)
			{
				try
				{
					if (PhotoModeManager.PhotoModeActive || LetterBox.IsPlaying)
					{
						return false;
					}
				}
				catch
				{
					return false;
				}
			}
			if (FlockFocusConfig.DisableDuringConversations.Value)
			{
				try
				{
					if (MMConversation.isPlaying)
					{
						return false;
					}
				}
				catch
				{
					return false;
				}
			}
			return Time.timeScale > 0f;
		}
	}
	internal static class PlayerFarmingIndicatorPatch
	{
		private static bool _overrideActive;

		private static bool _previousCoopVisualIndicators;

		public static void Postfix(PlayerFarming __instance)
		{
			ApplyGlobalSuppression();
		}

		internal static void ApplyGlobalSuppression()
		{
			if (!ShouldSuppress())
			{
				RestoreCoopVisualIndicators();
			}
			else if (SettingsManager.Settings != null && SettingsManager.Settings.Accessibility != null)
			{
				if (!_overrideActive)
				{
					_previousCoopVisualIndicators = SettingsManager.Settings.Accessibility.CoopVisualIndicators;
					_overrideActive = true;
				}
				SettingsManager.Settings.Accessibility.CoopVisualIndicators = false;
			}
		}

		private static bool ShouldSuppress()
		{
			FlockFocusController controller = FlockFocusPlugin.Controller;
			if (FlockFocusConfig.HidePlayerIndicatorsWhileFocused.Value && (Object)(object)controller != (Object)null)
			{
				return controller.ShouldFocus;
			}
			return false;
		}

		private static void RestoreCoopVisualIndicators()
		{
			if (_overrideActive)
			{
				if (SettingsManager.Settings != null && SettingsManager.Settings.Accessibility != null)
				{
					SettingsManager.Settings.Accessibility.CoopVisualIndicators = _previousCoopVisualIndicators;
				}
				_overrideActive = false;
			}
		}
	}
}