Decompiled source of AnyDirectionParry v1.1.1

AnyDirectionParry.dll

Decompiled 6 hours ago
using System;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;

[assembly: AssemblyProduct("AnyDirectionParry")]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyTitle("AnyDirectionParry")]
[assembly: AssemblyFileVersion("1.1.1.0")]
[assembly: CompilationRelaxations(8)]
[assembly: AssemblyVersion("1.1.1.0")]
namespace AnyDirectionParry;

public static class PluginInfo
{
	public const string PLUGIN_GUID = "supidowagon.AnyDirectionParry";

	public const string PLUGIN_NAME = "Any Direction Parry";

	public const string PLUGIN_VERSION = "1.1.1";
}
[BepInPlugin("supidowagon.AnyDirectionParry", "Any Direction Parry", "1.1.1")]
public class Plugin : BaseUnityPlugin
{
	[HarmonyPatch(typeof(EffectDealer), "FacingRuleCheck", new Type[]
	{
		typeof(DamageDealer),
		typeof(Vector3),
		typeof(Vector2)
	})]
	private static class Patch_EffectDealer_FacingRuleCheck
	{
		private static void Postfix(EffectDealer __instance, ref bool __result)
		{
			if (!__result && IgnoreParryDirection != null && IgnoreParryDirection.Value && (PlayerOnly == null || !PlayerOnly.Value || IsPlayerParryDealer(__instance)))
			{
				__result = true;
			}
		}
	}

	internal static ManualLogSource Logger;

	internal static ConfigEntry<bool> IgnoreParryDirection;

	internal static ConfigEntry<bool> PlayerOnly;

	private static PropertyInfo playerInstanceProp;

	private static FieldInfo playerHealthField;

	private static FieldInfo parryDealerField;

	private static bool reflectionReady;

	private static bool reflectionFailed;

	private void Awake()
	{
		Logger = ((BaseUnityPlugin)this).Logger;
		IgnoreParryDirection = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "IgnoreParryDirection", true, "Parry attacks coming from any direction, whichever way Yi happens to be facing. Turn off to restore the stock behaviour without removing the mod.");
		PlayerOnly = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "PlayerOnly", true, "Only lift the facing requirement for the player. Leave this on unless you also want enemies that parry to ignore facing.");
		Logger.LogInfo((object)"Plugin supidowagon.AnyDirectionParry is loaded!");
		Harmony val = Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "supidowagon.AnyDirectionParry");
		foreach (MethodBase patchedMethod in val.GetPatchedMethods())
		{
			Logger.LogInfo((object)("Patched method: " + patchedMethod.DeclaringType.FullName + "." + patchedMethod.Name));
		}
		if (val.GetPatchedMethods().Count() == 0)
		{
			Logger.LogError((object)"Failed to apply Harmony patches.");
		}
	}

	private static void EnsureReflection()
	{
		if (reflectionReady || reflectionFailed)
		{
			return;
		}
		Type type = AccessTools.TypeByName("Player");
		if (type != null)
		{
			playerInstanceProp = AccessTools.Property(type, "i");
			playerHealthField = AccessTools.Field(type, "health");
			if (playerHealthField != null)
			{
				parryDealerField = AccessTools.Field(playerHealthField.FieldType, "parryDealer");
			}
		}
		if (playerInstanceProp == null || playerHealthField == null || parryDealerField == null)
		{
			reflectionFailed = true;
			Logger.LogWarning((object)"Could not resolve Player.i.health.parryDealer; PlayerOnly cannot be enforced, so the facing rule is left untouched. Set PlayerOnly=false to apply it regardless.");
		}
		else
		{
			reflectionReady = true;
		}
	}

	internal static bool IsPlayerParryDealer(EffectDealer dealer)
	{
		if ((Object)(object)dealer == (Object)null)
		{
			return false;
		}
		EnsureReflection();
		if (!reflectionReady)
		{
			return false;
		}
		object value = playerInstanceProp.GetValue(null, null);
		if (value == null)
		{
			return false;
		}
		object value2 = playerHealthField.GetValue(value);
		if (value2 == null)
		{
			return false;
		}
		return object.ReferenceEquals(dealer, parryDealerField.GetValue(value2));
	}
}