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 ImprovedMagicShield v1.2.2
BepInEx/plugins/ImprovedMagicShield/ImprovedMagicShield.dll
Decompiled 2 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; using ImprovedMagicShield.Visuals; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: AssemblyCompany("ImprovedMagicShield")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.2.2.0")] [assembly: AssemblyInformationalVersion("1.2.2+e2da7d7dcd13a819baa3c91349153a8173ea9902")] [assembly: AssemblyProduct("ImprovedMagicShield")] [assembly: AssemblyTitle("ImprovedMagicShield")] [assembly: AssemblyVersion("1.2.2.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 ImprovedMagicShield { internal static class DisplayPolicy { internal const double FreshSeconds = 2.0; internal static float ProtectionFraction(float remaining, float capacity) { if (!(remaining > 0f) || !(capacity > 0f) || float.IsInfinity(remaining) || float.IsInfinity(capacity)) { return 0f; } return Math.Min(1f, remaining / capacity); } internal static float SnapshotAlpha(double activityAt, double now) { if (activityAt < 0.0 || activityAt > now + 2.0 || double.IsNaN(activityAt)) { return 0f; } return HudPolicy.Alpha((float)Math.Max(0.0, now - activityAt)); } internal static bool IsFresh(float remaining, double sampledAt, double now, long publisher, long owner) { double num = now - sampledAt; if (remaining > 0f && !float.IsInfinity(remaining) && publisher == owner && num >= -2.0) { return num <= 2.0; } return false; } internal static int WholeProtection(float remaining) { return (int)Math.Min(2147483647.0, Math.Max(0.0, Math.Floor(remaining))); } } internal static class HudPolicy { internal static bool TryRead(SE_Shield shield, out float remaining, out float capacity) { remaining = (capacity = 0f); if ((Object)(object)shield == (Object)null || (((StatusEffect)shield).m_ttl > 0f && ((StatusEffect)shield).GetDuration() > ((StatusEffect)shield).m_ttl)) { return false; } remaining = ShieldRefresh.Remaining(shield); capacity = ShieldRefresh.Capacity(shield); if (remaining > 0f && capacity > 0f && !float.IsInfinity(capacity)) { return !float.IsNaN(capacity); } return false; } internal static float Fraction(float remaining, float capacity) { if (!(capacity > 0f)) { return 0f; } return Math.Max(0f, Math.Min(1f, remaining / capacity)); } internal static float Width(float capacity, int protectionPerSegment) { return Math.Max(0f, capacity) / (float)Math.Max(1, protectionPerSegment) * 32f; } internal static float Alpha(float quietTime) { return Math.Max(0f, Math.Min(1f, 1f - (Math.Max(0f, quietTime) - 5f) / 0.5f)); } internal static string Text(float remaining, float capacity) { return DisplayPolicy.WholeProtection(remaining) + " / " + DisplayPolicy.WholeProtection(capacity); } } [BepInPlugin("Slikfoul.ImprovedMagicShield", "Improved Magic Shield", "1.2.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] [DefaultExecutionOrder(11000)] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "Slikfoul.ImprovedMagicShield"; public const string PluginVersion = "1.2.2"; private Harmony harmony; private static ConfigEntry<bool> modEnabled; private static ConfigEntry<bool> showProtection; private static ConfigEntry<bool> showHud; private static ConfigEntry<bool> showHealthOutline; private static ConfigEntry<int> labelScale; private static ConfigEntry<int> protectionPerSegment; private static ConfigEntry<int> labelOffset; private static bool hooksReady; private ShieldLabels labels; private ShieldHud shieldHud; private ShieldVisualController shieldVisuals; internal static bool IsEnabled { get { if (hooksReady && modEnabled != null) { return modEnabled.Value; } return false; } } private void Awake() { //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected O, but got Unknown //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Expected O, but got Unknown //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Expected O, but got Unknown //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Expected O, but got Unknown //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Expected O, but got Unknown //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Expected O, but got Unknown modEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Enabled", true, "Enable improved shield refreshes, displays and optional appearance controls. Disabling restores vanilla behavior for subsequent casts without removing active shields."); showProtection = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Display", "Show remaining protection", false, "Show remaining shield protection above other eligible characters, never your own character. Use the shielded character's cast, damage and combat activity to fade after five quiet seconds, independently of your combat. The owning peer needs this version to supply current protection and activity."); showHealthOutline = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Display", "Show shield health outline", false, "Draw a rounded, translucent purple contour outside other shielded characters' visible health bars. Its visible length follows remaining / full shield protection without a vertical end cap through health. Independent of protection numbers and the local shield bar; native health stays unchanged. The owning peer needs version 1.2.0 or newer to supply the actual shield capacity."); showHud = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Display", "Show local shield bar", true, "Show your own remaining / full shield protection in a fixed lower HUD row. Show for five seconds after a cast, shield damage or a vanilla notification that an alerted enemy targets you. Attack, block and bow inputs alone do not reveal the bar. Fade out after five quiet seconds, including damaged shields. Independent of the overhead labels."); labelScale = ((BaseUnityPlugin)this).Config.Bind<int>("2 - Display", "Label scale (%)", 80, new ConfigDescription("Size of the remaining-protection label, in percent.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(50, 300), Array.Empty<object>())); protectionPerSegment = ((BaseUnityPlugin)this).Config.Bind<int>("2 - Display", "Protection per segment", 50, new ConfigDescription("Full shield protection represented by one native 32-unit HUD segment. Lower values make the local bar longer. Width follows the currently applied shield, including another caster's shield. The frame keeps shrinking at higher values; its readable caption may extend beyond a short frame. Damage changes only the fill. Whole numbers only.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 500), Array.Empty<object>())); labelOffset = ((BaseUnityPlugin)this).Config.Bind<int>("2 - Display", "Label vertical offset", -20, new ConfigDescription("Move remaining-protection labels relative to their automatic position: above player and summoned skeleton names, below other visible name/health blocks. Positive values move up; negative values move down. Uses HUD units and follows the native header canvas scale. Does not move the local shield bar. Whole numbers only.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(-200, 200), Array.Empty<object>())); VisualSettings settings = new VisualSettings(((BaseUnityPlugin)this).Config); try { ShieldRefresh.VerifyFields(); shieldVisuals = new ShieldVisualController(settings, delegate(string message) { ((BaseUnityPlugin)this).Logger.LogWarning((object)message); }); harmony = new Harmony("Slikfoul.ImprovedMagicShield"); harmony.PatchAll(typeof(Plugin).Assembly); labels = new ShieldLabels(); shieldHud = new ShieldHud(); Camera.onPreCull = (CameraCallback)Delegate.Combine((Delegate?)(object)Camera.onPreCull, (Delegate?)new CameraCallback(PrepareLabels)); hooksReady = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)"Improved Magic Shield 1.2.2 loaded. Shield refreshes compare new full protection with current remaining protection."); } catch (Exception ex) { if (harmony != null) { harmony.UnpatchSelf(); } hooksReady = false; if (shieldVisuals != null) { shieldVisuals.Dispose(); } ((BaseUnityPlugin)this).Logger.LogError((object)("Improved Magic Shield disabled: incompatible status-effect hooks. " + ex)); } } private void Update() { if (shieldVisuals != null) { shieldVisuals.ReleaseLightWrites(); } if (labels != null) { labels.Tick(IsEnabled, showProtection.Value, showHealthOutline.Value); } } private void OnGUI() { if (labels != null && IsEnabled && showProtection.Value) { labels.Draw(labelScale.Value, labelOffset.Value); } } private void PrepareLabels(Camera camera) { if (labels != null) { labels.PrepareFrame(camera, IsEnabled && showProtection.Value, labelScale.Value, labelOffset.Value, IsEnabled && showHealthOutline.Value); } } private void LateUpdate() { if (shieldHud != null) { shieldHud.Tick(IsEnabled && showHud.Value, protectionPerSegment.Value); } if (shieldVisuals != null) { shieldVisuals.Tick(IsEnabled); } } private void OnDestroy() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown hooksReady = false; Camera.onPreCull = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPreCull, (Delegate?)new CameraCallback(PrepareLabels)); if (labels != null) { labels.Clear(); } if (shieldHud != null) { shieldHud.Destroy(); } if (shieldVisuals != null) { shieldVisuals.Dispose(); } if (harmony != null) { harmony.UnpatchSelf(); } } } internal static class ShieldActivity { private sealed class State { internal SE_Shield Shield; internal float Age; internal float Protection; internal float ActivityAge; internal uint Threat; internal uint SeenThreat; } private static ConditionalWeakTable<Character, State> states = new ConditionalWeakTable<Character, State>(); private static State Get(Character character) { return states.GetValue(character, (Character ignored) => new State()); } internal static void ObserveThreat(Player player, bool alerted) { if (alerted && !((Object)(object)player != (Object)(object)Player.m_localPlayer)) { Get((Character)(object)player).Threat++; } } internal static float QuietTime(Character character, SE_Shield shield, float remaining) { State state = Get(character); float duration = ((StatusEffect)shield).GetDuration(); BaseAI val = ((character is Player) ? null : character.GetBaseAI()); bool flag = (Object)(object)val != (Object)null && val.IsAlerted() && val.HaveTarget(); if (state.Shield != shield || duration < state.Age || remaining < state.Protection || state.Threat != state.SeenThreat || flag) { state.ActivityAge = duration; } state.Shield = shield; state.Age = duration; state.Protection = remaining; state.SeenThreat = state.Threat; return Math.Max(0f, duration - state.ActivityAge); } internal static void Clear() { states = new ConditionalWeakTable<Character, State>(); } } internal sealed class ShieldHealthOutline { private RectTransform root; private RectTransform progress; private RectTransform rim; private RectTransform glow; private RectMask2D clip; private bool ownsSprites; private int spriteKey; private float spriteHeight; internal void Render(RectTransform health, float fraction) { //IL_0017: 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_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_008d: 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_0284: Unknown result type (might be due to invalid IL or missing references) //IL_02a5: Unknown result type (might be due to invalid IL or missing references) //IL_029c: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Expected O, but got Unknown //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_012b: 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) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Expected O, but got Unknown //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Unknown result type (might be due to invalid IL or missing references) //IL_02bb: Unknown result type (might be due to invalid IL or missing references) //IL_02ca: Unknown result type (might be due to invalid IL or missing references) //IL_02cf: Unknown result type (might be due to invalid IL or missing references) //IL_02dd: Unknown result type (might be due to invalid IL or missing references) //IL_02ee: Unknown result type (might be due to invalid IL or missing references) //IL_02f3: Unknown result type (might be due to invalid IL or missing references) //IL_0302: Unknown result type (might be due to invalid IL or missing references) //IL_0307: Unknown result type (might be due to invalid IL or missing references) //IL_0315: Unknown result type (might be due to invalid IL or missing references) //IL_032f: Unknown result type (might be due to invalid IL or missing references) //IL_0379: Unknown result type (might be due to invalid IL or missing references) //IL_03a7: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)health == (Object)null) && ((Component)health).gameObject.activeInHierarchy) { Rect rect = health.rect; if (!(((Rect)(ref rect)).width <= 0f)) { rect = health.rect; if (!(((Rect)(ref rect)).height <= 0f) && fraction > 0f && !float.IsInfinity(fraction)) { if ((Object)(object)root != (Object)null && (Object)(object)((Transform)root).parent != (Object)(object)health) { Dispose(); } if (ownsSprites) { float num = spriteHeight; rect = health.rect; if (num != ((Rect)(ref rect)).height) { Dispose(); } } if ((Object)(object)root == (Object)null) { if (ownsSprites) { Dispose(); } root = (RectTransform)new GameObject("ImprovedMagicShield.HealthOutline", new Type[1] { typeof(RectTransform) }).transform; ((Transform)root).SetParent((Transform)(object)health, false); root.anchorMin = Vector2.zero; root.anchorMax = Vector2.one; root.offsetMin = new Vector2(-5f, -5f); root.offsetMax = new Vector2(5f, 5f); progress = (RectTransform)new GameObject("Progress", new Type[1] { typeof(RectTransform) }).transform; ((Transform)progress).SetParent((Transform)(object)root, false); progress.anchorMin = Vector2.zero; progress.anchorMax = Vector2.one; RectTransform obj = progress; Vector2 offsetMin = (progress.offsetMax = Vector2.zero); obj.offsetMin = offsetMin; clip = ((Component)progress).gameObject.AddComponent<RectMask2D>(); rect = health.rect; spriteHeight = ((Rect)(ref rect)).height; spriteKey = ShieldOutlineSprites.Acquire(spriteHeight, out var rimSprite, out var glowSprite); ownsSprites = true; glow = Layer("Glow", glowSprite, new Color(0.65f, 0.25f, 1f, 0.2f)); rim = Layer("Rim", rimSprite, new Color(0.75f, 0.4f, 1f, 0.85f)); } float num2 = Mathf.Min(1f, fraction); progress.anchorMax = new Vector2(num2, 1f); clip.softness = (Vector2Int)((num2 < 1f) ? new Vector2Int(2, 0) : Vector2Int.zero); RectTransform obj2 = glow; rect = health.rect; float num3 = ((Rect)(ref rect)).width + 10f; rect = health.rect; obj2.sizeDelta = new Vector2(num3, ((Rect)(ref rect)).height + 10f); RectTransform obj3 = rim; rect = health.rect; float num4 = ((Rect)(ref rect)).width + 6f; rect = health.rect; obj3.sizeDelta = new Vector2(num4, ((Rect)(ref rect)).height + 6f); rim.anchoredPosition = new Vector2(2f, 0f); Canvas componentInParent = ((Component)health).gameObject.GetComponentInParent<Canvas>(); float num5 = (((Object)(object)componentInParent != (Object)null) ? componentInParent.referencePixelsPerUnit : 100f); ((Component)glow).GetComponent<Image>().pixelsPerUnitMultiplier = num5 * 64f / (100f * glow.sizeDelta.y); ((Component)rim).GetComponent<Image>().pixelsPerUnitMultiplier = num5 * 64f / (100f * rim.sizeDelta.y); ((Component)root).gameObject.SetActive(true); return; } } } Hide(); } private RectTransform Layer(string name, Sprite sprite, Color color) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001e: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0045: 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_0058: 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_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected O, but got Unknown RectTransform val = (RectTransform)new GameObject(name, new Type[1] { typeof(RectTransform) }).transform; ((Transform)val).SetParent((Transform)(object)progress, false); val.pivot = new Vector2(0f, 0.5f); Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(0f, 0.5f); val.anchorMax = val2; val.anchorMin = val2; Image obj = ((Component)val).gameObject.AddComponent<Image>(); obj.sprite = sprite; obj.type = (Type)1; obj.fillCenter = false; ((Graphic)obj).color = color; ((Graphic)obj).raycastTarget = false; return val; } internal void Hide() { if ((Object)(object)root != (Object)null) { ((Component)root).gameObject.SetActive(false); } } internal void Dispose() { if ((Object)(object)root != (Object)null) { ((Component)root).gameObject.SetActive(false); Object.Destroy((Object)(object)((Component)root).gameObject); } if (ownsSprites) { ShieldOutlineSprites.Release(spriteKey); } ownsSprites = false; root = null; progress = (rim = (glow = null)); clip = null; } } [HarmonyPatch(typeof(Player), "RPC_OnTargeted")] internal static class ShieldThreatHook { internal static void Postfix(Player __instance, bool alerted) { if (Plugin.IsEnabled) { ShieldActivity.ObserveThreat(__instance, alerted); } } } [HarmonyPatch(typeof(Character), "RPC_Damage")] internal static class HitShieldHook { internal static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Expected O, but got Unknown //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Expected O, but got Unknown //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Expected O, but got Unknown //IL_028a: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Expected O, but got Unknown List<CodeInstruction> list = instructions.ToList(); MethodInfo method = typeof(StatusEffect).GetMethod("ResetTime"); MethodInfo method2 = typeof(StatusEffect).GetMethod("SetLevel"); FieldInfo field = typeof(HitData).GetField("m_itemLevel"); FieldInfo field2 = typeof(HitData).GetField("m_skillLevel"); List<int> list2 = new List<int>(); for (int i = 0; i + 7 < list.Count; i++) { if (!(list[i].opcode != OpCodes.Ldloc_S) && list[i].operand is LocalBuilder localBuilder && !(localBuilder.LocalType != typeof(StatusEffect)) && CodeInstructionExtensions.Calls(list[i + 1], method) && list[i + 2].opcode == list[i].opcode && object.Equals(list[i + 2].operand, localBuilder) && list[i + 3].opcode == OpCodes.Ldarg_2 && CodeInstructionExtensions.LoadsField(list[i + 4], field, false) && list[i + 5].opcode == OpCodes.Ldarg_2 && CodeInstructionExtensions.LoadsField(list[i + 6], field2, false) && CodeInstructionExtensions.Calls(list[i + 7], method2)) { list2.Add(i); } } if (list2.Count != 1) { throw new InvalidOperationException("Expected exactly one Character.RPC_Damage existing-effect refresh block; found " + list2.Count + "."); } int num = list2[0]; if (list.Skip(num + 1).Take(7).Any((CodeInstruction c) => c.labels.Count != 0 || c.blocks.Count != 0) || list[num].blocks.Count != 0) { throw new InvalidOperationException("Unexpected control flow inside the shield refresh block."); } CodeInstruction val = new CodeInstruction(list[num]); CodeInstruction[] collection = (CodeInstruction[])(object)new CodeInstruction[4] { val, new CodeInstruction(OpCodes.Ldarg_2, (object)null), new CodeInstruction(OpCodes.Call, (object)typeof(ShieldRefresh).GetMethod("RefreshFromHit", BindingFlags.Static | BindingFlags.NonPublic)), new CodeInstruction(OpCodes.Stloc_S, list[num].operand) }; list.RemoveRange(num, 8); list.InsertRange(num, collection); return list; } } [HarmonyPatch(typeof(SEMan), "Internal_AddStatusEffect")] internal static class ManagerHashShieldHook { internal static bool Prefix(SEMan __instance, int nameHash, bool resetTime, int itemLevel, float skillLevel, short variant, ref StatusEffect __result) { return ShieldRefresh.InterceptManagerRefresh(__instance, nameHash, resetTime, itemLevel, skillLevel, variant, ref __result); } } [HarmonyPatch(typeof(SEMan), "AddStatusEffect", new Type[] { typeof(StatusEffect), typeof(bool), typeof(int), typeof(float), typeof(short) })] internal static class ManagerObjectShieldHook { internal static bool Prefix(SEMan __instance, StatusEffect statusEffect, bool resetTime, int itemLevel, float skillLevel, short variant, ref StatusEffect __result) { return ShieldRefresh.InterceptManagerRefresh(__instance, statusEffect.NameHash(), resetTime, itemLevel, skillLevel, variant, ref __result); } } internal sealed class ShieldHud { private Hud owner; private Hud failedHud; private RectTransform root; private RectTransform visual; private GuiBar fast; private GuiBar slow; private TMP_Text text; private CanvasGroup visibility; private const float BorderWidth = 16f; private const float RowHeight = 192f; internal void Tick(bool enabled, int protectionPerSegment = 50) { //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) Hud instance = Hud.instance; Player localPlayer = Player.m_localPlayer; if (!enabled || (Object)(object)instance == (Object)null || (Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead() || ((Character)localPlayer).IsTeleporting() || !instance.IsVisible() || ((Character)localPlayer).InCutscene()) { Hide(); return; } SE_Shield shield = ShieldRefresh.FindShield((Character)(object)localPlayer); if (!HudPolicy.TryRead(shield, out var remaining, out var capacity)) { Hide(); return; } if ((Object)(object)owner != (Object)(object)instance || (Object)(object)root == (Object)null) { Destroy(); if ((Object)(object)failedHud == (Object)(object)instance || (Object)(object)instance.m_rootObject == (Object)null || (Object)(object)instance.m_staminaBar2Root == (Object)null || (Object)(object)instance.m_eitrBarRoot == (Object)null || (Object)(object)instance.m_eitrBarFast == (Object)null || (Object)(object)instance.m_eitrBarSlow == (Object)null || (Object)(object)instance.m_eitrText == (Object)null) { return; } try { Create(instance); } catch (Exception ex) { Destroy(); failedHud = instance; Debug.LogWarning((object)("Improved Magic Shield: native resource HUD could not be cloned. Shield mechanics remain active. " + ex)); return; } } visibility.alpha = HudPolicy.Alpha(ShieldActivity.QuietTime((Character)(object)localPlayer, shield, remaining)); ((Component)root).gameObject.SetActive(visibility.alpha > 0f); string text = HudPolicy.Text(remaining, capacity); float num = HudPolicy.Width(capacity, protectionPerSegment); root.SetSizeWithCurrentAnchors((Axis)0, num + 16f); float num2 = this.text.GetPreferredValues(HudPolicy.Text(capacity, capacity)).x + 8f; this.text.rectTransform.SetSizeWithCurrentAnchors((Axis)0, Mathf.Max(num, num2)); this.text.text = text; float value = HudPolicy.Fraction(remaining, capacity); fast.SetMaxValue(1f); slow.SetMaxValue(1f); fast.SetValue(value); slow.SetValue(value); fast.SetWidth(num); slow.SetWidth(num); fast.SetColor(new Color(0.68f, 0.35f, 0.9f, 1f)); } private void Create(Hud hud) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Expected O, but got Unknown //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0121: 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_0134: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Expected O, but got Unknown //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Unknown result type (might be due to invalid IL or missing references) //IL_0282: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_02b1: Unknown result type (might be due to invalid IL or missing references) //IL_02bb: Unknown result type (might be due to invalid IL or missing references) //IL_02e0: Unknown result type (might be due to invalid IL or missing references) //IL_02ea: Unknown result type (might be due to invalid IL or missing references) Transform val = ((Component)hud.m_eitrBarFast).transform; while ((Object)(object)val != (Object)null && (!((Component)hud.m_eitrBarSlow).transform.IsChildOf(val) || !hud.m_eitrText.transform.IsChildOf(val))) { val = val.parent; } if ((Object)(object)val == (Object)null || !val.IsChildOf((Transform)(object)hud.m_eitrBarRoot)) { throw new InvalidOperationException("Eitr resource visuals no longer share an expected subtree."); } GameObject val2 = new GameObject("ImprovedMagicShield.ResourceBar", new Type[1] { typeof(RectTransform) }); val2.SetActive(false); root = (RectTransform)val2.transform; ((Transform)root).SetParent(hud.m_rootObject.transform, false); RectTransform obj = root; RectTransform obj2 = root; Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(0.5f, 0f); obj2.anchorMax = val3; obj.anchorMin = val3; root.pivot = new Vector2(0.5f, 0.5f); root.anchoredPosition = new Vector2(0f, 192f); RectTransform obj3 = root; Rect rect = hud.m_eitrBarRoot.rect; float width = ((Rect)(ref rect)).width; rect = hud.m_eitrBarRoot.rect; obj3.sizeDelta = new Vector2(width, ((Rect)(ref rect)).height); visibility = val2.AddComponent<CanvasGroup>(); visibility.interactable = false; visibility.blocksRaycasts = false; visual = (RectTransform)Object.Instantiate<GameObject>(((Component)val).gameObject, (Transform)(object)root, false).transform; visual.anchoredPosition = Vector2.zero; ((Transform)visual).localScale = Vector3.one; ((Transform)visual).localRotation = Quaternion.identity; fast = MapClone<GuiBar>(hud.m_eitrBarFast, val, (Transform)(object)visual); slow = MapClone<GuiBar>(hud.m_eitrBarSlow, val, (Transform)(object)visual); text = MapClone<TMP_Text>(hud.m_eitrText, val, (Transform)(object)visual); text.enableAutoSizing = false; text.textWrappingMode = (TextWrappingModes)0; text.overflowMode = (TextOverflowModes)0; text.alignment = (TextAlignmentOptions)514; text.rectTransform.anchorMin = new Vector2(0.5f, text.rectTransform.anchorMin.y); text.rectTransform.anchorMax = new Vector2(0.5f, text.rectTransform.anchorMax.y); text.rectTransform.pivot = new Vector2(0.5f, text.rectTransform.pivot.y); text.rectTransform.anchoredPosition = new Vector2(0f, text.rectTransform.anchoredPosition.y); Behaviour[] componentsInChildren = ((Component)visual).GetComponentsInChildren<Behaviour>(true); foreach (Behaviour val4 in componentsInChildren) { if (!(val4 is Graphic) && !(val4 is GuiBar)) { val4.enabled = false; } } Graphic[] componentsInChildren2 = ((Component)visual).GetComponentsInChildren<Graphic>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { componentsInChildren2[i].raycastTarget = false; } ((Component)visual).gameObject.SetActive(true); ((Component)fast).gameObject.SetActive(true); ((Component)slow).gameObject.SetActive(true); ((Component)text).gameObject.SetActive(true); fast.m_smoothDrain = false; fast.m_smoothFill = false; owner = hud; } private static T MapClone<T>(T original, Transform source, Transform clone) where T : Component { Stack<int> stack = new Stack<int>(); Transform val = ((Component)original).transform; while ((Object)(object)val != (Object)(object)source) { if ((Object)(object)val == (Object)null) { throw new InvalidOperationException("Native HUD reference escaped its visual subtree."); } stack.Push(val.GetSiblingIndex()); val = val.parent; } while (stack.Count > 0) { clone = clone.GetChild(stack.Pop()); } T component = ((Component)clone).GetComponent<T>(); if ((Object)(object)component == (Object)null) { throw new InvalidOperationException("A cloned native resource component is missing."); } return component; } private void Hide() { if ((Object)(object)root != (Object)null) { ((Component)root).gameObject.SetActive(false); } } internal void Destroy() { if ((Object)(object)root != (Object)null) { ((Component)root).gameObject.SetActive(false); Object.Destroy((Object)(object)((Component)root).gameObject); } root = null; visual = null; fast = null; slow = null; text = null; visibility = null; owner = null; } } internal sealed class ShieldLabelAnchor { private const BindingFlags Fields = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private static readonly FieldInfo hudsField = typeof(EnemyHud).GetField("m_huds", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo guiField = typeof(EnemyHud).GetNestedType("HudData", BindingFlags.NonPublic)?.GetField("m_gui", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private readonly Vector3[] corners = (Vector3[])(object)new Vector3[4]; private GameObject cachedRoot; private RectTransform name; private RectTransform health; private Canvas canvas; private TMP_Text label; internal bool HasNativeLabel => (Object)(object)label != (Object)null; internal void SetAlpha(float alpha) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)label != (Object)null) { ((Graphic)label).color = new Color(0.85f, 0.65f, 1f, alpha); } } internal void Hide() { if ((Object)(object)label != (Object)null) { ((Component)label).gameObject.SetActive(false); } } internal void Dispose() { if ((Object)(object)label != (Object)null) { ((Component)label).gameObject.SetActive(false); Object.Destroy((Object)(object)((Component)label).gameObject); } label = null; } internal bool TryRender(Character character, bool aboveName, float remaining, int scale, int offset) { //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) if (!TryEdge(character, aboveName, out var edge, out var _)) { Hide(); return false; } TMP_Text val = (((Object)(object)name != (Object)null) ? ((Component)name).GetComponent<TMP_Text>() : null); if ((Object)(object)val == (Object)null) { Hide(); return false; } if ((Object)(object)label == (Object)null) { GameObject val2 = Object.Instantiate<GameObject>(((Component)val).gameObject, cachedRoot.transform, false); ((Object)val2).name = "ImprovedMagicShield.Protection"; label = val2.GetComponent<TMP_Text>(); Behaviour[] componentsInChildren = val2.GetComponentsInChildren<Behaviour>(true); foreach (Behaviour val3 in componentsInChildren) { if (!(val3 is Graphic)) { val3.enabled = false; } } ((Behaviour)label).enabled = true; ((Graphic)label).raycastTarget = false; label.enableAutoSizing = false; label.textWrappingMode = (TextWrappingModes)0; label.overflowMode = (TextOverflowModes)0; label.alignment = (TextAlignmentOptions)514; ((Graphic)label).color = new Color(0.85f, 0.65f, 1f); } float left = float.PositiveInfinity; float right = float.NegativeInfinity; float bottom = float.PositiveInfinity; float top = float.NegativeInfinity; IncludeLocal(name, ref left, ref right, ref bottom, ref top); if (!aboveName) { IncludeLocal(health, ref left, ref right, ref bottom, ref top); } float num = 20f * (float)Mathf.Clamp(scale, 50, 300) / 100f; float num2 = num * 2f; label.fontSize = num; label.text = DisplayPolicy.WholeProtection(remaining).ToString(); RectTransform rectTransform = label.rectTransform; Vector2 val4 = default(Vector2); ((Vector2)(ref val4))..ctor(0.5f, 0.5f); rectTransform.pivot = val4; edge = (rectTransform.anchorMax = val4); rectTransform.anchorMin = edge; ((Transform)rectTransform).localScale = Vector3.one; ((Transform)rectTransform).localRotation = Quaternion.identity; rectTransform.sizeDelta = new Vector2(Mathf.Max(300f, right - left), num2); ((Transform)rectTransform).localPosition = new Vector3((left + right) * 0.5f, (aboveName ? (top + 4f + num2 * 0.5f) : (bottom - 4f - num2 * 0.5f)) + (float)offset, 0f); ((Component)label).gameObject.SetActive(true); return true; } private void IncludeLocal(RectTransform rect, ref float left, ref float right, ref float bottom, ref float top) { //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_0041: 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) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_005a: 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_007c: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)rect == (Object)null) && ((Component)rect).gameObject.activeInHierarchy) { rect.GetWorldCorners(corners); Vector3[] array = corners; foreach (Vector3 val in array) { Vector3 val2 = cachedRoot.transform.InverseTransformPoint(val); left = Mathf.Min(left, val2.x); right = Mathf.Max(right, val2.x); bottom = Mathf.Min(bottom, val2.y); top = Mathf.Max(top, val2.y); } } } internal bool TryLowerEdge(Character character, out Vector2 edge, out float uiScale) { return TryEdge(character, aboveName: false, out edge, out uiScale); } internal bool TryUpperNameEdge(Character character, out Vector2 edge, out float uiScale) { return TryEdge(character, aboveName: true, out edge, out uiScale); } internal RectTransform VisibleHealth(Character character) { if (!TryEdge(character, aboveName: false, out var _, out var _) || (Object)(object)health == (Object)null || !((Component)health).gameObject.activeInHierarchy) { return null; } return health; } private bool TryEdge(Character character, bool aboveName, out Vector2 edge, out float uiScale) { //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_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) edge = Vector2.zero; uiScale = 1f; if ((Object)(object)EnemyHud.instance == (Object)null || character.IsBoss() || hudsField == null || guiField == null) { return false; } if (!(hudsField.GetValue(EnemyHud.instance) is IDictionary dictionary) || !dictionary.Contains(character)) { return false; } object? value = guiField.GetValue(dictionary[character]); GameObject val = (GameObject)((value is GameObject) ? value : null); if ((Object)(object)val == (Object)null || !val.activeInHierarchy) { return false; } if ((Object)(object)val != (Object)(object)cachedRoot) { Dispose(); cachedRoot = val; ref RectTransform reference = ref name; Transform obj = val.transform.Find("Name"); reference = (RectTransform)(object)((obj is RectTransform) ? obj : null); ref RectTransform reference2 = ref health; Transform obj2 = val.transform.Find("Health"); reference2 = (RectTransform)(object)((obj2 is RectTransform) ? obj2 : null); canvas = val.GetComponentInParent<Canvas>(); } Camera camera = (((Object)(object)canvas != (Object)null && (int)canvas.renderMode != 0) ? canvas.worldCamera : null); float left = float.PositiveInfinity; float right = float.NegativeInfinity; float bottom = float.PositiveInfinity; float top = float.NegativeInfinity; Include(name, camera, ref left, ref right, ref bottom, ref top); if (!aboveName) { Include(health, camera, ref left, ref right, ref bottom, ref top); } if (float.IsInfinity(bottom) || float.IsNaN(bottom)) { return false; } edge = new Vector2((left + right) * 0.5f, aboveName ? top : bottom); if ((Object)(object)canvas != (Object)null) { uiScale = Mathf.Max(0.5f, canvas.scaleFactor); } return true; } private void Include(RectTransform rect, Camera camera, ref float left, ref float right, ref float bottom, ref float top) { //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_0037: 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) //IL_003d: 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_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)rect == (Object)null) && ((Component)rect).gameObject.activeInHierarchy) { rect.GetWorldCorners(corners); Vector3[] array = corners; foreach (Vector3 val in array) { Vector2 val2 = RectTransformUtility.WorldToScreenPoint(camera, val); left = Mathf.Min(left, val2.x); right = Mathf.Max(right, val2.x); bottom = Mathf.Min(bottom, val2.y); top = Mathf.Max(top, val2.y); } } } } internal sealed class ShieldLabels { private sealed class Label { internal Character Character; internal readonly ShieldLabelAnchor Anchor = new ShieldLabelAnchor(); internal readonly ShieldHealthOutline Outline = new ShieldHealthOutline(); internal void Dispose() { Anchor.Dispose(); Outline.Dispose(); } internal void Hide() { Anchor.Hide(); Outline.Hide(); } } private struct ScreenLabel { internal Label Label; internal Vector3 Position; internal float Gap; internal float UiScale; internal bool AboveName; } private static readonly int protectionKey = StringExtensionMethods.GetStableHashCode("Slikfoul.ImprovedMagicShield.Protection"); private static readonly int sampleKey = StringExtensionMethods.GetStableHashCode("Slikfoul.ImprovedMagicShield.SampleTime"); private static readonly int publisherKey = StringExtensionMethods.GetStableHashCode("Slikfoul.ImprovedMagicShield.Publisher"); private static readonly int activityKey = StringExtensionMethods.GetStableHashCode("Slikfoul.ImprovedMagicShield.ActivityTime"); private static readonly int capacityKey = StringExtensionMethods.GetStableHashCode("Slikfoul.ImprovedMagicShield.Capacity"); private static readonly int capacitySampleKey = StringExtensionMethods.GetStableHashCode("Slikfoul.ImprovedMagicShield.CapacitySampleTime"); private readonly HashSet<ZNetView> published = new HashSet<ZNetView>(); private readonly List<Label> labels = new List<Label>(); private readonly List<ScreenLabel> frameLabels = new List<ScreenLabel>(); private int preparedFrame = -1; private Camera preparedCamera; private float nextTick; private GUIStyle style; internal void Tick(bool enabled, bool show, bool showOutline = false) { if (!enabled || (Object)(object)ZNet.instance == (Object)null) { Clear(); return; } if (!show && !showOutline) { ReleaseLabels(); ClearFrame(); } if (!showOutline) { foreach (Label label in labels) { label.Outline.Hide(); } } if (!show) { foreach (Label label2 in labels) { label2.Anchor.Hide(); } } if (Time.unscaledTime < nextTick) { return; } nextTick = Time.unscaledTime + 0.1f; Dictionary<Character, Label> dictionary = new Dictionary<Character, Label>(); foreach (Label label3 in labels) { dictionary[label3.Character] = label3; } labels.Clear(); double timeSeconds = ZNet.instance.GetTimeSeconds(); foreach (Character allCharacter in Character.GetAllCharacters()) { if ((Object)(object)allCharacter == (Object)null) { continue; } ZNetView component = ((Component)allCharacter).GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null || !component.IsValid()) { continue; } ZDO zDO = component.GetZDO(); SE_Shield val = null; float num; if (component.IsOwner()) { val = ShieldRefresh.FindShield(allCharacter); num = (((Object)(object)val == (Object)null) ? 0f : ShieldRefresh.Remaining(val)); if (num > 0f) { float num2 = ShieldRefresh.Capacity(val); long num3 = (long)((timeSeconds - (double)ShieldActivity.QuietTime(allCharacter, val, num)) * 1000.0); if (!published.Contains(component) || zDO.GetFloat(protectionKey, 0f) != num || zDO.GetFloat(capacityKey, 0f) != num2 || timeSeconds - (double)zDO.GetLong(sampleKey, 0L) / 1000.0 >= 0.5 || zDO.GetLong(publisherKey, 0L) != zDO.GetOwner() || Math.Abs(zDO.GetLong(activityKey, -1L) - num3) >= 50) { zDO.Set(protectionKey, num); zDO.Set(capacityKey, num2); zDO.Set(sampleKey, (long)(timeSeconds * 1000.0)); zDO.Set(capacitySampleKey, (long)(timeSeconds * 1000.0)); zDO.Set(publisherKey, zDO.GetOwner()); zDO.Set(activityKey, num3); published.Add(component); } } else if (published.Remove(component)) { zDO.Set(protectionKey, 0f); } } else { num = zDO.GetFloat(protectionKey, 0f); if (!DisplayPolicy.IsFresh(num, (double)zDO.GetLong(sampleKey, 0L) / 1000.0, timeSeconds, zDO.GetLong(publisherKey, 0L), zDO.GetOwner())) { continue; } } if ((show || showOutline) && num > 0f && (Object)(object)allCharacter != (Object)(object)Player.m_localPlayer) { if (!dictionary.TryGetValue(allCharacter, out var value)) { value = new Label { Character = allCharacter }; } labels.Add(value); dictionary.Remove(allCharacter); } } foreach (Label value2 in dictionary.Values) { value2.Dispose(); } published.RemoveWhere((ZNetView v) => (Object)(object)v == (Object)null || !v.IsValid() || !v.IsOwner()); } internal void Clear() { ReleaseLabels(); ClearFrame(); foreach (ZNetView item in published) { if ((Object)(object)item != (Object)null && item.IsValid() && item.IsOwner()) { item.GetZDO().Set(protectionKey, 0f); } } published.Clear(); nextTick = 0f; ShieldActivity.Clear(); } private void ClearFrame() { frameLabels.Clear(); preparedFrame = -1; preparedCamera = null; } private void ReleaseLabels() { foreach (Label label in labels) { label.Dispose(); } labels.Clear(); } private static bool CanShow() { Player localPlayer = Player.m_localPlayer; if ((Object)(object)ZNet.instance != (Object)null && (Object)(object)localPlayer != (Object)null && !((Character)localPlayer).IsDead() && !((Character)localPlayer).IsTeleporting() && !((Character)localPlayer).InCutscene()) { if (!((Object)(object)Hud.instance == (Object)null)) { return Hud.instance.IsVisible(); } return true; } return false; } private static bool TryProtection(Character character, out float remaining) { remaining = 0f; if ((Object)(object)character == (Object)null || (Object)(object)character == (Object)(object)Player.m_localPlayer || character.IsDead()) { return false; } Player val = (Player)(object)((character is Player) ? character : null); if ((Object)(object)val != (Object)null && ((Character)val).IsTeleporting()) { return false; } ZNetView component = ((Component)character).GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null || !component.IsValid()) { return false; } if (component.IsOwner()) { SE_Shield val2 = ShieldRefresh.FindShield(character); remaining = (((Object)(object)val2 == (Object)null) ? 0f : ShieldRefresh.Remaining(val2)); if (remaining > 0f) { return !float.IsInfinity(remaining); } return false; } ZDO zDO = component.GetZDO(); remaining = zDO.GetFloat(protectionKey, 0f); return DisplayPolicy.IsFresh(remaining, (double)zDO.GetLong(sampleKey, 0L) / 1000.0, ZNet.instance.GetTimeSeconds(), zDO.GetLong(publisherKey, 0L), zDO.GetOwner()); } private static bool TryDisplay(Character character, out float remaining, out float alpha) { alpha = 0f; if (!TryProtection(character, out remaining)) { return false; } ZNetView component = ((Component)character).GetComponent<ZNetView>(); if (component.IsOwner()) { alpha = HudPolicy.Alpha(ShieldActivity.QuietTime(character, ShieldRefresh.FindShield(character), remaining)); } else { alpha = DisplayPolicy.SnapshotAlpha((double)component.GetZDO().GetLong(activityKey, -1L) / 1000.0, ZNet.instance.GetTimeSeconds()); } return true; } private static float ProtectionFraction(Character character, float remaining) { ZNetView component = ((Component)character).GetComponent<ZNetView>(); float capacity; if (component.IsOwner()) { SE_Shield val = ShieldRefresh.FindShield(character); capacity = (((Object)(object)val == (Object)null) ? 0f : ShieldRefresh.Capacity(val)); } else { ZDO zDO = component.GetZDO(); if (zDO.GetLong(capacitySampleKey, -1L) != zDO.GetLong(sampleKey, 0L)) { return 0f; } capacity = zDO.GetFloat(capacityKey, 0f); } return DisplayPolicy.ProtectionFraction(remaining, capacity); } internal void PrepareFrame(Camera camera, bool show, int scale = 100, int verticalOffset = 0, bool showOutline = false) { //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: 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_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: 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_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0124: 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_0298: Unknown result type (might be due to invalid IL or missing references) //IL_029a: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)camera == (Object)null || (Object)(object)camera != (Object)(object)Utils.GetMainCamera()) { return; } ClearFrame(); if ((!show && !showOutline) || !CanShow()) { foreach (Label label in labels) { label.Hide(); } return; } preparedFrame = Time.frameCount; preparedCamera = camera; foreach (Label label2 in labels) { if (!TryProtection(label2.Character, out var remaining)) { label2.Hide(); continue; } Vector3 val = label2.Character.GetTopPoint() + Vector3.up * 0.3f; Vector3 val2 = val - ((Component)camera).transform.position; if (((Vector3)(ref val2)).sqrMagnitude > 3600f) { label2.Hide(); continue; } Vector3 val3 = Utils.WorldToScreenPointScaled(camera, val); if (val3.z <= 0f || val3.x < 0f || val3.x > (float)Screen.width || val3.y < 0f || val3.y > (float)Screen.height) { label2.Hide(); continue; } if (showOutline) { label2.Outline.Render(label2.Anchor.VisibleHealth(label2.Character), ProtectionFraction(label2.Character, remaining)); } else { label2.Outline.Hide(); } if (!show || !TryDisplay(label2.Character, out remaining, out var alpha) || alpha <= 0f) { label2.Anchor.Hide(); continue; } float gap = 8f; bool flag = label2.Character is Player || ((Object)((Component)label2.Character).gameObject).name.StartsWith("Skeleton_Friendly", StringComparison.Ordinal); if (label2.Anchor.TryRender(label2.Character, flag, remaining, scale, verticalOffset)) { label2.Anchor.SetAlpha(alpha); } else if (!label2.Anchor.HasNativeLabel) { float uiScale = 1f; if (flag ? label2.Anchor.TryUpperNameEdge(label2.Character, out var edge, out uiScale) : label2.Anchor.TryLowerEdge(label2.Character, out edge, out uiScale)) { val3.x = edge.x; val3.y = edge.y; gap = 4f * uiScale; } frameLabels.Add(new ScreenLabel { Label = label2, Position = val3, Gap = gap, UiScale = uiScale, AboveName = flag }); } } } internal void Draw(int scale, int verticalOffset = 0) { //IL_023d: 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_0012: Invalid comparison between Unknown and I4 //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Expected O, but got Unknown //IL_0108: 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_0169: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Unknown result type (might be due to invalid IL or missing references) if (Event.current == null || (int)Event.current.type != 7 || !CanShow() || preparedFrame != Time.frameCount || (Object)(object)preparedCamera == (Object)null || (Object)(object)preparedCamera != (Object)(object)Utils.GetMainCamera()) { return; } if (style == null) { style = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)4, fontStyle = (FontStyle)1 }; } style.fontSize = Mathf.RoundToInt(20f * (float)Mathf.Clamp(scale, 50, 300) / 100f); Color color = GUI.color; try { Rect val = default(Rect); foreach (ScreenLabel frameLabel in frameLabels) { if (TryDisplay(frameLabel.Label.Character, out var remaining, out var alpha) && !(alpha <= 0f)) { Vector3 position = frameLabel.Position; string text = DisplayPolicy.WholeProtection(remaining).ToString(); float num = style.CalcSize(new GUIContent(text)).x + 12f; float num2 = (float)style.fontSize * 2f; float num3 = (float)Screen.height - position.y + (frameLabel.AboveName ? (0f - frameLabel.Gap - num2) : frameLabel.Gap); num3 -= (float)verticalOffset * frameLabel.UiScale; ((Rect)(ref val))..ctor(position.x - num / 2f, num3, num, num2); style.normal.textColor = Color.black; GUI.color = new Color(color.r, color.g, color.b, color.a * alpha); GUI.Label(new Rect(((Rect)(ref val)).x + 1f, ((Rect)(ref val)).y + 1f, num, num2), text, style); style.normal.textColor = new Color(0.85f, 0.65f, 1f); GUI.Label(val, text, style); } } } finally { GUI.color = color; } } } internal static class ShieldOutlineSprites { private sealed class Pair { internal Sprite Rim; internal Sprite Glow; internal int Users; } private const int Size = 64; private static readonly Dictionary<int, Pair> cache = new Dictionary<int, Pair>(); private static int users; internal static int Acquire(float height, out Sprite rimSprite, out Sprite glowSprite) { int num = Mathf.RoundToInt(height * 100f); if (!cache.TryGetValue(num, out var value)) { value = new Pair { Rim = Create("Rim", height, 3f, soft: false), Glow = Create("Glow", height, 5f, soft: true) }; cache.Add(num, value); } value.Users++; users++; rimSprite = value.Rim; glowSprite = value.Glow; return num; } private static Sprite Create(string name, float height, float margin, bool soft) { //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Expected O, but got Unknown //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) Color[] array = (Color[])(object)new Color[4096]; float num = height / (height + 2f * margin) * 64f * 0.5f; for (int i = 0; i < 64; i++) { for (int j = 0; j < 64; j++) { float num2 = (float)j + 0.5f - 32f; float num3 = (float)i + 0.5f - 32f; float num4 = (float)Math.Sqrt(num2 * num2 + num3 * num3) - 32f; float num5 = Math.Max(Math.Abs(num2), Math.Abs(num3)) - num; float num6 = Clamp(0.5f - num4) * (1f - Clamp(0.5f - num5)); if (soft) { num6 *= Clamp((0.5f - num4) / 3f) * Clamp((num5 + 0.5f) / 3f); } array[i * 64 + j] = new Color(1f, 1f, 1f, num6); } } Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false); ((Object)val).name = "ImprovedMagicShield." + name; ((Texture)val).wrapMode = (TextureWrapMode)1; ((Texture)val).filterMode = (FilterMode)1; val.SetPixels(array); val.Apply(false, false); Sprite obj = Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0, new Vector4(32f, 32f, 32f, 32f)); ((Object)obj).name = ((Object)val).name; return obj; } private static float Clamp(float value) { return Math.Max(0f, Math.Min(1f, value)); } internal static void Release(int key) { if (cache.TryGetValue(key, out var value)) { users--; if (--value.Users == 0) { Object.Destroy((Object)(object)value.Rim.texture); Object.Destroy((Object)(object)value.Glow.texture); Object.Destroy((Object)(object)value.Rim); Object.Destroy((Object)(object)value.Glow); cache.Remove(key); } } } } internal static class ShieldRefresh { private static readonly FieldInfo total = typeof(SE_Shield).GetField("m_totalAbsorbDamage", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly FieldInfo damage = typeof(SE_Shield).GetField("m_damage", BindingFlags.Instance | BindingFlags.NonPublic); internal static void VerifyFields() { if (total == null || damage == null || total.FieldType != typeof(float) || damage.FieldType != typeof(float)) { throw new MissingFieldException("SE_Shield protection fields are incompatible."); } } internal static float FullProtection(SE_Shield shield, float skillLevel) { float num = shield.m_absorbDamage + shield.m_absorbDamagePerSkillLevel * skillLevel; if (Game.m_worldLevel > 0) { num += shield.m_absorbDamageWorldLevel * (float)Game.m_worldLevel; } return num; } internal static bool TryRefresh(SE_Shield shield, int itemLevel, float skillLevel) { float num = FullProtection(shield, skillLevel); float num2 = (float)total.GetValue(shield) - (float)damage.GetValue(shield); if (!(num >= num2)) { return false; } ((StatusEffect)shield).ResetTime(); ((StatusEffect)shield).SetLevel(itemLevel, skillLevel); damage.SetValue(shield, 0f); return true; } internal static float Remaining(SE_Shield shield) { return Math.Max(0f, (float)total.GetValue(shield) - (float)damage.GetValue(shield)); } internal static float Capacity(SE_Shield shield) { return (float)total.GetValue(shield); } internal static SE_Shield FindShield(Character character) { foreach (StatusEffect statusEffect in character.GetSEMan().GetStatusEffects()) { SE_Shield val = (SE_Shield)(object)((statusEffect is SE_Shield) ? statusEffect : null); if (val != null) { return val; } } return null; } internal static StatusEffect RefreshFromHit(StatusEffect effect, HitData hit) { if (Plugin.IsEnabled) { SE_Shield val = (SE_Shield)(object)((effect is SE_Shield) ? effect : null); if (val != null) { if (!TryRefresh(val, hit.m_itemLevel, hit.m_skillLevel)) { return null; } return effect; } } effect.ResetTime(); effect.SetLevel((int)hit.m_itemLevel, hit.m_skillLevel); return effect; } internal static bool InterceptManagerRefresh(SEMan manager, int hash, bool resetTime, int itemLevel, float skillLevel, short variant, ref StatusEffect result) { if (!Plugin.IsEnabled || !resetTime) { return true; } StatusEffect statusEffect = manager.GetStatusEffect(hash); SE_Shield val = (SE_Shield)(object)((statusEffect is SE_Shield) ? statusEffect : null); if ((Object)(object)val == (Object)null) { return true; } if (TryRefresh(val, itemLevel, skillLevel)) { ((StatusEffect)val).m_hitVariant = variant; } result = null; return false; } } } namespace ImprovedMagicShield.Visuals { internal sealed class ShieldVisualCatalog { private ConditionalWeakTable<EffectList, object> lists = new ConditionalWeakTable<EffectList, object>(); private readonly HashSet<string> names = new HashSet<string>(StringComparer.Ordinal); public void Clear() { lists = new ConditionalWeakTable<EffectList, object>(); names.Clear(); } public bool Contains(EffectList list) { object value; if (list != null) { return lists.TryGetValue(list, out value); } return false; } public bool Contains(GameObject root) { if (!Object.op_Implicit((Object)(object)root)) { return false; } string text = ((Object)root).name; if (text.EndsWith("(Clone)", StringComparison.Ordinal)) { text = text.Substring(0, text.Length - 7); } return names.Contains(text); } public void Register(SE_Shield shield) { if (Object.op_Implicit((Object)(object)shield)) { Add(((StatusEffect)shield).m_startEffects); Add(shield.m_hitEffects); Add(shield.m_breakEffects); Add(((StatusEffect)shield).m_stopEffects); } } private void Add(EffectList list) { if (list == null || list.m_effectPrefabs == null) { return; } if (!Contains(list)) { lists.Add(list, new object()); } EffectData[] effectPrefabs = list.m_effectPrefabs; for (int i = 0; i < effectPrefabs.Length; i++) { GameObject val = effectPrefabs[i]?.m_prefab; if (Eligible(val)) { names.Add(((Object)val).name); } } } internal static bool Eligible(GameObject root) { if (Object.op_Implicit((Object)(object)root) && !Object.op_Implicit((Object)(object)root.GetComponentInChildren<Character>(true))) { return !Object.op_Implicit((Object)(object)root.GetComponentInChildren<Piece>(true)); } return false; } } internal sealed class ShieldVisualController : IDisposable { internal static ShieldVisualController Instance; internal readonly ShieldVisualCatalog Catalog = new ShieldVisualCatalog(); private readonly VisualSettings settings; private readonly Action<string> warn; private readonly HashSet<GameObject> pending = new HashSet<GameObject>(); private readonly HashSet<GameObject> pendingNetwork = new HashSet<GameObject>(); private readonly Dictionary<GameObject, VisualState> active = new Dictionary<GameObject, VisualState>(); private readonly List<GameObject> expired = new List<GameObject>(); private bool rebuild = true; private bool applied; private bool faulted; private bool warned; private int failures; public ShieldVisualController(VisualSettings settings, Action<string> warn) { this.settings = settings; this.warn = warn; Instance = this; } internal void RequestCatalog() { rebuild = true; } internal void ReleaseLightWrites() { foreach (VisualState value in active.Values) { value.ReleaseLightWrites(); } } internal void Register(SE_Shield shield) { Catalog.Register(shield); } internal void Observe(GameObject root) { if (ShieldVisualCatalog.Eligible(root)) { pending.Add(root); } } internal void ObserveNetwork(GameObject root) { if (Object.op_Implicit((Object)(object)root)) { if (rebuild) { pendingNetwork.Add(root); } else if (Catalog.Contains(root)) { Observe(root); } } } internal static bool ConflictingControlsEnabled() { ConfigEntry<bool> val = default(ConfigEntry<bool>); ConfigEntry<bool> val2 = default(ConfigEntry<bool>); foreach (PluginInfo value in Chainloader.PluginInfos.Values) { if (value.Metadata.GUID.IndexOf("subtleshield", StringComparison.OrdinalIgnoreCase) >= 0 || string.Equals(value.Metadata.Name, "SubtleShield", StringComparison.OrdinalIgnoreCase)) { return true; } if (string.Equals(value.Metadata.GUID, "Slikfoul.EffectsControl", StringComparison.OrdinalIgnoreCase)) { if (!Object.op_Implicit((Object)(object)value.Instance) || !value.Instance.Config.TryGetEntry<bool>("1. General", "Enable mod", ref val) || !value.Instance.Config.TryGetEntry<bool>("1. General", "Magic shield", ref val2)) { return true; } if (val.Value && val2.Value) { return true; } } } return false; } public void Tick(bool modEnabled) { //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Invalid comparison between Unknown and I4 //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) try { bool flag = rebuild; if (rebuild) { Catalog.Clear(); if (Object.op_Implicit((Object)(object)ObjectDB.instance)) { foreach (StatusEffect statusEffect in ObjectDB.instance.m_StatusEffects) { SE_Shield val = (SE_Shield)(object)((statusEffect is SE_Shield) ? statusEffect : null); if (val != null) { Catalog.Register(val); } } } rebuild = false; } foreach (GameObject item in pendingNetwork) { if (Catalog.Contains(item)) { Observe(item); } } pendingNetwork.Clear(); int num; int num2; if (modEnabled && settings.Enabled.Value) { num = (((int)SystemInfo.graphicsDeviceType != 4) ? 1 : 0); if (num != 0) { num2 = (ConflictingControlsEnabled() ? 1 : 0); goto IL_00f8; } } else { num = 0; } num2 = 0; goto IL_00f8; IL_00f8: bool flag2 = (byte)num2 != 0; if (flag2 && !warned) { warn("Magic Shield Effect suspended: disable Magic shield in EffectsControl or disable SubtleShield to use these visual settings."); } warned = flag2; if (num == 0) { faulted = false; } if (num == 0 || flag2 || faulted) { if (applied) { Restore(); } pending.Clear(); applied = false; return; } if (!applied || flag) { GameObject[] array = Resources.FindObjectsOfTypeAll<GameObject>(); foreach (GameObject val2 in array) { if (!Object.op_Implicit((Object)(object)val2)) { continue; } Scene scene = val2.scene; if (((Scene)(ref scene)).IsValid()) { scene = val2.scene; if (((Scene)(ref scene)).isLoaded && val2.activeInHierarchy && Catalog.Contains(val2)) { Observe(val2); } } } } applied = true; foreach (GameObject item2 in pending) { if (Object.op_Implicit((Object)(object)item2) && !active.ContainsKey(item2)) { VisualState visualState = new VisualState(item2, EffectStage.Shield); if (visualState.Empty) { visualState.Dispose(); } else { active.Add(item2, visualState); } } } pending.Clear(); VisualOptions options = settings.Get(); expired.Clear(); foreach (KeyValuePair<GameObject, VisualState> item3 in active) { if (!Object.op_Implicit((Object)(object)item3.Key)) { item3.Value.Dispose(); expired.Add(item3.Key); } else { item3.Value.Apply(options); } } foreach (GameObject item4 in expired) { active.Remove(item4); } } catch (Exception ex) { Restore(); applied = false; faulted = true; if (failures++ < 5) { warn("Shield visual controls suspended after an error; gameplay continues. " + ex); } } } private void Restore() { foreach (VisualState value in active.Values) { value.Dispose(); } active.Clear(); pending.Clear(); } public void Dispose() { Restore(); pendingNetwork.Clear(); Catalog.Clear(); if (Instance == this) { Instance = null; } } } [HarmonyPatch(typeof(ObjectDB), "Awake")] internal static class VisualDatabaseAwakeHook { private static void Postfix() { ShieldVisualController.Instance?.RequestCatalog(); } } [HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")] internal static class VisualDatabaseCopyHook { private static void Postfix() { ShieldVisualController.Instance?.RequestCatalog(); } } [HarmonyPatch(typeof(ZNetScene), "Awake")] internal static class VisualSceneHook { private static void Postfix() { ShieldVisualController.Instance?.RequestCatalog(); } } [HarmonyPatch(typeof(SE_Shield), "Setup")] internal static class VisualShieldSetupHook { private static void Prefix(SE_Shield __instance) { ShieldVisualController.Instance?.Register(__instance); } } [HarmonyPatch(typeof(EffectList), "Create")] internal static class VisualEffectCreateHook { private static void Postfix(EffectList __instance, GameObject[] __result) { ShieldVisualController instance = ShieldVisualController.Instance; if (instance != null && __result != null && instance.Catalog.Contains(__instance)) { foreach (GameObject root in __result) { instance.Observe(root); } } } } [HarmonyPatch(typeof(ZNetScene), "CreateObject")] internal static class VisualNetworkCreateHook { private static void Postfix(GameObject __result) { ShieldVisualController.Instance?.ObserveNetwork(__result); } } public enum EffectStage { Shield } public sealed class VisualOptions { public float Light = 1f; public float Glow = 1f; public float Opacity = 1f; public float Size = 1f; public float Density = 1f; public float ShieldOvality; public bool TintEnabled; public Color Tint = Color.white; public static VisualOptions Original() { return new VisualOptions(); } } internal sealed class VisualSettings { public readonly ConfigEntry<bool> Enabled; public readonly ConfigEntry<int> Color; public readonly ConfigEntry<int> Glow; public readonly ConfigEntry<int> Light; public readonly ConfigEntry<int> Opacity; public readonly ConfigEntry<int> Ovality; public VisualSettings(ConfigFile config) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown Enabled = config.Bind<bool>("3 - Magic Shield", "Magic Shield Effect", false, new ConfigDescription("Customize shield appearance on this client. Off by default. Disable Magic shield in EffectsControl before enabling this setting. Controls are suspended while EffectsControl shield controls or SubtleShield are active. Turning this off restores the captured appearance; shield protection and the HUD are unaffected.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 100 } })); Color = Integer(config, "3 - Magic Shield", "Color", 269, 360, "Hue: 0/360 red, 60 yellow, 120 green, 180 cyan, 240 blue, 300 magenta. Applied whenever Magic Shield Effect is enabled."); Glow = Integer(config, "3 - Magic Shield", "Glow", 72, 100, "Bubble and particle glow. 100 is original brightness."); Light = Integer(config, "3 - Magic Shield", "Light brightness", 35, 100, "Shield light intensity. 100 is original brightness; light range is unchanged."); Opacity = Integer(config, "3 - Magic Shield", "Opacity", 30, 100, "Bubble and particle opacity. 100 is original opacity; 0 hides the visual shield without changing protection."); Ovality = Integer(config, "3 - Magic Shield", "Ovality", 50, 100, "Bubble shape: 0 round, 50 oval, 100 narrow oval. Height and colliders are unchanged."); } private static ConfigEntry<int> Integer(ConfigFile config, string section, string key, int value, int maximum, string description) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown return config.Bind<int>(section, key, value, new ConfigDescription(description + " Whole numbers only.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, maximum), Array.Empty<object>())); } public VisualOptions Get() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) return new VisualOptions { TintEnabled = true, Tint = Color.HSVToRGB((float)Color.Value / 360f, 1f, 1f), Glow = (float)Glow.Value / 100f, Light = (float)Light.Value / 100f, Opacity = (float)Opacity.Value / 100f, ShieldOvality = (float)Ovality.Value / 100f }; } } internal sealed class ConfigurationManagerAttributes { public int Order; } public sealed class VisualState : IDisposable { public readonly EffectStage Stage; private readonly List<ParticleState> particles = new List<ParticleState>(); private readonly List<LightState> lights = new List<LightState>(); private readonly List<RendererState> renderers = new List<RendererState>(); private readonly List<MeshState> meshes = new List<MeshState>(); private bool disposed; public bool Empty => particles.Count + lights.Count + renderers.Count == 0; public VisualState(GameObject root, EffectStage stage) { Stage = stage; try { ParticleSystem[] componentsInChildren = root.GetComponentsInChildren<ParticleSystem>(true); foreach (ParticleSystem system in componentsInChildren) { particles.Add(new ParticleState(system)); } Light[] componentsInChildren2 = root.GetComponentsInChildren<Light>(true); foreach (Light light in componentsInChildren2) { lights.Add(new LightState(light)); } Renderer[] componentsInChildren3 = root.GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren3) { renderers.Add(new RendererState(val)); if (val is MeshRenderer) { MeshFilter component = ((Component)val).GetComponent<MeshFilter>(); if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.sharedMesh) && component.sharedMesh.isReadable) { meshes.Add(new MeshState(component, stage == EffectStage.Shield && string.Equals(((Object)component).name, "Sphere", StringComparison.OrdinalIgnoreCase))); } } } } catch { Dispose(); throw; } } public void Apply(VisualOptions options) { if (disposed) { return; } foreach (LightState light in lights) { light.Apply(options.Light); } foreach (ParticleState particle in particles) { particle.Apply(options); } foreach (RendererState renderer in renderers) { renderer.Apply(options); } foreach (MeshState mesh in meshes) { mesh.Apply(options); } } public void ReleaseLightWrites() { foreach (LightState light in lights) { light.Restore(); } } public void Dispose() { if (disposed) { return; } foreach (ParticleState particle in particles) { try { particle.Restore(); } catch { } } foreach (LightState light in lights) { try { light.Restore(); } catch { } } foreach (RendererState renderer in renderers) { try { renderer.Dispose(); } catch { } } foreach (MeshState mesh in meshes) { try { mesh.Dispose(); } catch { } } disposed = true; } } internal sealed class LightState { private readonly Light light; private float native; private float lastWritten; private bool wrote; public LightState(Light light) { this.light = light; native = light.intensity; } public void Apply(float factor) { if (Object.op_Implicit((Object)(object)light)) { if (!wrote || light.intensity != lastWritten) { native = light.intensity; } lastWritten = native * factor; light.intensity = lastWritten; wrote = true; } } public void Restore() { if (Object.op_Implicit((Object)(object)light) && wrote && light.intensity == lastWritten) { light.intensity = native; } wrote = false; } } internal static class CurveScale { public static MinMaxCurve Multiply(MinMaxCurve original, float factor) { //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_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 //IL_0051: Unknown result type (might be due to invalid IL or missing references) ParticleSystemCurveMode mode = ((MinMaxCurve)(ref original)).mode; if ((int)mode != 0) { if ((int)mode == 3) { ((MinMaxCurve)(ref original)).constantMin = ((MinMaxCurve)(ref original)).constantMin * factor; ((MinMaxCurve)(ref original)).constantMax = ((MinMaxCurve)(ref original)).constantMax * factor; } else { ((MinMaxCurve)(ref original)).curveMultiplier = ((MinMaxCurve)(ref original)).curveMultiplier * factor; } } else { ((MinMaxCurve)(ref original)).constant = ((MinMaxCurve)(ref original)).constant * factor; } return original; } } internal sealed class ParticleState { private sealed class NativeParticle { public Color32 Color; public Vector3 Size; public float Remaining; public float Lifetime; public int Ticket; } private readonly ParticleSystem system; private readonly MinMaxCurve timeRate; private readonly MinMaxCurve distanceRate; private readonly Burst[] bursts; private readonly Dictionary<uint, List<NativeParticle>> live = new Dictionary<uint, List<NativeParticle>>(); private readonly List<uint> emptySeeds = new List<uint>(); private Particle[] buffer = (Particle[])(object)new Particle[64]; private float density = -1f; private int ticket; public ParticleState(ParticleSystem system) { //IL_003c: 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_0045: 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_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) this.system = system; EmissionModule emission = system.emission; timeRate = ((EmissionModule)(ref emission)).rateOverTime; distanceRate = ((EmissionModule)(ref emission)).rateOverDistance; bursts = (Burst[])(object)new Burst[((EmissionModule)(ref emission)).burstCount]; ((EmissionModule)(ref emission)).GetBursts(bursts); } public void Apply(VisualOptions options) { //IL_0025: 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_002e: 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_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)system)) { return; } if (density != options.Density) { EmissionModule emission = system.emission; ((EmissionModule)(ref emission)).rateOverTime = CurveScale.Multiply(timeRate, options.Density); ((EmissionModule)(ref emission)).rateOverDistance = CurveScale.Multiply(distanceRate, options.Density); Burst[] array = (Burst[])(object)new Burst[bursts.Length]; for (int i = 0; i < bursts.Length; i++) { array[i] = bursts[i]; ((Burst)(ref array[i])).count = CurveScale.Multiply(((Burst)(ref bursts[i])).count, options.Density); } ((EmissionModule)(ref emission)).SetBursts(array); density = options.Density; } ApplyLive(options); } private void ApplyLive(VisualOptions options) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0189: 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_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0146: 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_0211: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)system) || !((Component)system).gameObject.activeInHierarchy) { return; } int particleCount = system.particleCount; if (particleCount > buffer.Length) { buffer = (Particle[])(object)new Particle[Mathf.NextPowerOfTwo(particleCount)]; } particleCount = system.GetParticles(buffer); ticket++; for (int i = 0; i < particleCount; i++) { Particle val = buffer[i]; if (!live.TryGetValue(((Particle)(ref val)).randomSeed, out var value)) { value = new List<NativeParticle>(); live.Add(((Particle)(ref val)).randomSeed, value); } NativeParticle nativeParticle = null; float num = float.MaxValue; foreach (NativeParticle item in value) { float num2 = item.Remaining - ((Particle)(ref val)).remainingLifetime; if (item.Ticket != ticket && item.Lifetime == ((Particle)(ref val)).startLifetime && !(num2 < -0.0001f) && num2 < num) { nativeParticle = item; num = num2; } } if (nativeParticle == null) { nativeParticle = new NativeParticle { Color = ((Particle)(ref val)).startColor, Size = ((Particle)(ref val)).startSize3D, Lifetime = ((Particle)(ref val)).startLifetime }; value.Add(nativeParticle); } nativeParticle.Ticket = ticket; nativeParticle.Remaining = ((Particle)(ref val)).remainingLifetime; Color val2 = Color32.op_Implicit(nativeParticle.Color); if (options.TintEnabled) { val2.r = options.Tint.r; val2.g = options.Tint.g; val2.b = options.Tint.b; } val2.r *= options.Glow; val2.g *= options.Glow; val2.b *= options.Glow; val2.a *= options.Opacity; ((Particle)(ref val)).startColor = Color32.op_Implicit(val2); ((Particle)(ref val)).startSize3D = nativeParticle.Size * options.Size; buffer[i] = val; } system.SetParticles(buffer, particleCount); emptySeeds.Clear(); foreach (KeyValuePair<uint, List<NativeParticle>> item2 in live) { item2.Value.RemoveAll((NativeParticle p) => p.Ticket != ticket); if (item2.Value.Count == 0) { emptySeeds.Add(item2.Key); } } foreach (uint emptySeed in emptySeeds) { live.Remove(emptySeed); } } public void Restore() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: 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_002a: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)system)) { EmissionModule emission = system.emission; ((EmissionModule)(ref emission)).rateOverTime = timeRate; ((EmissionModule)(ref emission)).rateOverDistance = distanceRate; ((EmissionModule)(ref emission)).SetBursts(bursts); ApplyLive(VisualOptions.Original()); live.Clear(); } } } internal sealed class RendererState : IDisposable { private readonly Renderer renderer; private readonly bool forceOff; private readonly List<MaterialState> materials = new List<MaterialState>(); private readonly Material[] originals; private readonly Material[] clones; private readonly float width; private readonly bool particle; public RendererState(Renderer renderer) { //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown this.renderer = renderer; forceOff = renderer.forceRenderingOff; particle = renderer is ParticleSystemRenderer; TrailRenderer val = (TrailRenderer)(object)((renderer is TrailRenderer) ? renderer : null); LineRenderer val2 = (LineRenderer)(object)((renderer is LineRenderer) ? renderer : null); width = (Object.op_Implicit((Object)(object)val) ? val.widthMultiplier : (Object.op_Implicit((Object)(object)val2) ? val2.widthMultiplier : 1f)); originals = renderer.sharedMaterials; clones = (Material[])(object)new Material[originals.Length]; try { for (int i = 0; i < originals.Length; i++) { if (Object.op_Implicit((Object)(object)originals[i])) { clones[i] = new Material(originals[i]); materials.Add(new MaterialState(clones[i], particle)); } } renderer.sharedMaterials = clones; } catch { Dispose(); throw; } } public void Apply(VisualOptions options) { if (!Object.op_Implicit((Object)(object)renderer)) { return; } renderer.forceRenderingOff = forceOff || options.Opacity <= 0f || options.Size <= 0f || (particle && options.Density <= 0f); foreach (MaterialState material in materials) { material.Apply(options); } Renderer obj = renderer; TrailRenderer val = (TrailRenderer)(object)((obj is TrailRenderer) ? obj : null); if (Object.op_Implicit((Object)(object)val)) { val.widthMultiplier = width * options.Size; } Renderer obj2 = renderer; LineRenderer val2 = (LineRenderer)(object)((obj2 is LineRenderer) ? obj2 : null); if (Object.op_Implicit((Object)(object)val2)) { val2.widthMultiplier = width * options.Size; } } public void Dispose() { if (Object.op_Implicit((Object)(object)renderer)) { renderer.forceRenderingOff = forceOff; Material[] sharedMaterials = renderer.sharedMaterials; for (int i = 0; i < Math.Min(sharedMaterials.Length, originals.Length); i++) { if ((Object)(object)sharedMaterials[i] == (Object)(object)clones[i]) { sharedMaterials[i] = originals[i]; } } renderer.sharedMaterials = sharedMaterials; Renderer obj = renderer; TrailRenderer val = (TrailRenderer)(object)((obj is TrailRenderer) ? obj : null); if (Object.op_Implicit((Object)(object)val)) { val.widthMultiplier = width; } Renderer obj2 = renderer; LineRenderer val2 = (LineRenderer)(object)((obj2 is LineRenderer) ? obj2 : null); if (Object.op_Implicit((Object)(object)val2)) { val2.widthMultiplier = width; } } Material[] array = clones; foreach (Material val3 in array) { if (Object.op_Implicit((Object)(object)val3)) { ReleaseVisual.Destroy((Object)(object)val3); } } } } internal sealed class MaterialState { private sealed class ColorProperty { public string Name; public Color Native; public Color Last; public bool Written; public bool Emission; } private readonly Material material; private readonly bool particle; private readonly List<ColorProperty> colors = new List<ColorProperty>(); public MaterialState(Material material, bool particle) { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) this.material = material; this.particle = particle; string[] array = new string[6] { "_Color", "_BaseColor", "_TintColor", "_EmissionColor", "_EmissiveColor", "_EmisColor" }; foreach (string text in array) { if (material.HasProperty(text)) { colors.Add(new ColorProperty { Name = text, Native = material.GetColor(text), Emission = (text.IndexOf("Emis", StringComparison.Ordinal) >= 0) }); } } } public void Apply(VisualOptions options) { //IL_0033: 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) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: 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_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)material)) { return; } foreach (ColorProperty color2 in colors) { Color color = material.GetColor(color2.Name); if (color2.Written && color != color2.Last) { color2.Native = color; } Color native = color2.Native; if (options.TintEnabled) { native.r = options.Tint.r; native.g = options.Tint.g; native.b = options.Tint.b; } if (color2.Emission || !particle) { native.r *= options.Glow; native.g *= options.Glow; native.b *= options.Glow; } if (!particle) { native.a *= options.Opacity; } material.SetColor(color2.Name, native); color2.Last = native; color2.Written = true; } } } internal sealed class MeshState : IDisposable { private readonly MeshFilter filter; private readonly Mesh original; private readonly Mesh clone; private readonly Vector3[] vertices; private readonly Vector3[] adjusted; private readonly Vector3[] normals; private readonly Vector3[] adjustedNormals; private readonly Vector4[] tangents; private readonly Vector4[] adjustedTangents; private readonly Vector3 center; private readonly bool shieldBubble; private float size = -1f; private float ovality = -1f; public MeshState(MeshFilter filter, bool shieldBubble) { //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) this.filter = filter; this.shieldBubble = shieldBubble; original = filter.sharedMesh; clone = Object.Instantiate<Mesh>(original); vertices = original.vertices; normals = original.normals; adjustedNormals = (Vector3[])(object)new Vector3[normals.Length]; tangents = original.tangents; adjustedTangents = (Vector4[])(object)new Vector4[tangents.Length]; adjusted = (Vector3[])(object)new Vector3[vertices.Length]; Bounds bounds = original.bounds; center = ((Bounds)(ref bounds)).center; filter.sharedMesh = clone; } public void Apply(VisualOptions options) { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0079: 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_008b: 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_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: 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_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012b: 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_0143: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (