Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ParryRework v1.0.3
ParryRework.dll
Decompiled 3 days agousing 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; } } }