Decompiled source of RealisticSpears Fix v0.1.1

RealisticSpears.dll

Decompiled 2 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyFileVersion("1.0.0.1")]
[assembly: AssemblyInformationalVersion("0.1.1-unofficial-gripfix")]
[assembly: AssemblyVersion("1.0.0.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;
		}
	}
}
internal static class AnimationSpeedManager
{
	public delegate double Handler(Character character, double speed);

	private static readonly Harmony harmony = new Harmony("AnimationSpeedManager");

	private static bool hasMarkerPatch = false;

	private static readonly MethodInfo method = AccessTools.DeclaredMethod(typeof(CharacterAnimEvent), "CustomFixedUpdate", (Type[])null, (Type[])null);

	private static int index = 0;

	private static bool changed = false;

	private static Handler[][] handlers = Array.Empty<Handler[]>();

	private static readonly Dictionary<int, List<Handler>> handlersPriorities = new Dictionary<int, List<Handler>>();

	public static void Add(Handler handler, int priority = 400)
	{
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Expected O, but got Unknown
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Expected O, but got Unknown
		if (!hasMarkerPatch)
		{
			harmony.Patch((MethodBase)method, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(AnimationSpeedManager), "markerPatch", (Type[])null, (Type[])null)), (HarmonyMethod)null);
			hasMarkerPatch = true;
		}
		if (!handlersPriorities.TryGetValue(priority, out var value))
		{
			handlersPriorities.Add(priority, value = new List<Handler>());
			harmony.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(AnimationSpeedManager), "wrapper", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}
		value.Add(handler);
		handlers = handlersPriorities.OrderBy(delegate(KeyValuePair<int, List<Handler>> kv)
		{
			KeyValuePair<int, List<Handler>> keyValuePair = kv;
			return keyValuePair.Key;
		}).Select(delegate(KeyValuePair<int, List<Handler>> kv)
		{
			KeyValuePair<int, List<Handler>> keyValuePair = kv;
			return keyValuePair.Value.ToArray();
		}).ToArray();
	}

	private static void wrapper(Character ___m_character, Animator ___m_animator)
	{
		double num = (double)___m_animator.speed * 10000000.0 % 100.0;
		if ((!(num > 10.0) || !(num < 30.0)) && !(___m_animator.speed <= 0.001f))
		{
			double num2 = ___m_animator.speed;
			double num3 = handlers[index++].Aggregate(num2, (double current, Handler handler) => handler(___m_character, current));
			if (num3 != num2)
			{
				___m_animator.speed = (float)(num3 - num3 % 1E-05);
				changed = true;
			}
		}
	}

	private static void markerPatch(Animator ___m_animator)
	{
		if (changed)
		{
			double num = (double)___m_animator.speed * 10000000.0 % 100.0;
			if (num < 10.0 || num > 30.0)
			{
				___m_animator.speed += 1.9E-06f;
			}
			changed = false;
		}
		index = 0;
	}
}
namespace RealisticSpears
{
	[HarmonyPatch(typeof(Humanoid), "EquipItem")]
	public static class Patch_Humanoid_EquipItem
	{
		private static void Prefix(Humanoid __instance, ItemData item)
		{
			if (item != null)
			{
				SharedData shared = item.m_shared;
				if (SpearUtils.IsSpearWithPokeAttack_Shared(shared))
				{
					shared.m_attack.m_attackAnimation = "sword_secondary";
					shared.m_attack.m_attackRange = 3f;
					shared.m_attack.m_attackHeight = 1f;
					shared.m_attack.m_attackAngle = 30f;
					shared.m_attack.m_attackRayWidth = 0.4f;
				}
			}
		}
	}
	[BepInPlugin("com.havocmods.realisticspears", "Realistic Spears", "0.1.1")]
	public class Plugin : BaseUnityPlugin
	{
		internal static Harmony HarmonyInstance;

		private void Awake()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Expected O, but got Unknown
			HarmonyInstance = new Harmony("com.havocmods.realisticspears");
			HarmonyInstance.PatchAll();
			AnimationSpeedManager.Add(delegate(Character character, double speed)
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0012: Expected O, but got Unknown
				//IL_0013: Unknown result type (might be due to invalid IL or missing references)
				//IL_001e: Expected O, but got Unknown
				//IL_0051: Unknown result type (might be due to invalid IL or missing references)
				//IL_0057: Expected O, but got Unknown
				Player val = (Player)((character is Player) ? character : null);
				if ((Object)val == (Object)null || !((Character)val).InAttack())
				{
					return speed;
				}
				object value = AccessTools.Field(typeof(Humanoid), "m_currentAttack").GetValue(val);
				Attack val2 = (Attack)((value is Attack) ? value : null);
				SharedData val3 = ((Humanoid)val).GetCurrentWeapon()?.m_shared;
				if (val2 == null || val3 == null)
				{
					return speed;
				}
				return (!SpearUtils.IsSpearWithSwordAttack_Shared(val3) || !string.Equals(val2.m_attackAnimation, "sword_secondary", StringComparison.OrdinalIgnoreCase)) ? speed : (speed * 2.200000047683716);
			});
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[RealisticSpears] Unofficial multiplayer grip fix 0.1.1 loaded.");
		}

		private void OnDestroy()
		{
			Harmony harmonyInstance = HarmonyInstance;
			if (harmonyInstance != null)
			{
				harmonyInstance.UnpatchSelf();
			}
		}
	}
	internal sealed class SpearRotatedMarker : MonoBehaviour
	{
		public Vector3 origLocalPos;

		public Quaternion origLocalRot;

		public bool rotationApplied;

		public bool initialized;

		public bool throwFlipped;
	}
	internal static class SpearPositioner
	{
		internal static void FixSpearRotationAndPosition(GameObject go, bool isRevert, bool isFangSpear)
		{
			if ((Object)(object)go != (Object)null)
			{
				if (!isRevert)
				{
					FixSpearRotation(go);
					FixSpearPositionOffset(go, isRevert, isFangSpear);
				}
				else
				{
					FixSpearPositionOffset(go, isRevert, isFangSpear);
					FixSpearRotation(go);
				}
			}
		}

		internal static void FixSpearRotation(GameObject go)
		{
			go.transform.Rotate(180f, 25f, 0f, (Space)1);
		}

		internal static void FixSpearPositionOffset(GameObject go, bool isRevert, bool isFangSpear)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: 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_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = (isRevert ? Vector3.back : Vector3.forward);
			float num = (isFangSpear ? (-0.72f) : (-0.5f));
			go.transform.Translate(val * num, (Space)1);
		}

		internal static void ApplyState(GameObject go, SpearRotatedMarker marker, bool applyRotation, bool isFangSpear, bool extraFlip = false)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: 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_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//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)
			if (!((Object)go == (Object)null) && !((Object)marker == (Object)null) && marker.initialized)
			{
				float num = (isFangSpear ? (-0.72f) : (-0.5f));
				Quaternion val = ((!applyRotation) ? marker.origLocalRot : (marker.origLocalRot * Quaternion.Euler(180f, 25f, 0f)));
				Quaternion val2 = (extraFlip ? (val * Quaternion.Euler(180f, 0f, 0f)) : val);
				go.transform.localRotation = val2;
				go.transform.localPosition = marker.origLocalPos + val2 * Vector3.forward * num;
				marker.rotationApplied = applyRotation;
				marker.throwFlipped = extraFlip;
			}
		}
	}
	internal static class SpearUtils
	{
		internal static bool IsSpearWithPokeAttack_Shared(SharedData shared)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Invalid comparison between Unknown and I4
			if (shared != null && (int)shared.m_skillType == 5 && shared.m_attack != null)
			{
				return shared.m_attack.m_attackAnimation == "spear_poke";
			}
			return false;
		}

		internal static bool IsSpearWithSwordAttack_Shared(SharedData shared)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Invalid comparison between Unknown and I4
			if (shared != null && (int)shared.m_skillType == 5 && shared.m_attack != null)
			{
				return shared.m_attack.m_attackAnimation == "sword_secondary";
			}
			return false;
		}

		internal static bool IsFangSpear_Shared(SharedData shared)
		{
			if (shared != null && !string.IsNullOrEmpty(shared.m_name))
			{
				return shared.m_name == "$item_spear_wolffang";
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(ZSyncAnimation), "RPC_SetTrigger")]
	public static class Patch_SpearTrigger
	{
		private static void Postfix(ZSyncAnimation __instance, string name)
		{
			Player componentInParent = ((Component)__instance).GetComponentInParent<Player>();
			if (!((Object)(object)componentInParent == (Object)null))
			{
				ThrowState orCreateValue = ThrowStates.States.GetOrCreateValue(componentInParent);
				switch (name)
				{
				case "spear_throw":
					orCreateValue.Start(Time.time);
					break;
				case "sword_secondary":
				case "spear_poke":
					orCreateValue.Clear();
					break;
				}
			}
		}
	}
	internal static class ThrowStates
	{
		internal static readonly ConditionalWeakTable<Player, ThrowState> States = new ConditionalWeakTable<Player, ThrowState>();
	}
	[HarmonyPatch(typeof(VisEquipment), "CustomUpdate")]
	public static class Patch_VisEquipment_CustomUpdate
	{
		private static readonly FieldInfo RightItemField = AccessTools.Field(typeof(VisEquipment), "m_rightItemInstance");

		private static readonly FieldInfo RightHashField = AccessTools.Field(typeof(VisEquipment), "m_currentRightItemHash");

		public static void Postfix(VisEquipment __instance)
		{
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Invalid comparison between Unknown and I4
			//IL_021b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: 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)
			if ((Object)(object)__instance == (Object)null || RightItemField == null || RightHashField == null)
			{
				return;
			}
			Player component = ((Component)__instance).GetComponent<Player>();
			if ((Object)(object)component == (Object)null || (Object)(object)ObjectDB.instance == (Object)null)
			{
				return;
			}
			object? value = RightItemField.GetValue(__instance);
			GameObject val = (GameObject)((value is GameObject) ? value : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			VisualSpearCache visualSpearCache = val.GetComponent<VisualSpearCache>();
			int num = (int)RightHashField.GetValue(__instance);
			if ((Object)(object)visualSpearCache == (Object)null)
			{
				GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(num);
				if ((Object)(object)itemPrefab == (Object)null)
				{
					return;
				}
				ItemDrop component2 = itemPrefab.GetComponent<ItemDrop>();
				if ((Object)(object)component2 == (Object)null || component2.m_itemData == null || component2.m_itemData.m_shared == null)
				{
					return;
				}
				SharedData shared = component2.m_itemData.m_shared;
				visualSpearCache = val.AddComponent<VisualSpearCache>();
				visualSpearCache.isSpear = (int)shared.m_skillType == 5 && shared.m_attack != null && (shared.m_attack.m_attackAnimation == "spear_poke" || shared.m_attack.m_attackAnimation == "sword_secondary");
				if (visualSpearCache.isSpear)
				{
					visualSpearCache.isFang = SpearUtils.IsFangSpear_Shared(shared);
					visualSpearCache.target = FindBestTargetTransform(val);
					visualSpearCache.marker = ((Component)visualSpearCache.target).GetComponent<SpearRotatedMarker>();
					if ((Object)(object)visualSpearCache.marker == (Object)null)
					{
						visualSpearCache.marker = ((Component)visualSpearCache.target).gameObject.AddComponent<SpearRotatedMarker>();
					}
					if (!visualSpearCache.marker.initialized)
					{
						visualSpearCache.marker.origLocalPos = visualSpearCache.target.localPosition;
						visualSpearCache.marker.origLocalRot = visualSpearCache.target.localRotation;
						visualSpearCache.marker.initialized = true;
					}
				}
			}
			if (visualSpearCache.isSpear && !((Object)(object)visualSpearCache.target == (Object)null) && !((Object)(object)visualSpearCache.marker == (Object)null))
			{
				if (ThrowStates.States.TryGetValue(component, out var value2) && value2.IsThrowing(Time.time, ((Character)component).InAttack()))
				{
					visualSpearCache.target.localPosition = visualSpearCache.marker.origLocalPos;
					visualSpearCache.target.localRotation = visualSpearCache.marker.origLocalRot;
					visualSpearCache.marker.rotationApplied = false;
					visualSpearCache.marker.throwFlipped = false;
				}
				else
				{
					SpearPositioner.ApplyState(((Component)visualSpearCache.target).gameObject, visualSpearCache.marker, applyRotation: true, visualSpearCache.isFang);
				}
			}
		}

		private static Transform FindBestTargetTransform(GameObject item)
		{
			Transform[] componentsInChildren = item.GetComponentsInChildren<Transform>(true);
			Transform[] array = componentsInChildren;
			foreach (Transform val in array)
			{
				if (string.Equals(((Object)val).name, "attach", StringComparison.OrdinalIgnoreCase))
				{
					return val;
				}
			}
			array = componentsInChildren;
			foreach (Transform val2 in array)
			{
				if (((Object)val2).name.IndexOf("attach", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return val2;
				}
			}
			MeshRenderer componentInChildren = item.GetComponentInChildren<MeshRenderer>(true);
			if (!((Object)(object)componentInChildren != (Object)null))
			{
				return item.transform;
			}
			return ((Component)componentInChildren).transform;
		}
	}
	internal sealed class VisualSpearCache : MonoBehaviour
	{
		internal bool isSpear;

		internal bool isFang;

		internal Transform target;

		internal SpearRotatedMarker marker;
	}
	internal sealed class ThrowState
	{
		private bool active;

		private bool sawAttack;

		private float started;

		internal void Start(float now)
		{
			active = true;
			sawAttack = false;
			started = now;
		}

		internal void Clear()
		{
			active = false;
			sawAttack = false;
		}

		internal bool IsThrowing(float now, bool inAttack)
		{
			if (!active)
			{
				return false;
			}
			float num = now - started;
			if (num < 0f || num > 5f)
			{
				Clear();
				return false;
			}
			if (inAttack)
			{
				sawAttack = true;
				return true;
			}
			if (sawAttack || num > 0.5f)
			{
				Clear();
				return false;
			}
			return true;
		}
	}
}