Decompiled source of FATE WASD v0.1.1

BepInEx/plugins/PartGhostWASD/PartGhost.FateWASD.dll

Decompiled 5 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using Cleverous.Prodigy;
using Cleverous.Prodigy.Input;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Tableflip;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.Utilities;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("PartGhost")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright (c) 2026 PartGhost")]
[assembly: AssemblyFileVersion("0.1.1.0")]
[assembly: AssemblyInformationalVersion("0.1.1")]
[assembly: AssemblyProduct("PartGhost.FateWASD")]
[assembly: AssemblyTitle("PartGhost.FateWASD")]
[assembly: AssemblyVersion("0.1.1.0")]
[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 PartGhost.FateControls
{
	internal static class ControlsCommon
	{
		internal sealed class LegacyGate
		{
			private readonly MethodBase target;

			private readonly string patch;

			private float nextCheck = float.NegativeInfinity;

			internal bool Owns { get; private set; } = true;

			internal LegacyGate(Type gameType, string method, string patch)
			{
				target = AccessTools.Method(gameType, method, (Type[])null, (Type[])null);
				this.patch = patch;
			}

			internal void Refresh()
			{
				if (!(Time.unscaledTime < nextCheck))
				{
					nextCheck = Time.unscaledTime + 1f;
					Patches val = ((target == null) ? null : Harmony.GetPatchInfo(target));
					Owns = val == null || !val.Prefixes.Concat(val.Postfixes).Any((Patch p) => p.owner == "local.fatecoop.prototype" && p.PatchMethod.Name == patch);
				}
			}
		}

		private static Type rebindApi;

		private static Func<bool> rebindBlocked;

		private static FieldInfo legacyActive;

		private static FieldInfo legacyDowned;

		private static bool dependenciesDirty;

		internal static Type Api => rebindApi;

		internal static bool Blocked
		{
			get
			{
				if (!InputBlocker.AnyBlockingUiMenuIsOpen && !InventoryUI.IsDraggingItem && !LegacyDowned)
				{
					return rebindBlocked?.Invoke() ?? false;
				}
				return true;
			}
		}

		private static bool LegacyDowned
		{
			get
			{
				if (legacyActive == null || legacyDowned == null)
				{
					return false;
				}
				object value = legacyActive.GetValue(null);
				if (value != null)
				{
					return (bool)legacyDowned.GetValue(value);
				}
				return false;
			}
		}

		static ControlsCommon()
		{
			dependenciesDirty = true;
			AppDomain.CurrentDomain.AssemblyLoad += AssemblyLoaded;
		}

		private static void AssemblyLoaded(object sender, AssemblyLoadEventArgs e)
		{
			dependenciesDirty = true;
		}

		internal static void Prepare()
		{
			if (dependenciesDirty)
			{
				dependenciesDirty = false;
				Type type = null;
				rebindApi = null;
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				foreach (Assembly assembly in assemblies)
				{
					rebindApi = rebindApi ?? assembly.GetType("ZombieGhost.Rebind.RebindApi", throwOnError: false);
					type = type ?? assembly.GetType("FateCoop.Prototype.Plugin", throwOnError: false);
				}
				MethodInfo methodInfo = rebindApi?.GetProperty("IsInputBlocked")?.GetGetMethod();
				rebindBlocked = ((methodInfo == null) ? null : ((Func<bool>)Delegate.CreateDelegate(typeof(Func<bool>), methodInfo)));
				legacyActive = ((type == null) ? null : AccessTools.Field(type, "Active"));
				legacyDowned = ((type == null) ? null : AccessTools.Field(type, "downed"));
			}
		}

		internal static object Register(string guid, string name, params (string id, InputAction action, string label, string category)[] actions)
		{
			Type api = Api;
			if (api == null)
			{
				return null;
			}
			object obj = api.GetMethod("RegisterProvider").Invoke(null, new object[2] { guid, name });
			try
			{
				for (int i = 0; i < actions.Length; i++)
				{
					(string, InputAction, string, string) tuple = actions[i];
					obj.GetType().GetMethod("RegisterAction").Invoke(obj, new object[5] { tuple.Item1, tuple.Item2, tuple.Item3, tuple.Item4, null });
				}
				return obj;
			}
			catch
			{
				(obj as IDisposable)?.Dispose();
				throw;
			}
		}

		internal static void Hook(Harmony harmony, Type source, string targetType, string method, string prefix = null, string postfix = null)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			MethodInfo methodInfo = AccessTools.Method(AccessTools.TypeByName(targetType), method, (Type[])null, (Type[])null) ?? throw new MissingMethodException(targetType, method);
			harmony.Patch((MethodBase)methodInfo, (prefix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(source, prefix, (Type[])null), (postfix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(source, postfix, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		internal static InputAction Button(string name, string path)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			InputAction val = new InputAction(name, (InputActionType)1, path, (string)null, (string)null, "Button");
			val.Enable();
			return val;
		}
	}
	[BepInPlugin("partghost.fate.wasd", "FATE WASD", "0.1.1")]
	public sealed class MovementPlugin : BaseUnityPlugin
	{
		public const string Guid = "partghost.fate.wasd";

		private static MovementPlugin active;

		private Harmony harmony;

		private InputAction up;

		private InputAction down;

		private InputAction left;

		private InputAction right;

		private object provider;

		private bool moving;

		private bool legacyWarned;

		private ControlsCommon.LegacyGate legacy;

		private InputAction[] movementActions;

		private InputAction rotateAction;

		private InputAction zoomAction;

		private bool cameraBindingsDirty = true;

		private readonly HashSet<string> usedKeys = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		private readonly Dictionary<InputAction, Dictionary<int, string>> suppressed = new Dictionary<InputAction, Dictionary<int, string>>();

		private static readonly FieldRef<InputBroker, NavMeshAgent> Agent = AccessTools.FieldRefAccess<InputBroker, NavMeshAgent>("m_navMeshAgent");

		private static readonly FieldRef<InputBroker, bool> Locked = AccessTools.FieldRefAccess<InputBroker, bool>("movementLocked");

		private static readonly FieldRef<InputBroker, bool> Attack = AccessTools.FieldRefAccess<InputBroker, bool>("attackWhenInRange");

		private static readonly FieldRef<InputBroker, bool> Interact = AccessTools.FieldRefAccess<InputBroker, bool>("interactWhenInRange");

		private static readonly FieldRef<ProdigyPlayer, PlayerInput> PlayerInputRef = AccessTools.FieldRefAccess<ProdigyPlayer, PlayerInput>("m_currentInput");

		private static readonly MethodInfo Behavior = AccessTools.PropertySetter(typeof(InputBroker), "LocalInputBehavior");

		private void Awake()
		{
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Expected O, but got Unknown
			if (!((BaseUnityPlugin)this).Config.Bind<bool>("Controls", "Enabled", true, "Enable camera-relative keyboard movement.").Value)
			{
				return;
			}
			active = this;
			up = ControlsCommon.Button("move.up", "<Keyboard>/w");
			down = ControlsCommon.Button("move.down", "<Keyboard>/s");
			left = ControlsCommon.Button("move.left", "<Keyboard>/a");
			right = ControlsCommon.Button("move.right", "<Keyboard>/d");
			movementActions = (InputAction[])(object)new InputAction[4] { up, down, left, right };
			legacy = new ControlsCommon.LegacyGate(typeof(InputBroker), "ParseClickToMove", "BeforeClickToMove");
			InputSystem.onActionChange += ActionChanged;
			harmony = new Harmony("partghost.fate.wasd");
			try
			{
				ControlsCommon.Hook(harmony, typeof(MovementPlugin), typeof(InputBroker).FullName, "ReadPressedInputs", null, "Read");
				ControlsCommon.Hook(harmony, typeof(MovementPlugin), typeof(InputBroker).FullName, "ParseClickToMove", "Move");
				ControlsCommon.Hook(harmony, typeof(MovementPlugin), typeof(ProdigyPlayer).FullName, "LocalClientCollectInput", "Collect");
				((BaseUnityPlugin)this).Logger.LogInfo((object)"FATE WASD 0.1.1 ready; standalone controls.");
			}
			catch (Exception ex)
			{
				harmony.UnpatchSelf();
				Shutdown();
				((BaseUnityPlugin)this).Logger.LogError((object)ex);
			}
		}

		private bool Owns()
		{
			if (legacy.Owns)
			{
				return true;
			}
			if (!legacyWarned)
			{
				legacyWarned = true;
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Original co-op controls are installed. Standalone WASD suspended; set its Controls.KeyboardMovement=false and restart to use standalone controls.");
			}
			return false;
		}

		private static void Read(InputBroker __instance)
		{
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: 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_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			MovementPlugin movementPlugin = active;
			if (movementPlugin == null)
			{
				return;
			}
			ControlsCommon.Prepare();
			movementPlugin.legacy.Refresh();
			if (!movementPlugin.Owns())
			{
				return;
			}
			if (movementPlugin.provider == null && ControlsCommon.Api != null)
			{
				movementPlugin.provider = ControlsCommon.Register("partghost.fate.wasd", "WASD Movement", ("up", movementPlugin.up, "Move up", "Movement"), ("down", movementPlugin.down, "Move down", "Movement"), ("left", movementPlugin.left, "Move left", "Movement"), ("right", movementPlugin.right, "Move right", "Movement"));
			}
			movementPlugin.ReserveCameraKeys(__instance);
			if ((int)__instance.LocalInputBehavior != 0)
			{
				return;
			}
			Keyboard current = Keyboard.current;
			if (current == null || !((ButtonControl)current.anyKey).wasPressedThisFrame)
			{
				return;
			}
			Behavior.Invoke(__instance, new object[1] { (object)(InputBehavior)1 });
			Enumerator<InputControlScheme> enumerator = __instance.Inputs.controlSchemes.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					InputControlScheme current2 = enumerator.Current;
					if (((InputControlScheme)(ref current2)).name.IndexOf("keyboard", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						__instance.Inputs.bindingMask = InputBinding.MaskByGroup(((InputControlScheme)(ref current2)).bindingGroup);
						break;
					}
				}
			}
			finally
			{
				((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
			}
			__instance.OnInputBehaviorChanged?.Invoke((InputBehavior)1);
		}

		private void ActionChanged(object changed, InputActionChange change)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			if ((int)change == 8)
			{
				cameraBindingsDirty = true;
			}
		}

		private void ReserveCameraKeys(InputBroker broker)
		{
			//IL_0006: 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_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: 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_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			CharacterInputsActions characterInputs = broker.Inputs.CharacterInputs;
			InputAction cameraRotate = ((CharacterInputsActions)(ref characterInputs)).CameraRotate;
			characterInputs = broker.Inputs.CharacterInputs;
			InputAction cameraZoom = ((CharacterInputsActions)(ref characterInputs)).CameraZoom;
			if (cameraRotate != rotateAction || cameraZoom != zoomAction)
			{
				rotateAction = cameraRotate;
				zoomAction = cameraZoom;
				cameraBindingsDirty = true;
			}
			if (!cameraBindingsDirty)
			{
				return;
			}
			usedKeys.Clear();
			InputAction[] array = movementActions;
			for (int i = 0; i < array.Length; i++)
			{
				Enumerator<InputBinding> enumerator = array[i].bindings.GetEnumerator();
				try
				{
					while (enumerator.MoveNext())
					{
						InputBinding current = enumerator.Current;
						if (!string.IsNullOrEmpty(((InputBinding)(ref current)).effectivePath))
						{
							usedKeys.Add(((InputBinding)(ref current)).effectivePath);
						}
					}
				}
				finally
				{
					((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
				}
			}
			UpdateCameraAction(cameraRotate);
			UpdateCameraAction(cameraZoom);
			cameraBindingsDirty = false;
		}

		private void UpdateCameraAction(InputAction action)
		{
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			if (!suppressed.TryGetValue(action, out var value))
			{
				value = (suppressed[action] = new Dictionary<int, string>());
			}
			for (int i = 0; i < action.bindings.Count; i++)
			{
				InputBinding val = action.bindings[i];
				string value2;
				string text = (value.TryGetValue(i, out value2) ? (value2 ?? ((InputBinding)(ref val)).path) : ((InputBinding)(ref val)).effectivePath);
				if (usedKeys.Contains(text ?? "") && (text ?? "").StartsWith("<Keyboard>", StringComparison.OrdinalIgnoreCase))
				{
					if (!value.ContainsKey(i))
					{
						value[i] = ((InputBinding)(ref val)).overridePath;
						InputActionRebindingExtensions.ApplyBindingOverride(action, i, "");
					}
				}
				else
				{
					if (!value.ContainsKey(i))
					{
						continue;
					}
					if (((InputBinding)(ref val)).overridePath == "")
					{
						if (value2 == null)
						{
							InputActionRebindingExtensions.RemoveBindingOverride(action, i);
						}
						else
						{
							InputActionRebindingExtensions.ApplyBindingOverride(action, i, value2);
						}
					}
					value.Remove(i);
				}
			}
		}

		private static void Move(InputBroker __instance)
		{
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Invalid comparison between Unknown and I4
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Invalid comparison between Unknown and I4
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: 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_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			MovementPlugin movementPlugin = active;
			if (movementPlugin == null || !movementPlugin.Owns())
			{
				return;
			}
			Player playerChar = Player.PlayerChar;
			NavMeshAgent val = Agent.Invoke(__instance);
			if ((Object)(object)playerChar == (Object)null || (Object)(object)val == (Object)null || !((Behaviour)val).enabled || !val.isOnNavMesh)
			{
				return;
			}
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor((float)((movementPlugin.right.IsPressed() ? 1 : 0) - (movementPlugin.left.IsPressed() ? 1 : 0)), (float)((movementPlugin.up.IsPressed() ? 1 : 0) - (movementPlugin.down.IsPressed() ? 1 : 0)));
			if (!(((Vector2)(ref val2)).sqrMagnitude > 0.01f) || ControlsCommon.Blocked || (int)__instance.LocalInputBehavior != 1 || (int)__instance.ActiveInputMode != 2 || Locked.Invoke(__instance) || ((Character)playerChar).PerformingAttack() || ((Character)playerChar).PerformingCast() || ((Character)playerChar).Fishing())
			{
				if (movementPlugin.moving)
				{
					val.ResetPath();
				}
				movementPlugin.moving = false;
				return;
			}
			Camera gameCamera = ProdigyCamera.GameCamera;
			if (!((Object)(object)gameCamera == (Object)null))
			{
				Transform transform = ((Component)gameCamera).transform;
				Vector3 val3 = Vector3.ProjectOnPlane(transform.forward, Vector3.up);
				Vector3 val4 = ((Vector3)(ref val3)).normalized * val2.y;
				val3 = Vector3.ProjectOnPlane(transform.right, Vector3.up);
				Vector3 val5 = Vector3.ClampMagnitude(val4 + ((Vector3)(ref val3)).normalized * val2.x, 1f);
				NavMeshHit val6 = default(NavMeshHit);
				if (NavMesh.SamplePosition(((Component)playerChar).transform.position + val5 * 1.5f, ref val6, 1.5f, -1))
				{
					Attack.Invoke(__instance) = false;
					Interact.Invoke(__instance) = false;
					__instance.SetMoveDestination(((NavMeshHit)(ref val6)).position);
					movementPlugin.moving = true;
				}
			}
		}

		private static bool Collect(ProdigyPlayer __instance)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			MovementPlugin movementPlugin = active;
			if (movementPlugin == null || !movementPlugin.Owns() || !movementPlugin.moving || !InputBlocker.Blocked)
			{
				return true;
			}
			InputBroker instance = SingletonBehaviour<InputBroker>.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return true;
			}
			NavMeshAgent val = Agent.Invoke(instance);
			if ((Object)(object)val == (Object)null)
			{
				return true;
			}
			Vector3 desiredVelocity = val.desiredVelocity;
			((PlayerInput)(ref PlayerInputRef.Invoke(__instance))).Set(desiredVelocity, desiredVelocity, desiredVelocity, false, false, false, false, false, false);
			return false;
		}

		private void Shutdown()
		{
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			InputSystem.onActionChange -= ActionChanged;
			(provider as IDisposable)?.Dispose();
			provider = null;
			InputAction[] array = (InputAction[])(object)new InputAction[4] { up, down, left, right };
			foreach (InputAction obj in array)
			{
				if (obj != null)
				{
					obj.Dispose();
				}
			}
			foreach (KeyValuePair<InputAction, Dictionary<int, string>> item in suppressed)
			{
				foreach (KeyValuePair<int, string> item2 in item.Value)
				{
					InputBinding val = item.Key.bindings[item2.Key];
					if (((InputBinding)(ref val)).overridePath == "")
					{
						if (item2.Value == null)
						{
							InputActionRebindingExtensions.RemoveBindingOverride(item.Key, item2.Key);
						}
						else
						{
							InputActionRebindingExtensions.ApplyBindingOverride(item.Key, item2.Key, item2.Value);
						}
					}
				}
			}
			suppressed.Clear();
			active = null;
		}

		private void OnApplicationQuit()
		{
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			Shutdown();
		}
	}
}