Please disclose if your mod was created primarily 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 ShieldOverflowFix v1.0.0
plugins/ShieldOverflowFix.dll
Decompiled 2 days agousing System; using System.Collections.Generic; 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.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("ShieldOverflowFix")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("ShieldOverflowFix")] [assembly: AssemblyTitle("ShieldOverflowFix")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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; } } } [BepInPlugin("ShieldOverflowFix", "Shield Overflow Fix", "1.0.0")] public class ShieldOverflowPlugin : BaseUnityPlugin { internal static ConfigEntry<bool> EnableShieldRecastReplace; internal static ConfigEntry<bool> EnableShieldOverflowFix; internal static ConfigEntry<bool> EnableShieldColorChange; internal static ConfigEntry<bool> UseOriginalShieldColorAsStartColor; internal static ConfigEntry<string> StartShieldColorHex; internal static ConfigEntry<string> DamagedShieldColorHex; internal static ConfigEntry<bool> ShowShieldDamageNumbers; private void Awake() { //IL_00ee: Unknown result type (might be due to invalid IL or missing references) EnableShieldOverflowFix = ((BaseUnityPlugin)this).Config.Bind<bool>("Combat", "EnableShieldOverflowFix", true, "Fixes shield overflow. Damage beyond the shield's remaining health will spill through instead of being completely blocked."); EnableShieldRecastReplace = ((BaseUnityPlugin)this).Config.Bind<bool>("Combat", "EnableShieldRecastReplace", true, "Recasting Staff of Protection refreshes the shield's health instead of only refreshing its timer."); ShowShieldDamageNumbers = ((BaseUnityPlugin)this).Config.Bind<bool>("Combat", "ShowShieldDamageNumbers", true, "Show floating damage numbers for damage absorbed by the shield."); EnableShieldColorChange = ((BaseUnityPlugin)this).Config.Bind<bool>("Visual", "EnableShieldColorChange", true, "Shield color changes based on how much shield health has been lost."); UseOriginalShieldColorAsStartColor = ((BaseUnityPlugin)this).Config.Bind<bool>("Visual", "UseOriginalShieldColorAsStartColor", true, "If true, the shield starts from its vanilla in-game color."); StartShieldColorHex = ((BaseUnityPlugin)this).Config.Bind<string>("Visual", "StartShieldColorHex", "#66D9FF80", "Starting shield color when UseOriginalShieldColorAsStartColor is false."); DamagedShieldColorHex = ((BaseUnityPlugin)this).Config.Bind<string>("Visual", "DamagedShieldColorHex", "#4DA6FFFF", "Color the shield approaches as it loses health."); new Harmony("ShieldOverflowFix").PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"ShieldOverflowFix loaded (1.0.0)"); } } internal static class ShieldRefs { internal static readonly FieldRef<SE_Shield, float> TotalAbsorb = AccessTools.FieldRefAccess<SE_Shield, float>("m_totalAbsorbDamage"); internal static readonly FieldRef<SE_Shield, float> Damage = AccessTools.FieldRefAccess<SE_Shield, float>("m_damage"); internal static readonly FieldRef<StatusEffect, Character> CharacterRef = AccessTools.FieldRefAccess<StatusEffect, Character>("m_character"); internal static readonly FieldRef<SE_Shield, EffectList> HitEffects = AccessTools.FieldRefAccess<SE_Shield, EffectList>("m_hitEffects"); internal static readonly FieldRef<StatusEffect, GameObject[]> StartEffectInstances = AccessTools.FieldRefAccess<StatusEffect, GameObject[]>("m_startEffectInstances"); internal static float GetRelevantDamage(HitData hit) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: 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_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002a: 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_0038: Unknown result type (might be due to invalid IL or missing references) DamageTypes damage = hit.m_damage; return damage.m_blunt + damage.m_slash + damage.m_pierce + damage.m_fire + damage.m_frost + damage.m_lightning + damage.m_poison + damage.m_spirit; } } internal static class ShieldRecastController { private static SE_Shield PendingRefreshShield; public static void MarkIfStaffRecast(SE_Shield shield, HitData hit, Character attacker) { if (!ShieldOverflowPlugin.EnableShieldRecastReplace.Value || (Object)(object)shield == (Object)null || hit == null || ((Object)shield).name != "Staff_shield") { return; } Character val = ShieldRefs.CharacterRef.Invoke((StatusEffect)(object)shield); if (val is Player && !((Object)(object)attacker != (Object)(object)val)) { float relevantDamage = ShieldRefs.GetRelevantDamage(hit); if (!(relevantDamage > 0f)) { PendingRefreshShield = shield; } } } public static bool TryConsume(StatusEffect effect, out SE_Shield shield) { shield = null; if (!ShieldOverflowPlugin.EnableShieldRecastReplace.Value) { return false; } SE_Shield val = (SE_Shield)(object)((effect is SE_Shield) ? effect : null); if (val == null) { return false; } if (val != PendingRefreshShield) { return false; } PendingRefreshShield = null; shield = val; return true; } public static void Clear(SE_Shield shield) { if (PendingRefreshShield == shield) { PendingRefreshShield = null; } } } [HarmonyPatch(typeof(SE_Shield), "OnDamaged")] public static class ShieldOverflowPatch { private static bool Prefix(SE_Shield __instance, HitData hit, Character attacker) { //IL_02a7: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Unknown result type (might be due to invalid IL or missing references) //IL_02b2: Unknown result type (might be due to invalid IL or missing references) //IL_02b7: Unknown result type (might be due to invalid IL or missing references) ShieldRecastController.MarkIfStaffRecast(__instance, hit, attacker); float relevantDamage = ShieldRefs.GetRelevantDamage(hit); if (relevantDamage <= 0f) { return false; } float num = ShieldRefs.TotalAbsorb.Invoke(__instance); if (num <= 0f) { return true; } float num2 = ShieldRefs.Damage.Invoke(__instance); float num3 = num - num2; if (num3 <= 0f) { return true; } float num4; if (relevantDamage <= num3) { num4 = relevantDamage; ShieldRefs.Damage.Invoke(__instance) = num2 + relevantDamage; hit.m_damage.m_blunt = 0f; hit.m_damage.m_slash = 0f; hit.m_damage.m_pierce = 0f; hit.m_damage.m_fire = 0f; hit.m_damage.m_frost = 0f; hit.m_damage.m_lightning = 0f; hit.m_damage.m_poison = 0f; hit.m_damage.m_spirit = 0f; } else { num4 = num3; if (ShieldOverflowPlugin.EnableShieldOverflowFix.Value) { float num5 = relevantDamage - num3; ShieldRefs.Damage.Invoke(__instance) = num + 0.01f; float num6 = num5 / relevantDamage; hit.m_damage.m_blunt *= num6; hit.m_damage.m_slash *= num6; hit.m_damage.m_pierce *= num6; hit.m_damage.m_fire *= num6; hit.m_damage.m_frost *= num6; hit.m_damage.m_lightning *= num6; hit.m_damage.m_poison *= num6; hit.m_damage.m_spirit *= num6; } else { ShieldRefs.Damage.Invoke(__instance) = num + 0.01f; hit.m_damage.m_blunt = 0f; hit.m_damage.m_slash = 0f; hit.m_damage.m_pierce = 0f; hit.m_damage.m_fire = 0f; hit.m_damage.m_frost = 0f; hit.m_damage.m_lightning = 0f; hit.m_damage.m_poison = 0f; hit.m_damage.m_spirit = 0f; } } Character val = ShieldRefs.CharacterRef.Invoke((StatusEffect)(object)__instance); if ((Object)(object)val != (Object)null) { ShieldRefs.HitEffects.Invoke(__instance).Create(hit.m_point, Quaternion.LookRotation(-hit.m_dir), ((Component)val).transform, 1f, -1); ShieldColorController.ApplyShieldStateColor(__instance); if (ShieldOverflowPlugin.ShowShieldDamageNumbers.Value && num4 > 0f) { ShieldDamageText.Show(hit, val, num4); } } return false; } } [HarmonyPatch(typeof(StatusEffect), "ResetTime")] public static class ShieldResetTimePatch { private static void Postfix(StatusEffect __instance) { if (ShieldRecastController.TryConsume(__instance, out var shield)) { ShieldRefs.Damage.Invoke(shield) = 0f; ShieldColorController.ApplyShieldStateColor(shield); } } } public static class ShieldColorController { private sealed class TrackedMaterial { public Material Material; public Color OriginalColor; public bool HasColor; public bool HasBaseColor; public bool HasTintColor; public bool HasEmissionColor; } private static readonly Dictionary<SE_Shield, List<TrackedMaterial>> Cache = new Dictionary<SE_Shield, List<TrackedMaterial>>(); public static void ApplyShieldStateColor(SE_Shield shield) { //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0122: 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_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)shield == (Object)null) { return; } float num = ShieldRefs.TotalAbsorb.Invoke(shield); if (num <= 0f) { return; } List<TrackedMaterial> materials = GetMaterials(shield); if (materials.Count == 0) { return; } float num2 = Mathf.Clamp(ShieldRefs.Damage.Invoke(shield), 0f, num); float num3 = (ShieldOverflowPlugin.EnableShieldColorChange.Value ? Mathf.Clamp01(num2 / num) : 0f); Color val = ParseColor(ShieldOverflowPlugin.StartShieldColorHex.Value, new Color(0.4f, 0.85f, 1f, 0.5f)); Color val2 = ParseColor(ShieldOverflowPlugin.DamagedShieldColorHex.Value, new Color(0.3f, 0.65f, 1f, 1f)); for (int num4 = materials.Count - 1; num4 >= 0; num4--) { TrackedMaterial trackedMaterial = materials[num4]; if (trackedMaterial == null || (Object)(object)trackedMaterial.Material == (Object)null) { materials.RemoveAt(num4); } else { Color val3 = (ShieldOverflowPlugin.UseOriginalShieldColorAsStartColor.Value ? trackedMaterial.OriginalColor : val); Color color = Color.Lerp(val3, val2, num3); ApplyColor(trackedMaterial, color); } } } public static void ClearShield(SE_Shield shield) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)shield == (Object)null) { return; } ShieldRecastController.Clear(shield); if (!Cache.TryGetValue(shield, out var value)) { return; } foreach (TrackedMaterial item in value) { if (item != null && (Object)(object)item.Material != (Object)null) { ApplyColor(item, item.OriginalColor); } } Cache.Remove(shield); } private static List<TrackedMaterial> GetMaterials(SE_Shield shield) { //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) if (Cache.TryGetValue(shield, out var value)) { return value; } List<TrackedMaterial> list = new List<TrackedMaterial>(); GameObject[] array = ShieldRefs.StartEffectInstances.Invoke((StatusEffect)(object)shield); if (array != null) { GameObject[] array2 = array; foreach (GameObject val in array2) { if (!Object.op_Implicit((Object)(object)val)) { continue; } Renderer[] componentsInChildren = val.GetComponentsInChildren<Renderer>(true); Renderer[] array3 = componentsInChildren; foreach (Renderer val2 in array3) { if (!Object.op_Implicit((Object)(object)val2)) { continue; } Material[] materials = val2.materials; if (materials == null || materials.Length == 0) { continue; } Material[] array4 = materials; foreach (Material val3 in array4) { if (Object.op_Implicit((Object)(object)val3)) { TrackedMaterial trackedMaterial = new TrackedMaterial { Material = val3, HasColor = val3.HasProperty("_Color"), HasBaseColor = val3.HasProperty("_BaseColor"), HasTintColor = val3.HasProperty("_TintColor"), HasEmissionColor = val3.HasProperty("_EmissionColor") }; trackedMaterial.OriginalColor = ReadColor(trackedMaterial, Color.white); list.Add(trackedMaterial); } } } } } Cache[shield] = list; return list; } private static Color ReadColor(TrackedMaterial tracked, Color fallback) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: 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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0070: 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_006c: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) Material material = tracked.Material; if (tracked.HasColor) { return material.GetColor("_Color"); } if (tracked.HasBaseColor) { return material.GetColor("_BaseColor"); } if (tracked.HasTintColor) { return material.GetColor("_TintColor"); } if (tracked.HasEmissionColor) { return material.GetColor("_EmissionColor"); } return fallback; } private static void ApplyColor(TrackedMaterial tracked, Color color) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) Material material = tracked.Material; if (tracked.HasColor) { material.SetColor("_Color", color); } if (tracked.HasBaseColor) { material.SetColor("_BaseColor", color); } if (tracked.HasTintColor) { material.SetColor("_TintColor", color); } if (tracked.HasEmissionColor) { material.SetColor("_EmissionColor", color); } } private static Color ParseColor(string value, Color fallback) { //IL_000b: 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) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrWhiteSpace(value)) { return fallback; } if (!value.StartsWith("#")) { value = "#" + value; } Color result = default(Color); if (ColorUtility.TryParseHtmlString(value, ref result)) { return result; } return fallback; } } public static class ShieldDamageText { public static void Show(HitData hit, Character character, float amount) { //IL_002c: 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_0032: 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_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)DamageText.instance == (Object)null) && !((Object)(object)character == (Object)null) && !(amount <= 0f)) { Vector3 val = hit.m_point; if (val == Vector3.zero) { val = character.GetCenterPoint(); } DamageText.instance.ShowText((TextType)0, val, amount, false); } } } [HarmonyPatch(typeof(StatusEffect), "UpdateStatusEffect")] public static class ShieldUpdatePatch { private static void Postfix(StatusEffect __instance) { SE_Shield val = (SE_Shield)(object)((__instance is SE_Shield) ? __instance : null); if (val != null) { ShieldColorController.ApplyShieldStateColor(val); } } } [HarmonyPatch(typeof(StatusEffect), "Stop")] public static class ShieldStopPatch { private static void Postfix(StatusEffect __instance) { SE_Shield val = (SE_Shield)(object)((__instance is SE_Shield) ? __instance : null); if (val != null) { ShieldColorController.ClearShield(val); } } }