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 EffectsControl v1.0.1
BepInEx/plugins/EffectsControl/EffectsControl.dll
Decompiled 3 days agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [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("EffectsControl")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.1.0")] [assembly: AssemblyInformationalVersion("1.0.1+eeb528b28c25607007c89dd2879bde52435d99d9")] [assembly: AssemblyProduct("EffectsControl")] [assembly: AssemblyTitle("EffectsControl")] [assembly: AssemblyVersion("1.0.1.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace EffectsControl { public sealed class EffectCatalog { private sealed class StageBox { public EffectStage Stage; } private ConditionalWeakTable<EffectList, StageBox> lists = new ConditionalWeakTable<EffectList, StageBox>(); private int registeredLists; private readonly Dictionary<string, EffectStage> projectiles = new Dictionary<string, EffectStage>(StringComparer.Ordinal); private readonly Dictionary<string, EffectStage> effects = new Dictionary<string, EffectStage>(StringComparer.Ordinal); private readonly HashSet<GameObject> visited = new HashSet<GameObject>(); public int ListCount => registeredLists; public int ProjectileCount => projectiles.Count; public void Clear() { lists = new ConditionalWeakTable<EffectList, StageBox>(); registeredLists = 0; projectiles.Clear(); effects.Clear(); visited.Clear(); } public bool TryList(EffectList list, out EffectStage stage) { if (list != null && lists.TryGetValue(list, out var value)) { stage = value.Stage; return true; } stage = EffectStage.Launch; return false; } public bool TryProjectile(GameObject instance, out EffectStage stage) { return TryInstance(projectiles, instance, out stage); } public bool TryEffect(GameObject instance, out EffectStage stage) { return TryInstance(effects, instance, out stage); } private static bool TryInstance(Dictionary<string, EffectStage> prefabs, GameObject instance, out EffectStage stage) { stage = EffectStage.Launch; if (!Object.op_Implicit((Object)(object)instance)) { return false; } string text = ((Object)instance).name; if (text.EndsWith("(Clone)", StringComparison.Ordinal)) { text = text.Substring(0, text.Length - 7); } return prefabs.TryGetValue(text, out stage); } public static bool IsWeapon(ItemData item) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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_001c: Invalid comparison between Unknown and I4 //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Invalid comparison between Unknown and I4 //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Invalid comparison between Unknown and I4 //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Invalid comparison between Unknown and I4 //IL_0035: 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_003a: Invalid comparison between Unknown and I4 if (item == null || item.m_shared == null) { return false; } ItemType itemType = item.m_shared.m_itemType; if ((int)itemType <= 9) { if (itemType - 3 <= 1 || (int)itemType == 9) { goto IL_003c; } } else if ((int)itemType == 14 || (int)itemType == 20 || itemType - 22 <= 1) { goto IL_003c; } return false; IL_003c: return true; } public void RegisterItem(ItemData item) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Invalid comparison between Unknown and I4 if (IsWeapon(item)) { SharedData shared = item.m_shared; RegisterAttack(shared.m_attack); RegisterAttack(shared.m_secondaryAttack); Add(shared.m_startEffect, EffectStage.Launch); Add(shared.m_holdStartEffect, EffectStage.Launch); Add(shared.m_trailStartEffect, EffectStage.Launch); Add(shared.m_triggerEffect, (shared.m_attack != null && (int)shared.m_attack.m_attackType == 4) ? EffectStage.Impact : EffectStage.Launch); Add(shared.m_hitEffect, EffectStage.Impact); Add(shared.m_hitTerrainEffect, EffectStage.Impact); Visit(shared.m_spawnOnHit, EffectStage.Impact); Visit(shared.m_spawnOnHitTerrain, EffectStage.Impact); } } public void RegisterAttack(Attack attack) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Invalid comparison between Unknown and I4 if (attack != null) { Add(attack.m_startEffect, EffectStage.Launch); Add(attack.m_trailStartEffect, EffectStage.Launch); Add(attack.m_burstEffect, EffectStage.Launch); Add(attack.m_triggerEffect, ((int)attack.m_attackType == 4) ? EffectStage.Impact : EffectStage.Launch); Add(attack.m_hitEffect, EffectStage.Impact); Add(attack.m_hitTerrainEffect, EffectStage.Impact); Visit(attack.m_attackProjectile, EffectStage.Flight); Visit(attack.m_spawnOnTrigger, EffectStage.Impact); Visit(attack.m_spawnOnHit, EffectStage.Impact); } } public void RegisterProjectile(Projectile projectile) { Add(projectile.m_hitEffects, EffectStage.Impact); Add(projectile.m_hitWaterEffects, EffectStage.Impact); Add(projectile.m_spawnOnHitEffects, EffectStage.Impact); Visit(projectile.m_spawnOnHit, EffectStage.Impact); foreach (GameObject item in projectile.m_randomSpawnOnHit) { Visit(item, EffectStage.Impact); } } public void RegisterAoe(Aoe aoe) { Add(aoe.m_hitEffects, EffectStage.Impact); Add(aoe.m_initiateEffect, EffectStage.Impact); Add(aoe.m_chainEffects, EffectStage.Impact); Visit(aoe.m_chainObj, EffectStage.Impact); Visit(aoe.m_spawnOnHitTerrain, EffectStage.Impact); } public void RegisterShield(SE_Shield shield) { Add(((StatusEffect)shield).m_startEffects, EffectStage.Shield); Add(shield.m_hitEffects, EffectStage.Shield); Add(shield.m_breakEffects, EffectStage.Shield); Add(((StatusEffect)shield).m_stopEffects, EffectStage.Shield); } private void Add(EffectList list, EffectStage stage) { if (list == null || list.m_effectPrefabs == null || list.m_effectPrefabs.Length == 0) { return; } if (!lists.TryGetValue(list, out var value)) { lists.Add(list, new StageBox { Stage = stage }); registeredLists++; } else if (stage == EffectStage.Shield) { value.Stage = stage; } EffectData[] effectPrefabs = list.m_effectPrefabs; foreach (EffectData val in effectPrefabs) { if (val != null) { Visit(val.m_prefab, stage); } } } private void Visit(GameObject prefab, EffectStage stage) { if (!Object.op_Implicit((Object)(object)prefab) || Object.op_Implicit((Object)(object)prefab.GetComponentInChildren<Character>(true)) || Object.op_Implicit((Object)(object)prefab.GetComponentInChildren<Piece>(true))) { return; } Projectile component = prefab.GetComponent<Projectile>(); Aoe component2 = prefab.GetComponent<Aoe>(); EffectStage effectStage = ((stage == EffectStage.Shield) ? stage : (Object.op_Implicit((Object)(object)component2) ? EffectStage.Impact : stage)); if (!effects.ContainsKey(((Object)prefab).name) || effectStage == EffectStage.Shield) { effects[((Object)prefab).name] = effectStage; } if (visited.Add(prefab) && (Object.op_Implicit((Object)(object)component) || Object.op_Implicit((Object)(object)component2))) { projectiles[((Object)prefab).name] = (Object.op_Implicit((Object)(object)component2) ? EffectStage.Impact : stage); if (Object.op_Implicit((Object)(object)component)) { RegisterProjectile(component); } if (Object.op_Implicit((Object)(object)component2)) { RegisterAoe(component2); } } } } [BepInPlugin("Slikfoul.EffectsControl", "EffectsControl", "1.0.1")] [DefaultExecutionOrder(10000)] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "Slikfoul.EffectsControl"; public const string PluginName = "EffectsControl"; public const string PluginVersion = "1.0.1"; internal static Plugin Instance; internal readonly EffectCatalog Catalog = new EffectCatalog(); private readonly Dictionary<GameObject, VisualState> active = new Dictionary<GameObject, VisualState>(); private readonly Dictionary<GameObject, EffectStage> pending = new Dictionary<GameObject, EffectStage>(); private readonly HashSet<GameObject> pendingNetwork = new HashSet<GameObject>(); private readonly List<GameObject> expired = new List<GameObject>(); private readonly VisualOptions[] options = new VisualOptions[4]; private Settings settings; private Harmony harmony; private bool rebuild = true; private bool ready; private bool shieldConflict; private bool optionsDirty = true; private int failures; private void Awake() { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Invalid comparison between Unknown and I4 //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown Instance = this; settings = new Settings(((BaseUnityPlugin)this).Config); settings.Changed += delegate { optionsDirty = true; }; if ((int)SystemInfo.graphicsDeviceType == 4) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Client visual mod: headless host skipped."); return; } harmony = new Harmony("Slikfoul.EffectsControl"); try { harmony.PatchAll(typeof(Plugin).Assembly); ready = true; } catch (Exception ex) { harmony.UnpatchSelf(); ((BaseUnityPlugin)this).Logger.LogError((object)("EffectsControl patches failed; original visuals retained. " + ex)); } ((BaseUnityPlugin)this).Logger.LogInfo((object)"EffectsControl 1.0.1: weapon and magic shield visual controls ready."); } internal void RequestCatalog() { rebuild = true; } private void RebuildCatalog() { Catalog.Clear(); if (Object.op_Implicit((Object)(object)ObjectDB.instance)) { foreach (GameObject item in ObjectDB.instance.m_items) { if (Object.op_Implicit((Object)(object)item)) { ItemDrop component = item.GetComponent<ItemDrop>(); if (Object.op_Implicit((Object)(object)component)) { Catalog.RegisterItem(component.m_itemData); } } } foreach (StatusEffect statusEffect in ObjectDB.instance.m_StatusEffects) { SE_Shield val = (SE_Shield)(object)((statusEffect is SE_Shield) ? statusEffect : null); if (Object.op_Implicit((Object)(object)val)) { Catalog.RegisterShield(val); } } } foreach (GameObject key in active.Keys) { if (Object.op_Implicit((Object)(object)key)) { Projectile component2 = key.GetComponent<Projectile>(); if (Object.op_Implicit((Object)(object)component2)) { Catalog.RegisterProjectile(component2); } Aoe component3 = key.GetComponent<Aoe>(); if (Object.op_Implicit((Object)(object)component3)) { Catalog.RegisterAoe(component3); } } } bool flag = false; foreach (PluginInfo value in Chainloader.PluginInfos.Values) { if (string.Equals(value.Metadata.Name, "SubtleShield", StringComparison.OrdinalIgnoreCase) || value.Metadata.GUID.IndexOf("subtleshield", StringComparison.OrdinalIgnoreCase) >= 0) { flag = true; } } if (flag && !shieldConflict) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"SubtleShield is active. EffectsControl shield controls are suspended; disable SubtleShield and restart to use this mod's shield settings."); } shieldConflict = flag; optionsDirty = true; rebuild = false; } private void Update() { if (ready && rebuild) { Guard(RebuildCatalog); } } private void LateUpdate() { if (!ready) { return; } if (!rebuild) { foreach (GameObject item in pendingNetwork) { ObserveNetworkEffect(item); } pendingNetwork.Clear(); } RefreshOptions(); foreach (KeyValuePair<GameObject, EffectStage> pair in pending) { if (!Object.op_Implicit((Object)(object)pair.Key) || active.ContainsKey(pair.Key) || (pair.Value == EffectStage.Shield && shieldConflict)) { continue; } Guard(delegate { VisualState visualState = new VisualState(pair.Key, pair.Value); if (visualState.Empty) { visualState.Dispose(); } else { active.Add(pair.Key, visualState); } }); } pending.Clear(); expired.Clear(); foreach (KeyValuePair<GameObject, VisualState> item2 in active) { if (!Object.op_Implicit((Object)(object)item2.Key)) { item2.Value.Dispose(); expired.Add(item2.Key); continue; } try { item2.Value.Apply(options[(int)item2.Value.Stage]); } catch (Exception error) { item2.Value.Dispose(); expired.Add(item2.Key); Report(error); } } foreach (GameObject item3 in expired) { active.Remove(item3); } } internal void Observe(GameObject root, EffectStage stage) { if (ready && Object.op_Implicit((Object)(object)root) && !active.ContainsKey(root) && !pending.ContainsKey(root) && (stage != EffectStage.Shield || !shieldConflict) && !Object.op_Implicit((Object)(object)root.GetComponentInChildren<Character>(true)) && !Object.op_Implicit((Object)(object)root.GetComponentInChildren<Piece>(true))) { pending.Add(root, stage); } } private void RefreshOptions() { if (optionsDirty) { for (int i = 0; i < options.Length; i++) { options[i] = settings.Get((EffectStage)i, shieldConflict); } optionsDirty = false; } } internal void ObserveProjectile(GameObject root) { if (!ready || !Object.op_Implicit((Object)(object)root) || !Catalog.TryProjectile(root, out var stage)) { return; } Guard(delegate { Projectile component = root.GetComponent<Projectile>(); if (Object.op_Implicit((Object)(object)component)) { Catalog.RegisterProjectile(component); } Aoe component2 = root.GetComponent<Aoe>(); if (Object.op_Implicit((Object)(object)component2)) { Catalog.RegisterAoe(component2); } Observe(root, stage); }); } internal void ObserveNetworkEffect(GameObject root) { if (!ready || !Object.op_Implicit((Object)(object)root)) { return; } if (rebuild) { pendingNetwork.Add(root); } else { if (!Catalog.TryEffect(root, out var stage)) { return; } Guard(delegate { Projectile component = root.GetComponent<Projectile>(); if (Object.op_Implicit((Object)(object)component)) { Catalog.RegisterProjectile(component); } Aoe component2 = root.GetComponent<Aoe>(); if (Object.op_Implicit((Object)(object)component2)) { Catalog.RegisterAoe(component2); } Observe(root, stage); }); } } internal void Guard(Action action) { try { action(); } catch (Exception error) { Report(error); } } private void Report(Exception error) { if (failures++ < 5) { ((BaseUnityPlugin)this).Logger.LogError((object)("Visual control failed; gameplay continues. " + error)); } } private void OnDestroy() { ready = false; if (harmony != null) { harmony.UnpatchSelf(); } foreach (VisualState value in active.Values) { value.Dispose(); } active.Clear(); pending.Clear(); pendingNetwork.Clear(); Catalog.Clear(); Instance = null; } } [HarmonyPatch(typeof(ObjectDB), "Awake")] internal static class DatabaseAwakePatch { private static void Postfix() { if (Object.op_Implicit((Object)(object)Plugin.Instance)) { Plugin.Instance.RequestCatalog(); } } } [HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")] internal static class DatabaseCopyPatch { private static void Postfix() { if (Object.op_Implicit((Object)(object)Plugin.Instance)) { Plugin.Instance.RequestCatalog(); } } } [HarmonyPatch(typeof(ZNetScene), "Awake")] internal static class ScenePatch { private static void Postfix() { if (Object.op_Implicit((Object)(object)Plugin.Instance)) { Plugin.Instance.RequestCatalog(); } } } [HarmonyPatch(typeof(Attack), "Start")] internal static class AttackPatch { private static void Prefix(Attack __instance, ItemData weapon) { Plugin plugin = Plugin.Instance; if (Object.op_Implicit((Object)(object)plugin) && EffectCatalog.IsWeapon(weapon)) { plugin.Guard(delegate { plugin.Catalog.RegisterItem(weapon); plugin.Catalog.RegisterAttack(__instance); }); } } } [HarmonyPatch(typeof(EffectList), "Create")] internal static class EffectsPatch { private static void Postfix(EffectList __instance, GameObject[] __result) { Plugin instance = Plugin.Instance; if (Object.op_Implicit((Object)(object)instance) && __result != null && instance.Catalog.TryList(__instance, out var stage)) { foreach (GameObject root in __result) { instance.Observe(root, stage); } } } } [HarmonyPatch(typeof(Projectile), "Awake")] internal static class ProjectileAwakePatch { private static void Postfix(Projectile __instance) { if (Object.op_Implicit((Object)(object)Plugin.Instance)) { Plugin.Instance.ObserveProjectile(((Component)__instance).gameObject); } } } [HarmonyPatch(typeof(Aoe), "Awake")] internal static class AoeAwakePatch { private static void Postfix(Aoe __instance) { if (Object.op_Implicit((Object)(object)Plugin.Instance)) { Plugin.Instance.ObserveProjectile(((Component)__instance).gameObject); } } } [HarmonyPatch(typeof(ZNetScene), "CreateObject")] internal static class NetworkEffectsPatch { private static void Postfix(GameObject __result) { if (Object.op_Implicit((Object)(object)Plugin.Instance) && Object.op_Implicit((Object)(object)__result)) { Plugin.Instance.ObserveNetworkEffect(__result); } } } [HarmonyPatch(typeof(Projectile), "Setup")] internal static class ProjectileSetupPatch { private static void Postfix(Projectile __instance, ItemData item, ItemData ammo) { Plugin p = Plugin.Instance; if (Object.op_Implicit((Object)(object)p) && (EffectCatalog.IsWeapon(item) || EffectCatalog.IsWeapon(ammo))) { p.Guard(delegate { p.Catalog.RegisterProjectile(__instance); p.Observe(((Component)__instance).gameObject, EffectStage.Flight); }); } } } [HarmonyPatch(typeof(Aoe), "Setup")] internal static class AoeSetupPatch { private static void Postfix(Aoe __instance, ItemData item, ItemData ammo) { Plugin p = Plugin.Instance; if (Object.op_Implicit((Object)(object)p) && (EffectCatalog.IsWeapon(item) || EffectCatalog.IsWeapon(ammo))) { p.Guard(delegate { p.Catalog.RegisterAoe(__instance); p.Observe(((Component)__instance).gameObject, EffectStage.Impact); }); } } } [HarmonyPatch(typeof(SE_Shield), "Setup")] internal static class ShieldPatch { private static void Prefix(SE_Shield __instance) { Plugin p = Plugin.Instance; if (Object.op_Implicit((Object)(object)p)) { p.Guard(delegate { p.Catalog.RegisterShield(__instance); }); } } } public enum EffectStage { Launch, Flight, Impact, 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 Settings { public readonly ConfigEntry<bool> Enabled; public readonly ConfigEntry<bool> Weapons; public readonly ConfigEntry<bool> Shields; public readonly ConfigEntry<bool> ShieldTint; public readonly ConfigEntry<int> Light; public readonly ConfigEntry<int> Glow; public readonly ConfigEntry<int> Opacity; public readonly ConfigEntry<int> Size; public readonly ConfigEntry<int> Density; public readonly ConfigEntry<int> Launch; public readonly ConfigEntry<int> Flight; public readonly ConfigEntry<int> Impact; public readonly ConfigEntry<int> ShieldLight; public readonly ConfigEntry<int> ShieldGlow; public readonly ConfigEntry<int> ShieldOpacity; public readonly ConfigEntry<int> ShieldOvality; public readonly ConfigEntry<int> ShieldColor; public event Action Changed; public Settings(ConfigFile config) { Enabled = config.Bind<bool>("1. General", "Enable mod", true, "Enable visual settings. Disabling restores the saved original appearance of active effects."); Weapons = config.Bind<bool>("1. General", "Weapon effects", true, "Control attack launch, flight and impact effects. Weather, fog and building lights are excluded."); Shields = config.Bind<bool>("1. General", "Magic shield", true, "Control Staff of Protection visuals. Shield control is suspended while SubtleShield is active; disable it and restart to use these settings."); Light = Percent(config, "2. Weapons - General", "Light brightness", 0, "Light intensity: reduce surrounding illumination and whiteout. Light range is unchanged."); Glow = Percent(config, "2. Weapons - General", "Glow", 50, "Particle colors and supported emissive/additive material colors. Some custom shaders ignore these properties."); Opacity = Percent(config, "2. Weapons - General", "Opacity", 25, "Particle and material alpha. Lower values increase transparency. Custom and opaque shaders may ignore alpha; 0 hides the visual renderers."); Size = Percent(config, "2. Weapons - General", "Size", 100, "Particle size, readable mesh geometry and trail width. Root transforms, colliders, trajectories, damage radius and particle travel distance are unchanged."); Density = Percent(config, "2. Weapons - General", "Particle count", 100, "Emission rates and burst counts relative to the original. Existing particles retain their lifetime; 0 hides particles. Direct Emit calls from other code are not limited at intermediate values."); Launch = Influence(config, "Attack launch", 100, "Influence of general settings on windup and projectile launch effects."); Flight = Influence(config, "Flight", 0, "Influence of general settings on a flying projectile. Speed and collisions are unchanged."); Impact = Influence(config, "Impact", 100, "Influence of general settings on hits, explosions and Aoe, including Demolisher hits."); ShieldLight = Percent(config, "4. Magic Shield", "Light brightness", 35, "Intensity of lights in the magic shield effect."); ShieldGlow = Percent(config, "4. Magic Shield", "Glow", 45, "Supported emissive/additive colors of the bubble and particles."); ShieldOpacity = Percent(config, "4. Magic Shield", "Opacity", 30, "Bubble and particle alpha. 0 hides the visual shield; protection and duration are unchanged."); ShieldOvality = Integer(config, "Ovality", 50, 0, 100, "Bubble shape: 0 is round; 50 is oval; 100 is a narrower oval. Height, protection and colliders are unchanged. Whole numbers only."); ShieldTint = config.Bind<bool>("4. Magic Shield", "Change color", false, "Replace supported material and particle RGB colors. Disable for original colors; alpha is controlled separately."); ShieldColor = Integer(config, "Color", 0, 0, 360, "Hue slider: 0/360 red, 60 yellow, 120 green, 180 cyan, 240 blue, 300 magenta. Used when Change color is enabled. Glow controls intensity; Opacity controls transparency. Whole numbers only."); config.SettingChanged += delegate { if (this.Changed != null) { this.Changed(); } }; } private static ConfigEntry<int> Percent(ConfigFile config, string section, string key, int value, 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 + " 100% is the original value; 0% disables this visual component. Whole numbers only. Scaling does not accumulate.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); } private static ConfigEntry<int> Influence(ConfigFile config, string key, int value, string description) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown return config.Bind<int>("3. Weapons - Stages", key, value, new ConfigDescription(description + " 100% fully applies section 2 settings; 0% restores the original effect without their influence. Intermediate values blend the influence. Whole numbers only.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); } private static ConfigEntry<int> Integer(ConfigFile config, string key, int value, int min, int max, string description) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown return config.Bind<int>("4. Magic Shield", key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<int>(min, max), Array.Empty<object>())); } public VisualOptions Get(EffectStage stage, bool shieldConflict) { //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_00d9: 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) if (!Enabled.Value || ((stage == EffectStage.Shield) ? (!Shields.Value || shieldConflict) : (!Weapons.Value))) { return VisualOptions.Original(); } int value; switch (stage) { case EffectStage.Shield: { Color tint = Color.HSVToRGB((float)ShieldColor.Value / 360f, 1f, 1f); return new VisualOptions { Light = (float)ShieldLight.Value / 100f, Glow = (float)ShieldGlow.Value / 100f, Opacity = (float)ShieldOpacity.Value / 100f, ShieldOvality = (float)ShieldOvality.Value / 100f, TintEnabled = ShieldTint.Value, Tint = tint }; } default: value = Impact.Value; break; case EffectStage.Flight: value = Flight.Value; break; case EffectStage.Launch: value = Launch.Value; break; } float num = (float)value / 100f; return new VisualOptions { Light = Mathf.Lerp(1f, (float)Light.Value / 100f, num), Glow = Mathf.Lerp(1f, (float)Glow.Value / 100f, num), Opacity = Mathf.Lerp(1f, (float)Opacity.Value / 100f, num), Size = Mathf.Lerp(1f, (float)Size.Value / 100f, num), Density = Mathf.Lerp(1f, (float)Density.Value / 100f, num) }; } } 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 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; } } } 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 (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)filter) || (Object)(object)filter.sharedMesh != (Object)(object)clone) { return; } float num = (shieldBubble ? Mathf.Clamp01(options.ShieldOvality) : 0f); if (options.Size == size && num == ovality) { return; } float num2 = 1f - num * 0.5f; Vector3 val = new Vector3(num2, 1f, num2) * options.Size; for (int i = 0; i < vertices.Length; i++) { adjusted[i] = center + Vector3.Scale(vertices[i] - center, val); } clone.vertices = adjusted; for (int j = 0; j < normals.Length; j++) { Vector3[] array = adjustedNormals; int num3 = j; ? val3; if (num != 0f) { Vector3 val2 = new Vector3(normals[j].x / num2, normals[j].y, normals[j].z / num2); val3 = ((Vector3)(ref val2)).normalized; } else { val3 = normals[j]; } array[num3] = (Vector3)val3; } Vector3 val4 = default(Vector3); for (int k = 0; k < tangents.Length; k++) { if (num == 0f) { adjustedTangents[k] = tangents[k]; continue; } ((Vector3)(ref val4))..ctor(tangents[k].x * num2, tangents[k].y, tangents[k].z * num2); if (k < adjustedNormals.Length) { val4 -= adjustedNormals[k] * Vector3.Dot(adjustedNormals[k], val4); } ((Vector3)(ref val4)).Normalize(); adjustedTangents[k] = new Vector4(val4.x, val4.y, val4.z, tangents[k].w); } clone.normals = adjustedNormals; clone.tangents = adjustedTangents; clone.RecalculateBounds(); size = options.Size; ovality = num; } public void Dispose() { if (Object.op_Implicit((Object)(object)filter) && (Object)(object)filter.sharedMesh == (Object)(object)clone) { filter.sharedMesh = original; } if (Object.op_Implicit((Object)(object)clone)) { ReleaseVisual.Destroy((Object)(object)clone); } } } internal static class ReleaseVisual { public static void Destroy(Object resource) { if (Application.isPlaying) { Object.Destroy(resource); } else { Object.DestroyImmediate(resource); } } } }