Decompiled source of ParryAndDodgeConfig v1.1.2

BepInEx\plugins\ParryAndDodgeConfig\ParryAndDodgeConfig.dll

Decompiled a week ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[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("ParryAndDodgeConfig")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.1.0")]
[assembly: AssemblyInformationalVersion("1.1.1")]
[assembly: AssemblyProduct("ParryAndDodgeConfig")]
[assembly: AssemblyTitle("ParryAndDodgeConfig")]
[assembly: AssemblyVersion("1.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 ParryAndDodgeConfig
{
	[BepInPlugin("com.rafal.configurableparrywindow", "ParryAndDodgeConfig", "1.1.1")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.rafal.configurableparrywindow";

		public const string PluginName = "ParryAndDodgeConfig";

		public const string PluginVersion = "1.1.1";

		internal static ConfigEntry<float> WindowSeconds;

		internal static ConfigEntry<float> DodgeInvincibilitySeconds;

		internal static ConfigEntry<bool> LogPatchInfo;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Expected O, but got Unknown
			WindowSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Parry", "WindowSeconds", 0.25f, new ConfigDescription("Timed-block/parry window in seconds. Vanilla is 0.25 seconds (250 ms).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 2f), Array.Empty<object>()));
			DodgeInvincibilitySeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Dodge", "InvincibilityDurationSeconds", 0f, new ConfigDescription("Dodge invincibility duration in seconds. Set to 0 to use Valheim's vanilla dodge invincibility behavior. Otherwise the configured duration is applied from the start of the dodge's invincibility window.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
			LogPatchInfo = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "LogPatchInfo", true, "Log the active parry window, dodge setting, and patch status when the mod loads.");
			_harmony = new Harmony("com.rafal.configurableparrywindow");
			try
			{
				_harmony.PatchAll();
				string text = ((DodgeInvincibilitySeconds.Value <= 0f) ? "vanilla" : $"{DodgeInvincibilitySeconds.Value:0.###} s ({DodgeInvincibilitySeconds.Value * 1000f:0} ms)");
				((BaseUnityPlugin)this).Logger.LogInfo((object)("ParryAndDodgeConfig 1.1.1 loaded. " + $"Parry: {WindowSeconds.Value:0.###} s ({WindowSeconds.Value * 1000f:0} ms). " + "Dodge i-frames: " + text + "."));
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"Failed to install Harmony patches: {arg}");
			}
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	[HarmonyPatch(typeof(Humanoid), "BlockAttack")]
	internal static class BlockAttackPatch
	{
		private static readonly FieldInfo BlockTimerField = AccessTools.Field(typeof(Humanoid), "m_blockTimer");

		private static bool _warnedMissingField;

		private static void Prefix(Humanoid __instance)
		{
			if ((Object)(object)__instance == (Object)null || BlockTimerField == null)
			{
				if (!_warnedMissingField)
				{
					_warnedMissingField = true;
					Debug.LogError((object)"[Parry And Dodge Config] Could not find Humanoid.m_blockTimer. Parry patch is disabled.");
				}
				return;
			}
			float num = Mathf.Clamp(Plugin.WindowSeconds.Value, 0.01f, 2f);
			try
			{
				float num2 = (float)BlockTimerField.GetValue(__instance);
				if (num2 < 0f)
				{
					return;
				}
				if (num > 0.25f)
				{
					if (num2 >= 0.25f && num2 < num)
					{
						BlockTimerField.SetValue(__instance, 0f);
					}
				}
				else if (num < 0.25f && num2 >= num && num2 < 0.25f)
				{
					BlockTimerField.SetValue(__instance, 0.25f);
				}
			}
			catch (Exception arg)
			{
				Debug.LogError((object)$"[Parry And Dodge Config] Failed to read/write m_blockTimer: {arg}");
			}
		}
	}
	[HarmonyPatch(typeof(Player), "Dodge")]
	internal static class DodgePatch
	{
		private sealed class DodgeState
		{
			internal bool Pending;

			internal bool Active;

			internal float StartTime;
		}

		private static readonly ConditionalWeakTable<Player, DodgeState> States = new ConditionalWeakTable<Player, DodgeState>();

		private static readonly FieldInfo DodgeInvincibleField = AccessTools.Field(typeof(Player), "m_dodgeInvincible");

		private static readonly FieldInfo DodgeInvincibleCachedField = AccessTools.Field(typeof(Player), "m_dodgeInvincibleCached");

		private static readonly FieldInfo DodgeAnimationTagField = AccessTools.Field(typeof(Player), "s_animatorTagDodge");

		private static readonly MethodInfo GetNextOrCurrentAnimHashMethod = AccessTools.Method(typeof(Player), "GetNextOrCurrentAnimHash", (Type[])null, (Type[])null);

		private static bool _warnedMissingFields;

		private static void Postfix(Player __instance)
		{
			if (!((Object)(object)__instance == (Object)null) && !(Plugin.DodgeInvincibilitySeconds.Value <= 0f))
			{
				if (DodgeInvincibleField == null || DodgeInvincibleCachedField == null)
				{
					WarnMissingFields();
				}
				else
				{
					States.GetOrCreateValue(__instance).Pending = true;
				}
			}
		}

		[HarmonyPatch(typeof(Player), "UpdateDodge")]
		[HarmonyPostfix]
		private static void UpdateDodgePostfix(Player __instance)
		{
			if ((Object)(object)__instance == (Object)null || Plugin.DodgeInvincibilitySeconds.Value <= 0f)
			{
				return;
			}
			if (DodgeInvincibleField == null || DodgeInvincibleCachedField == null)
			{
				WarnMissingFields();
				return;
			}
			try
			{
				bool flag = (bool)DodgeInvincibleField.GetValue(__instance);
				DodgeState orCreateValue = States.GetOrCreateValue(__instance);
				if (orCreateValue.Pending && flag)
				{
					orCreateValue.Pending = false;
					orCreateValue.Active = true;
					orCreateValue.StartTime = Time.time;
				}
				if (!orCreateValue.Active)
				{
					return;
				}
				float num = Time.time - orCreateValue.StartTime;
				float num2 = Mathf.Clamp(Plugin.DodgeInvincibilitySeconds.Value, 0.001f, 2f);
				bool flag2 = num < num2;
				if (!flag && num < num2 && !IsDodgeAnimationActive(__instance))
				{
					orCreateValue.Active = false;
					return;
				}
				DodgeInvincibleField.SetValue(__instance, flag2);
				DodgeInvincibleCachedField.SetValue(__instance, flag2);
				if (!flag2)
				{
					orCreateValue.Active = false;
				}
			}
			catch (Exception arg)
			{
				Debug.LogError((object)$"[Parry And Dodge Config] Failed to override dodge invincibility: {arg}");
			}
		}

		private static bool IsDodgeAnimationActive(Player player)
		{
			if (GetNextOrCurrentAnimHashMethod == null || DodgeAnimationTagField == null)
			{
				return false;
			}
			try
			{
				int num = (int)DodgeAnimationTagField.GetValue(null);
				if (GetNextOrCurrentAnimHashMethod == null)
				{
					return false;
				}
				return (int)GetNextOrCurrentAnimHashMethod.Invoke(player, null) == num;
			}
			catch
			{
				return false;
			}
		}

		private static void WarnMissingFields()
		{
			if (!_warnedMissingFields)
			{
				_warnedMissingFields = true;
				Debug.LogError((object)"[Parry And Dodge Config] Could not find Player.m_dodgeInvincible and/or Player.m_dodgeInvincibleCached. Dodge invincibility override is disabled.");
			}
		}
	}
}