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 ParryAndDodgeConfig v1.1.2
BepInEx\plugins\ParryAndDodgeConfig\ParryAndDodgeConfig.dll
Decompiled a week agousing 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."); } } } }