Decompiled source of ParryRework v1.0.3

ParryRework.dll

Decompiled 3 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using ConditionalConfigSync;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("ParryRework")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ParryRework")]
[assembly: AssemblyTitle("ParryRework")]
[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;
		}
	}
}
namespace ParryRework
{
	[BepInPlugin("com.dreich.parryrework", "Parry Rework", "1.0.3")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class ParryReworkPlugin : BaseUnityPlugin
	{
		public const string Guid = "com.dreich.parryrework";

		public const string Name = "Parry Rework";

		public const string Version = "1.0.3";

		internal const string ConfigSyncGuid = "_shudnal.ConditionalConfigSync";

		internal static ManualLogSource Log;

		internal static bool ConfigSyncAvailable;

		private static bool? treasureMaps;

		internal const string TreasureMapsGuid = "com.dreich.treasuremaps";

		private static ConfigEntry<bool> ConfigLockedEntry;

		internal static ConfigEntry<bool> ParryNegatesDamage;

		internal static ConfigEntry<bool> AnyBlockerCanParry;

		internal static ConfigEntry<bool> FistsCanParry;

		internal static ConfigEntry<bool> LogStagger;

		internal static ConfigEntry<string> StaggerSkill;

		internal static ConfigEntry<string> CreatureBiomes;

		internal static ConfigEntry<bool> ShieldArmorWhileBlocking;

		internal static ConfigEntry<float> ShieldArmorMultiplier;

		internal static ConfigEntry<bool> WeaponArmorWhileBlocking;

		internal static ConfigEntry<float> WeaponArmorMultiplier;

		internal static ConfigEntry<bool> RemoveShieldParryBonus;

		internal static ConfigEntry<float> BucklerPenalty;

		internal static ConfigEntry<float> RoundPenalty;

		internal static ConfigEntry<float> TowerPenalty;

		internal static bool TreasureMapsAvailable
		{
			get
			{
				bool? flag = treasureMaps;
				if (!flag.HasValue)
				{
					bool? flag2 = (treasureMaps = Chainloader.PluginInfos.ContainsKey("com.dreich.treasuremaps"));
					return flag2.Value;
				}
				return flag == true;
			}
		}

		private void Awake()
		{
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Expected O, but got Unknown
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Expected O, but got Unknown
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Expected O, but got Unknown
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Expected O, but got Unknown
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Expected O, but got Unknown
			//IL_037e: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			ConfigSyncAvailable = Chainloader.PluginInfos.ContainsKey("_shudnal.ConditionalConfigSync");
			if (ConfigSyncAvailable)
			{
				ConfigSyncCompat.Initialize("com.dreich.parryrework", "Parry Rework", "1.0.3");
			}
			ConfigLockedEntry = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Lock Configuration", true, "If on, the configuration is locked and can be changed by server admins only. Requires ConditionalConfigSync.");
			if (ConfigSyncAvailable)
			{
				ConfigSyncCompat.AddLockingConfigEntry(ConfigLockedEntry);
			}
			ParryNegatesDamage = BindShared("Parry", "ParryNegatesDamage", defaultValue: true, "A successful parry, with any weapon or shield, stops all of the hit's damage.");
			AnyBlockerCanParry = BindShared("Parry", "AnyBlockerCanParry", defaultValue: true, "Every weapon and shield can parry, including tower shields and anything else with no parry bonus.");
			FistsCanParry = BindShared("Parry", "FistsCanParry", defaultValue: false, "Allows parrying while blocking with your bare fists, with no weapon or shield in your hands.");
			LogStagger = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "LogStagger", false, "Log every parry's Block skill check: your skill, the skill the attacker needs, and whether it was staggered.");
			StaggerSkill = BindShared("Parry", "StaggerBlockSkill", "Meadows=10,BlackForest=20,Swamp=30,Mountain=40,Plains=50,Mistlands=60,AshLands=70,DeepNorth=80,Ocean=30", "Comma separated Biome=Level pairs. A parry only staggers the attacker when your Block skill is at least the level for the attacker's biome.");
			CreatureBiomes = BindShared("Parry", "CreatureBiomes", "", "Comma separated CreaturePrefab=Biome pairs that set which biome a creature counts as. Creatures not listed use the biome they spawn in naturally, or else the biome they are standing in.");
			ShieldArmorWhileBlocking = BindShared("Shields", "ArmorWhileBlocking", defaultValue: true, "While you hold a shield up, its block armor is added to your armor.");
			ShieldArmorMultiplier = BindShared("Shields", "ArmorMultiplier", 1f, new ConfigDescription("The shield's block armor is multiplied by this before it is added to your armor.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>()));
			WeaponArmorWhileBlocking = BindShared("Weapons", "ArmorWhileBlocking", defaultValue: true, "While you block with a weapon, its block armor is added to your armor, like a shield.");
			WeaponArmorMultiplier = BindShared("Weapons", "ArmorMultiplier", 1f, new ConfigDescription("The weapon's block armor is multiplied by this before it is added to your armor.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>()));
			RemoveShieldParryBonus = BindShared("Shields", "RemoveParryBonus", defaultValue: true, "Shields lose their parry bonus. Parrying with a shield still stops the hit, the bonus just no longer adds to the block.");
			BucklerPenalty = BindShared("Shields", "BucklerMovementPenalty", 3f, new ConfigDescription("Movement speed penalty, in percent, while a buckler is equipped.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>()));
			RoundPenalty = BindShared("Shields", "RoundShieldMovementPenalty", 5f, new ConfigDescription("Movement speed penalty, in percent, while a round shield is equipped.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>()));
			TowerPenalty = BindShared("Shields", "TowerShieldMovementPenalty", 8f, new ConfigDescription("Movement speed penalty, in percent, while a tower shield is equipped.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>()));
			StaggerSkill.SettingChanged += delegate
			{
				CreatureTier.Clear();
			};
			CreatureBiomes.SettingChanged += delegate
			{
				CreatureTier.Clear();
			};
			RemoveShieldParryBonus.SettingChanged += delegate
			{
				Shields.Apply();
			};
			BucklerPenalty.SettingChanged += delegate
			{
				Shields.Apply();
			};
			RoundPenalty.SettingChanged += delegate
			{
				Shields.Apply();
			};
			TowerPenalty.SettingChanged += delegate
			{
				Shields.Apply();
			};
			new Harmony("com.dreich.parryrework").PatchAll();
		}

		private ConfigEntry<T> BindShared<T>(string section, string key, T defaultValue, string description)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			return BindShared(section, key, defaultValue, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()));
		}

		private ConfigEntry<T> BindShared<T>(string section, string key, T defaultValue, ConfigDescription description)
		{
			ConfigEntry<T> val = ((BaseUnityPlugin)this).Config.Bind<T>(section, key, defaultValue, description);
			if (ConfigSyncAvailable)
			{
				ConfigSyncCompat.AddConfigEntry<T>(val, serverControlled: true);
			}
			return val;
		}
	}
	internal static class ConfigSyncCompat
	{
		private static object configSync;

		[MethodImpl(MethodImplOptions.NoInlining)]
		internal static void Initialize(string guid, string name, string version)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			configSync = (object)new ConfigSync(guid)
			{
				DisplayName = name,
				CurrentVersion = version,
				MinimumRequiredVersion = version,
				ModRequired = true
			};
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		internal static void AddLockingConfigEntry(ConfigEntry<bool> entry)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			((ConditionalConfigSync)(ConfigSync)configSync).AddLockingConfigEntry<bool>(entry);
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		internal static void AddConfigEntry<T>(ConfigEntry<T> entry, bool serverControlled)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			((ConditionalConfigSync)(ConfigSync)configSync).AddConfigEntry<T>(entry, (ConfigSyncMode)((!serverControlled) ? 2 : 0));
		}
	}
	internal static class CreatureTier
	{
		private static Dictionary<string, Biome> spawnBiomes;

		private static Dictionary<string, Biome> overrides;

		private static Dictionary<Biome, int> levels;

		private static readonly Biome[] Order;

		internal static void Clear()
		{
			overrides = null;
			levels = null;
		}

		internal static int RequiredLevel(Character attacker)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			Biome key = BiomeOf(attacker);
			Levels().TryGetValue(key, out var value);
			return value;
		}

		private static Dictionary<Biome, int> Levels()
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			if (levels != null)
			{
				return levels;
			}
			levels = new Dictionary<Biome, int>();
			string[] array = ParryReworkPlugin.StaggerSkill.Value.Split(new char[1] { ',' });
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Split(new char[1] { '=' });
				if (array2.Length == 2 && Enum.TryParse<Biome>(array2[0].Trim(), ignoreCase: true, out Biome result) && int.TryParse(array2[1].Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result2))
				{
					levels[result] = result2;
				}
			}
			return levels;
		}

		private static Biome BiomeOf(Character attacker)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			string prefabName = Utils.GetPrefabName(((Component)attacker).gameObject);
			if (Overrides().TryGetValue(prefabName, out var value))
			{
				return value;
			}
			if (SpawnBiomes().TryGetValue(prefabName, out var value2))
			{
				return value2;
			}
			Vector3 position = ((Component)attacker).transform.position;
			if (WorldGenerator.instance == null)
			{
				return (Biome)1;
			}
			return WorldGenerator.instance.GetBiome(position);
		}

		private static Dictionary<string, Biome> Overrides()
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			if (overrides != null)
			{
				return overrides;
			}
			overrides = new Dictionary<string, Biome>(StringComparer.OrdinalIgnoreCase);
			string[] array = ParryReworkPlugin.CreatureBiomes.Value.Split(new char[1] { ',' });
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Split(new char[1] { '=' });
				if (array2.Length == 2 && Enum.TryParse<Biome>(array2[1].Trim(), ignoreCase: true, out Biome result))
				{
					overrides[array2[0].Trim()] = result;
				}
			}
			return overrides;
		}

		private static Dictionary<string, Biome> SpawnBiomes()
		{
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: 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_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			if (spawnBiomes != null && spawnBiomes.Count > 0)
			{
				return spawnBiomes;
			}
			spawnBiomes = new Dictionary<string, Biome>(StringComparer.OrdinalIgnoreCase);
			SpawnSystemList[] array = Resources.FindObjectsOfTypeAll<SpawnSystemList>();
			foreach (SpawnSystemList val in array)
			{
				if ((Object)(object)val == (Object)null || val.m_spawners == null)
				{
					continue;
				}
				foreach (SpawnData spawner in val.m_spawners)
				{
					if (spawner == null || !spawner.m_enabled || (Object)(object)spawner.m_prefab == (Object)null)
					{
						continue;
					}
					Biome val2 = Lowest(spawner.m_biome);
					if ((int)val2 != 0)
					{
						string name = ((Object)spawner.m_prefab).name;
						if (!spawnBiomes.TryGetValue(name, out var value) || Rank(val2) < Rank(value))
						{
							spawnBiomes[name] = val2;
						}
					}
				}
			}
			return spawnBiomes;
		}

		private static Biome Lowest(Biome flags)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: 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_0010: 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_0025: 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)
			Biome[] order = Order;
			foreach (Biome val in order)
			{
				if ((flags & val) != 0)
				{
					return val;
				}
			}
			if ((flags & 0x100) != 0)
			{
				return (Biome)256;
			}
			return (Biome)0;
		}

		private static int Rank(Biome biome)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			int num = Array.IndexOf(Order, biome);
			if (num >= 0)
			{
				return num;
			}
			return 2;
		}

		static CreatureTier()
		{
			Biome[] array = new Biome[8];
			RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
			Order = (Biome[])(object)array;
		}
	}
	internal static class Shields
	{
		private static readonly Dictionary<SharedData, (float movement, float parry)> originals = new Dictionary<SharedData, (float, float)>();

		internal static bool IsShield(ItemData item)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Invalid comparison between Unknown and I4
			if (item != null && item.m_shared != null)
			{
				return (int)item.m_shared.m_itemType == 5;
			}
			return false;
		}

		internal static void Apply()
		{
			ObjectDB instance = ObjectDB.instance;
			if ((Object)(object)instance == (Object)null || instance.m_items == null)
			{
				return;
			}
			foreach (GameObject item in instance.m_items)
			{
				ItemDrop val = (((Object)(object)item != (Object)null) ? item.GetComponent<ItemDrop>() : null);
				if (!((Object)(object)val == (Object)null) && IsShield(val.m_itemData))
				{
					SharedData shared = val.m_itemData.m_shared;
					if (!originals.ContainsKey(shared))
					{
						originals[shared] = (shared.m_movementModifier, shared.m_timedBlockBonus);
					}
					string text = ((Object)item).name.ToLowerInvariant();
					float num = (text.Contains("tower") ? ParryReworkPlugin.TowerPenalty.Value : (text.Contains("buckler") ? ParryReworkPlugin.BucklerPenalty.Value : ParryReworkPlugin.RoundPenalty.Value));
					shared.m_movementModifier = (0f - num) / 100f;
					shared.m_timedBlockBonus = (ParryReworkPlugin.RemoveShieldParryBonus.Value ? 1f : originals[shared].parry);
				}
			}
		}
	}
	[HarmonyPatch(typeof(ObjectDB), "Awake")]
	internal static class ObjectDBAwakePatch
	{
		private static void Postfix()
		{
			Shields.Apply();
		}
	}
	[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
	internal static class ObjectDBCopyPatch
	{
		private static void Postfix()
		{
			Shields.Apply();
		}
	}
	[HarmonyPatch(typeof(Humanoid), "BlockAttack")]
	internal static class ParryPatch
	{
		private static readonly FieldRef<Humanoid, float> BlockTimer = AccessTools.FieldRefAccess<Humanoid, float>("m_blockTimer");

		private static readonly FieldRef<Humanoid, int> BlockCharges = AccessTools.FieldRefAccess<Humanoid, int>("m_blockCharges");

		private static readonly FieldRef<Humanoid, float> BlockChargeTimer = AccessTools.FieldRefAccess<Humanoid, float>("m_blockChargeRemoveTimer");

		private static readonly FieldRef<Humanoid, VisEquipment> Visual = AccessTools.FieldRefAccess<Humanoid, VisEquipment>("m_visEquipment");

		private static readonly FieldRef<Character, Rigidbody> Body = AccessTools.FieldRefAccess<Character, Rigidbody>("m_body");

		private static readonly MethodInfo CurrentBlocker = AccessTools.Method(typeof(Humanoid), "GetCurrentBlocker", (Type[])null, (Type[])null);

		private static SharedData suppressed;

		private static float suppressedBonus;

		internal static Player Blocking;

		[HarmonyPriority(600)]
		private static bool Prefix(Humanoid __instance, HitData hit, Character attacker, ref bool __result)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Player val = (Player)(object)((__instance is Player) ? __instance : null);
				if ((Object)(object)val == (Object)null)
				{
					return true;
				}
				Blocking = val;
				if (!ParryReworkPlugin.ParryNegatesDamage.Value)
				{
					return true;
				}
				if (Vector3.Dot(hit.m_dir, ((Component)__instance).transform.forward) > 0f)
				{
					return true;
				}
				object? obj = CurrentBlocker.Invoke(__instance, null);
				ItemData val2 = (ItemData)((obj is ItemData) ? obj : null);
				if (val2 == null)
				{
					return true;
				}
				if (IsFists(val, val2) && !ParryReworkPlugin.FistsCanParry.Value)
				{
					SuppressParry(val2);
					return true;
				}
				if (!ParryReworkPlugin.AnyBlockerCanParry.Value && val2.m_shared.m_timedBlockBonus <= 1f && !Shields.IsShield(val2))
				{
					return true;
				}
				float num = BlockTimer.Invoke(__instance);
				if (num == -1f || num >= 0.25f)
				{
					return true;
				}
				float perfectBlockStaminaDrain = __instance.m_perfectBlockStaminaDrain;
				perfectBlockStaminaDrain += perfectBlockStaminaDrain * ((Character)__instance).GetEquipmentBlockStaminaModifier();
				((Character)__instance).GetSEMan().ModifyBlockStaminaUsage(perfectBlockStaminaDrain, ref perfectBlockStaminaDrain, false);
				if (perfectBlockStaminaDrain > 0f && !((Character)__instance).HaveStamina(perfectBlockStaminaDrain))
				{
					return true;
				}
				if (perfectBlockStaminaDrain > 0f)
				{
					((Character)__instance).UseStamina(perfectBlockStaminaDrain);
				}
				else
				{
					((Character)__instance).AddStamina(0f - perfectBlockStaminaDrain);
				}
				Parry(val, val2, hit, attacker);
				__result = true;
				return false;
			}
			catch (Exception ex)
			{
				ParryReworkPlugin.Log.LogWarning((object)("Parry failed, falling back to the normal block: " + ex.Message));
				return true;
			}
		}

		internal static bool IsFists(Player player, ItemData blocker)
		{
			ItemDrop unarmedWeapon = ((Humanoid)player).m_unarmedWeapon;
			if ((Object)(object)unarmedWeapon != (Object)null && unarmedWeapon.m_itemData != null)
			{
				return blocker.m_shared == unarmedWeapon.m_itemData.m_shared;
			}
			return false;
		}

		private static void SuppressParry(ItemData blocker)
		{
			suppressed = blocker.m_shared;
			suppressedBonus = suppressed.m_timedBlockBonus;
			suppressed.m_timedBlockBonus = 1f;
		}

		internal static bool HasStaggerTrait(Player player)
		{
			if (!ParryReworkPlugin.TreasureMapsAvailable)
			{
				return false;
			}
			ItemData val = (((Object)(object)player != (Object)null) ? ((Humanoid)player).GetCurrentWeapon() : null);
			if (val != null && val.m_customData != null && val.m_customData.Count > 0 && val.m_customData.TryGetValue("TreasureMaps_ChampionTrait", out var value))
			{
				return value == "ParryStagger";
			}
			return false;
		}

		internal static bool CanStagger(Player player, Character attacker)
		{
			if (HasStaggerTrait(player))
			{
				if (ParryReworkPlugin.LogStagger.Value)
				{
					ParryReworkPlugin.Log.LogInfo((object)("Parry against " + attacker.m_name + ": Staggering Parry weapon, staggered"));
				}
				return true;
			}
			int num = CreatureTier.RequiredLevel(attacker);
			bool flag = ((Character)player).GetSkillLevel((SkillType)6) >= (float)num;
			if (ParryReworkPlugin.LogStagger.Value)
			{
				ParryReworkPlugin.Log.LogInfo((object)("Parry against " + attacker.m_name + ": Block " + Mathf.FloorToInt(((Character)player).GetSkillLevel((SkillType)6)) + ", needs " + num + (flag ? ", staggered" : ", no stagger")));
			}
			return flag;
		}

		private static void Finalizer()
		{
			Blocking = null;
			if (suppressed != null)
			{
				suppressed.m_timedBlockBonus = suppressedBonus;
				suppressed = null;
			}
		}

		private static void Parry(Player player, ItemData blocker, HitData hit, Character attacker)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: 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_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Expected O, but got Unknown
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Max(1f, blocker.GetBlockPower(((Character)player).GetSkillFactor((SkillType)6)));
			float totalDamage = hit.GetTotalDamage();
			hit.m_statusEffectHash = 0;
			hit.m_damage = default(DamageTypes);
			hit.m_pushForce = 0f;
			DamageText instance = DamageText.instance;
			if (instance != null)
			{
				instance.ShowText((TextType)6, hit.m_point + Vector3.up * 0.5f, totalDamage, false);
			}
			if (blocker.m_shared.m_useDurability)
			{
				blocker.m_durability -= blocker.m_shared.m_useDurabilityDrain * (totalDamage / num) * Game.m_durabilityRate;
			}
			((Character)player).RaiseSkill((SkillType)6, 2f);
			blocker.m_shared.m_blockEffect.Create(hit.m_point, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID));
			BlockCharge(player, blocker);
			((Humanoid)player).m_perfectBlockEffect.Create(hit.m_point, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID));
			((Character)player).AddAdrenaline(blocker.m_shared.m_perfectBlockAdrenaline);
			if ((Object)(object)attacker != (Object)null && (attacker.m_staggerWhenBlocked || HasStaggerTrait(player)))
			{
				attacker.Stagger(-hit.m_dir);
			}
			float perfectBlockStaminaRegen = blocker.m_shared.m_perfectBlockStaminaRegen;
			if (perfectBlockStaminaRegen > 0f)
			{
				((Character)player).AddStamina(perfectBlockStaminaRegen);
			}
			else
			{
				float perfectBlockStaminaDrain = ((Humanoid)player).m_perfectBlockStaminaDrain;
				perfectBlockStaminaDrain -= perfectBlockStaminaDrain * ((Character)player).GetEquipmentBlockStaminaModifier();
				((Character)player).GetSEMan().ModifyBlockStaminaUsage(perfectBlockStaminaDrain, ref perfectBlockStaminaDrain, false);
				if (perfectBlockStaminaDrain > 0f)
				{
					((Character)player).UseStamina(perfectBlockStaminaDrain);
				}
				else
				{
					((Character)player).AddStamina(0f - perfectBlockStaminaDrain);
				}
			}
			StatusEffect val = (((Object)(object)blocker.m_shared.m_perfectBlockStatusEffect != (Object)null) ? blocker.m_shared.m_perfectBlockStatusEffect : ((Humanoid)player).m_perfectBlockStatusEffect);
			if ((Object)(object)val != (Object)null)
			{
				((Character)player).GetSEMan().AddStatusEffect(val, true, blocker.m_worldLevel, ((Character)player).GetSkillLevel((SkillType)6), (short)(-1));
			}
			if ((Object)(object)attacker != (Object)null && !hit.m_ranged)
			{
				HitData val2 = new HitData
				{
					m_pushForce = blocker.GetDeflectionForce() * 0.5f,
					m_staggerMultiplier = 0f
				};
				Vector3 val3 = ((Component)attacker).transform.position - ((Component)player).transform.position;
				val3.y = 0f;
				val2.m_dir = ((Vector3)(ref val3)).normalized;
				attacker.Damage(val2);
			}
		}

		private static void BlockCharge(Player player, ItemData blocker)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: 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_0066: Unknown result type (might be due to invalid IL or missing references)
			if (blocker.m_shared.m_buildBlockCharges)
			{
				BlockCharges.Invoke((Humanoid)(object)player)++;
				BlockChargeTimer.Invoke((Humanoid)(object)player) = 0f;
				VisEquipment val = Visual.Invoke((Humanoid)(object)player);
				Vector3 val2 = (((Object)(object)val != (Object)null && (Object)(object)val.m_leftHand != (Object)null) ? val.m_leftHand.position : ((Component)player).transform.position);
				blocker.m_shared.m_blockChargeEffects.Create(val2, ((Component)player).transform.rotation, (Transform)null, 1f, BlockCharges.Invoke((Humanoid)(object)player), default(ZDOID));
				if (BlockCharges.Invoke((Humanoid)(object)player) >= blocker.m_shared.m_maxBlockCharges)
				{
					blocker.m_shared.m_attack.StartWithoutAnimation((Humanoid)(object)player, Body.Invoke((Character)(object)player), val, blocker, 0f);
					BlockCharges.Invoke((Humanoid)(object)player) = 0;
				}
			}
		}
	}
	[HarmonyPatch(typeof(Character), "Stagger")]
	internal static class BlockStaggerGuard
	{
		private static bool Prefix(Character __instance)
		{
			Player blocking = ParryPatch.Blocking;
			if ((Object)(object)blocking == (Object)null || (Object)(object)__instance == (Object)(object)blocking || __instance is Player)
			{
				return true;
			}
			return ParryPatch.CanStagger(blocking, __instance);
		}
	}
	[HarmonyPatch(typeof(Player), "GetBodyArmor")]
	internal static class ShieldArmorPatch
	{
		private static readonly MethodInfo CurrentBlocker = AccessTools.Method(typeof(Humanoid), "GetCurrentBlocker", (Type[])null, (Type[])null);

		private static void Postfix(Player __instance, ref float __result)
		{
			try
			{
				if (!((Character)__instance).IsBlocking())
				{
					return;
				}
				object? obj = CurrentBlocker.Invoke(__instance, null);
				ItemData val = (ItemData)((obj is ItemData) ? obj : null);
				if (val == null)
				{
					return;
				}
				float value;
				if (Shields.IsShield(val))
				{
					if (!ParryReworkPlugin.ShieldArmorWhileBlocking.Value)
					{
						return;
					}
					value = ParryReworkPlugin.ShieldArmorMultiplier.Value;
				}
				else
				{
					if (!ParryReworkPlugin.WeaponArmorWhileBlocking.Value || !WeaponArmor.IsWeapon(val))
					{
						return;
					}
					value = ParryReworkPlugin.WeaponArmorMultiplier.Value;
				}
				__result += val.GetBlockPower(((Character)__instance).GetSkillFactor((SkillType)6)) * value;
			}
			catch (Exception)
			{
			}
		}
	}
	[HarmonyPatch(typeof(ItemData), "GetTooltip", new Type[]
	{
		typeof(ItemData),
		typeof(int),
		typeof(bool),
		typeof(float),
		typeof(int),
		typeof(bool)
	})]
	internal static class ShieldTooltipPatch
	{
		private static readonly Regex ParryLine = new Regex("\\n\\$item_parrybonus:[^\\n]*");

		private static void Postfix(ItemData item, ref string __result)
		{
			if (Shields.IsShield(item) && !string.IsNullOrEmpty(__result) && ParryReworkPlugin.RemoveShieldParryBonus.Value)
			{
				__result = ParryLine.Replace(__result, "");
			}
		}
	}
	internal static class WeaponArmor
	{
		internal static bool IsWeapon(ItemData item)
		{
			//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_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Invalid comparison between Unknown and I4
			//IL_0037: 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)
			//IL_003c: Invalid comparison between Unknown and I4
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Invalid comparison between Unknown and I4
			if (item == null || (Object)(object)item.m_dropPrefab == (Object)null || item.m_shared.m_blockPower <= 0f)
			{
				return false;
			}
			ItemType itemType = item.m_shared.m_itemType;
			if (itemType - 3 <= 1 || itemType - 14 <= 1 || (int)itemType == 22)
			{
				return true;
			}
			return false;
		}
	}
}