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 DimmerCombatParticleEffects v1.1.0
plugins\DimmerCombatParticleEffects.dll
Decompiled 3 weeks agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using DimmerCombatParticleEffects.HitVfx; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_utils")] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("DimmerCombatParticleEffects")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.1.0.0")] [assembly: AssemblyInformationalVersion("1.1.0+7e0271ad4228e614d3b2c485f5be1b5d97f75767")] [assembly: AssemblyProduct("DimmerCombatParticleEffects")] [assembly: AssemblyTitle("DimmerCombatParticleEffects")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.0.0")] [module: UnverifiableCode] [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 DimmerCombatParticleEffects { [BepInPlugin("wheeze.valheim.dimmercombatparticleeffects", "Dimmer Combat Particle Effects", "1.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string PluginGuid = "wheeze.valheim.dimmercombatparticleeffects"; public const string PluginName = "Dimmer Combat Particle Effects"; public const string PluginVersion = "1.1.0"; internal static ManualLogSource Log; internal static Plugin Instance; private Harmony _harmony; private void Awake() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Instance = this; HitVfxSettings.Bind(((BaseUnityPlugin)this).Config); ParticleProbe.Reset(); _harmony = new Harmony("wheeze.valheim.dimmercombatparticleeffects"); _harmony.PatchAll(typeof(Plugin).Assembly); Log.LogInfo((object)string.Format("{0} {1} loaded; {2} method(s) patched.", "Dimmer Combat Particle Effects", "1.1.0", _harmony.GetPatchedMethods().Count())); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } HitEffectScope.Reset(); HitVfxCatalog.Reset(); Instance = null; ManualLogSource log = Log; if (log != null) { log.LogInfo((object)"Dimmer Combat Particle Effects unloaded."); } } } } namespace DimmerCombatParticleEffects.Patches { [HarmonyPatch(typeof(Aoe), "OnHit", new Type[] { typeof(Collider), typeof(Vector3) })] internal static class AoeOnHitPatch { [HarmonyPrefix] private static void Prefix(Aoe __instance, out int __state) { __state = HitEffectScope.Depth; if (HitVfxSettings.ShouldDampen(HitVfxSettings.AoeHits)) { HitEffectScope.Arm(__instance.m_hitEffects); } } [HarmonyFinalizer] private static void Finalizer(int __state) { HitEffectScope.UnwindTo(__state); } } internal static class AttackHitEffects { public static void Arm(Attack attack) { if (attack != null && HitVfxSettings.ShouldDampen(HitVfxSettings.WeaponHits)) { HitEffectScope.Arm(attack.m_hitEffect); ItemData weapon = attack.m_weapon; if (weapon?.m_shared != null) { HitEffectScope.Arm(weapon.m_shared.m_hitEffect); } } } } [HarmonyPatch(typeof(Attack), "DoMeleeAttack", new Type[] { })] internal static class AttackDoMeleeAttackPatch { [HarmonyPrefix] private static void Prefix(Attack __instance, out int __state) { __state = HitEffectScope.Depth; AttackHitEffects.Arm(__instance); } [HarmonyFinalizer] private static void Finalizer(int __state) { HitEffectScope.UnwindTo(__state); } } [HarmonyPatch(typeof(Attack), "DoAreaAttack", new Type[] { })] internal static class AttackDoAreaAttackPatch { [HarmonyPrefix] private static void Prefix(Attack __instance, out int __state) { __state = HitEffectScope.Depth; AttackHitEffects.Arm(__instance); } [HarmonyFinalizer] private static void Finalizer(int __state) { HitEffectScope.UnwindTo(__state); } } [HarmonyPatch(typeof(Character), "ApplyDamage", new Type[] { typeof(HitData), typeof(bool), typeof(bool), typeof(DamageModifier) })] internal static class CharacterApplyDamagePatch { [HarmonyPrefix] private static void Prefix(Character __instance, out int __state) { __state = HitEffectScope.Depth; if (HitVfxSettings.ShouldDampenCharacter(__instance)) { HitEffectScope.Arm(__instance.m_hitEffects); } } [HarmonyFinalizer] private static void Finalizer(int __state) { HitEffectScope.UnwindTo(__state); } } [HarmonyPatch(typeof(Character), "RPC_Damage", new Type[] { typeof(long), typeof(HitData) })] internal static class CharacterRpcDamagePatch { [HarmonyPrefix] private static void Prefix(Character __instance, out int __state) { __state = HitEffectScope.Depth; if (HitVfxSettings.ShouldDampenCharacter(__instance)) { HitEffectScope.Arm(__instance.m_critHitEffects); HitEffectScope.Arm(__instance.m_backstabHitEffects); } } [HarmonyFinalizer] private static void Finalizer(int __state) { HitEffectScope.UnwindTo(__state); } } [HarmonyPatch(typeof(EffectList), "Create")] internal static class EffectListCreatePatch { [HarmonyPostfix] private static void Postfix(EffectList __instance, GameObject[] __result) { if (__result == null || __result.Length == 0) { return; } bool flag = HitEffectScope.Depth > 0 && HitEffectScope.IsArmed(__instance); if (flag) { ParticleDampener.Apply(__result, HitVfxSettings.Opacity.Value, HitVfxSettings.Brightness.Value, HitVfxSettings.Size.Value); } if (HitVfxSettings.LogAllEffects.Value || (flag && HitVfxSettings.LogDampenedEffects.Value)) { string text = (flag ? "dampened" : "skipped"); for (int i = 0; i < __result.Length; i++) { Plugin.Log.LogInfo((object)("[HitVfx " + text + "] " + ParticleDampener.Describe(__result[i]))); } } } } [HarmonyPatch(typeof(Projectile), "OnHit", new Type[] { typeof(Collider), typeof(Vector3), typeof(bool), typeof(Vector3) })] internal static class ProjectileOnHitPatch { [HarmonyPrefix] private static void Prefix(Projectile __instance, out int __state) { __state = HitEffectScope.Depth; if (HitVfxSettings.ShouldDampen(HitVfxSettings.ProjectileHits)) { HitEffectScope.Arm(__instance.m_hitEffects); } } [HarmonyFinalizer] private static void Finalizer(int __state) { HitEffectScope.UnwindTo(__state); } } [HarmonyPatch(typeof(SE_Burning), "UpdateStatusEffect", new Type[] { typeof(float) })] internal static class SeBurningUpdatePatch { [HarmonyPrefix] private static void Prefix(SE_Burning __instance, out int __state) { __state = HitEffectScope.Depth; if (HitVfxSettings.ShouldDampenStatusEffect(((StatusEffect)__instance).m_character)) { HitEffectScope.Arm(__instance.m_tickEffect); } } [HarmonyFinalizer] private static void Finalizer(int __state) { HitEffectScope.UnwindTo(__state); } } [HarmonyPatch(typeof(SE_Poison), "UpdateStatusEffect", new Type[] { typeof(float) })] internal static class SePoisonUpdatePatch { [HarmonyPrefix] private static void Prefix(SE_Poison __instance, out int __state) { __state = HitEffectScope.Depth; if (HitVfxSettings.ShouldDampenStatusEffect(((StatusEffect)__instance).m_character)) { HitEffectScope.Arm(__instance.m_tickEffect); } } [HarmonyFinalizer] private static void Finalizer(int __state) { HitEffectScope.UnwindTo(__state); } } [HarmonyPatch(typeof(SE_Stats), "UpdateStatusEffect", new Type[] { typeof(float) })] internal static class SeStatsUpdatePatch { [HarmonyPrefix] private static void Prefix(SE_Stats __instance, out int __state) { __state = HitEffectScope.Depth; if (HitVfxSettings.ShouldDampenStatusEffect(((StatusEffect)__instance).m_character)) { HitEffectScope.Arm(__instance.m_tickEffect); } } [HarmonyFinalizer] private static void Finalizer(int __state) { HitEffectScope.UnwindTo(__state); } } [HarmonyPatch(typeof(StatusEffect), "TriggerStartEffects", new Type[] { })] internal static class StatusEffectTriggerStartEffectsPatch { [HarmonyPrefix] private static void Prefix(StatusEffect __instance, out int __state) { __state = HitEffectScope.Depth; if (HitVfxSettings.ShouldDampenStatusEffect(__instance.m_character)) { HitEffectScope.Arm(__instance.m_startEffects); } } [HarmonyFinalizer] private static void Finalizer(int __state) { HitEffectScope.UnwindTo(__state); } } [HarmonyPatch(typeof(ZNetScene), "CreateObject", new Type[] { typeof(ZDO) })] internal static class ZNetSceneCreateObjectPatch { [HarmonyPostfix] private static void Postfix(ZDO zdo, GameObject __result) { if (!((Object)(object)__result == (Object)null) && zdo != null && HitVfxSettings.Enabled.Value && HitVfxCatalog.TryGetSource(zdo.GetPrefab(), out var source)) { bool flag = HitVfxSettings.IsSourceEnabled(source); if (flag) { ParticleDampener.Apply(__result, HitVfxSettings.Opacity.Value, HitVfxSettings.Brightness.Value, HitVfxSettings.Size.Value); } if (HitVfxSettings.LogAllEffects.Value || (flag && HitVfxSettings.LogDampenedEffects.Value)) { string arg = (flag ? "dampened" : "skipped"); Plugin.Log.LogInfo((object)$"[HitVfx {arg} networked/{source}] {ParticleDampener.Describe(__result)}"); } } } } } namespace DimmerCombatParticleEffects.HitVfx { internal static class HitEffectScope { private static readonly List<EffectList> Armed = new List<EffectList>(8); public static int Depth => Armed.Count; public static void Arm(EffectList list) { if (list != null) { Armed.Add(list); } } public static void UnwindTo(int depth) { if (depth < 0) { depth = 0; } if (Armed.Count > depth) { Armed.RemoveRange(depth, Armed.Count - depth); } } public static bool IsArmed(EffectList list) { for (int num = Armed.Count - 1; num >= 0; num--) { if (Armed[num] == list) { return true; } } return false; } public static void Reset() { Armed.Clear(); } } [Flags] internal enum HitVfxSource { None = 0, Character = 1, Weapon = 2, Projectile = 4, Aoe = 8, StatusEffect = 0x10 } internal static class HitVfxCatalog { private static readonly Dictionary<int, HitVfxSource> ByPrefabHash = new Dictionary<int, HitVfxSource>(); private static bool _built; public static int Count => ByPrefabHash.Count; public static void Reset() { ByPrefabHash.Clear(); _built = false; } public static bool TryGetSource(int prefabHash, out HitVfxSource source) { if (!_built) { Build(); } return ByPrefabHash.TryGetValue(prefabHash, out source); } private static void Build() { ZNetScene instance = ZNetScene.instance; ObjectDB instance2 = ObjectDB.instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance2 == (Object)null) { return; } ByPrefabHash.Clear(); for (int i = 0; i < instance.m_prefabs.Count; i++) { GameObject val = instance.m_prefabs[i]; if (!((Object)(object)val == (Object)null)) { Character component = val.GetComponent<Character>(); if ((Object)(object)component != (Object)null) { Add(component.m_hitEffects, HitVfxSource.Character); Add(component.m_critHitEffects, HitVfxSource.Character); Add(component.m_backstabHitEffects, HitVfxSource.Character); } Projectile component2 = val.GetComponent<Projectile>(); if ((Object)(object)component2 != (Object)null) { Add(component2.m_hitEffects, HitVfxSource.Projectile); } Aoe component3 = val.GetComponent<Aoe>(); if ((Object)(object)component3 != (Object)null) { Add(component3.m_hitEffects, HitVfxSource.Aoe); } AddItem(val); } } for (int j = 0; j < instance2.m_items.Count; j++) { AddItem(instance2.m_items[j]); } for (int k = 0; k < instance2.m_StatusEffects.Count; k++) { StatusEffect val2 = instance2.m_StatusEffects[k]; if ((Object)(object)val2 == (Object)null) { continue; } Add(val2.m_startEffects, HitVfxSource.StatusEffect); SE_Burning val3 = (SE_Burning)(object)((val2 is SE_Burning) ? val2 : null); if (val3 != null) { Add(val3.m_tickEffect, HitVfxSource.StatusEffect); continue; } SE_Poison val4 = (SE_Poison)(object)((val2 is SE_Poison) ? val2 : null); if (val4 != null) { Add(val4.m_tickEffect, HitVfxSource.StatusEffect); continue; } SE_Stats val5 = (SE_Stats)(object)((val2 is SE_Stats) ? val2 : null); if (val5 != null) { Add(val5.m_tickEffect, HitVfxSource.StatusEffect); } } _built = true; Plugin.Log.LogInfo((object)$"Hit VFX catalog built: {ByPrefabHash.Count} prefab(s) recognised."); } private static void AddItem(GameObject prefab) { SharedData val = prefab.GetComponent<ItemDrop>()?.m_itemData?.m_shared; if (val != null) { Add(val.m_hitEffect, HitVfxSource.Weapon); Add(val.m_attack?.m_hitEffect, HitVfxSource.Weapon); Add(val.m_secondaryAttack?.m_hitEffect, HitVfxSource.Weapon); } } private static void Add(EffectList list, HitVfxSource source) { if (list?.m_effectPrefabs == null) { return; } for (int i = 0; i < list.m_effectPrefabs.Length; i++) { GameObject val = list.m_effectPrefabs[i]?.m_prefab; if (!((Object)(object)val == (Object)null)) { int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)val).name); ByPrefabHash.TryGetValue(stableHashCode, out var value); ByPrefabHash[stableHashCode] = value | source; } } } } internal static class HitVfxSettings { private const string SectionGeneral = "1 - General"; private const string SectionStrength = "2 - Strength"; private const string SectionSources = "3 - Sources"; private const string SectionServer = "4 - Server"; public static SyncedSetting<bool> Enabled; public static SyncedSetting<float> Opacity; public static SyncedSetting<float> Brightness; public static SyncedSetting<float> Size; public static SyncedSetting<bool> CharacterHits; public static SyncedSetting<bool> WeaponHits; public static SyncedSetting<bool> ProjectileHits; public static SyncedSetting<bool> AoeHits; public static SyncedSetting<bool> StatusEffectVisuals; public static SyncedSetting<bool> IncludePlayerHits; public static ConfigEntry<bool> ForceServerSync; public static ConfigEntry<bool> LogDampenedEffects; public static ConfigEntry<bool> LogAllEffects; private static readonly List<object> Tunables = new List<object>(); public static bool UseEntryValues { get { if (ForceServerSync != null && ForceServerSync.Value) { return true; } ZNet instance = ZNet.instance; if (!((Object)(object)instance == (Object)null)) { return instance.IsServer(); } return true; } } public static void Bind(ConfigFile cfg) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Expected O, but got Unknown //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_011b: 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_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Expected O, but got Unknown //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Expected O, but got Unknown //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Expected O, but got Unknown //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Expected O, but got Unknown //IL_025b: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Expected O, but got Unknown //IL_028f: Unknown result type (might be due to invalid IL or missing references) //IL_0299: Expected O, but got Unknown ForceServerSync = cfg.Bind<bool>("4 - Server", "Force server sync", false, new ConfigDescription("Server admins only. When on, every setting below is taken from the server and applied to everyone connected, overriding their own. When off, each player keeps their own settings. Has no effect in single player, where your settings are always used.", (AcceptableValueBase)null, new object[1] { Admin() })); Enabled = Tunable<bool>(cfg.Bind<bool>("1 - General", "Enabled", true, new ConfigDescription("Dampen the particle effects that burst out of a target when it is struck. Lights are never touched, so hits still illuminate dark areas.", (AcceptableValueBase)null, new object[1] { Admin() }))); LogDampenedEffects = cfg.Bind<bool>("1 - General", "Log dampened effects", false, "Write one line to the BepInEx log for every effect that gets dampened, listing its particle systems, its lights, and any mesh renderers this mod does not touch. Diagnostic only - never synced, never affects other players."); LogAllEffects = cfg.Bind<bool>("1 - General", "Log every effect", false, "Log every effect the game spawns, including the ones this mod leaves alone, marked dampened or skipped. Use this to find an effect that is still too loud: whatever is bothering you will appear in the log as skipped, which names the prefab and tells us which spawn path is still uncovered. Very noisy - diagnostic only."); Opacity = Tunable<float>(cfg.Bind<float>("2 - Strength", "Opacity", 0.35f, new ConfigDescription("Alpha multiplier applied to hit particles. 1 is vanilla, 0 is invisible. Lower this until enemy wind-up animations read clearly through the effect.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), new object[1] { Admin() }))); Brightness = Tunable<float>(cfg.Bind<float>("2 - Strength", "Brightness", 1f, new ConfigDescription("Colour multiplier applied to hit particles. Leave at 1 unless an effect stays bright after lowering Opacity, which means its shader blends additively and ignores alpha. Lowering this dims those without touching any light source.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), new object[1] { Admin() }))); Size = Tunable<float>(cfg.Bind<float>("2 - Strength", "Size", 1f, new ConfigDescription("Size multiplier applied to hit particles. 1 is vanilla. Lower it to shrink the area an effect covers instead of only fading it.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 1f), new object[1] { Admin() }))); CharacterHits = Tunable<bool>(cfg.Bind<bool>("3 - Sources", "Character hit effects", true, new ConfigDescription("Dampen the burst the struck creature itself spawns: blood, impact sparks, and the extra crit and backstab bursts.", (AcceptableValueBase)null, new object[1] { Admin() }))); WeaponHits = Tunable<bool>(cfg.Bind<bool>("3 - Sources", "Weapon hit effects", true, new ConfigDescription("Dampen the burst the attacking weapon spawns at the point of impact. This is where the elemental effects live - fire, frost, lightning, poison, spirit.", (AcceptableValueBase)null, new object[1] { Admin() }))); ProjectileHits = Tunable<bool>(cfg.Bind<bool>("3 - Sources", "Projectile hit effects", true, new ConfigDescription("Dampen the burst an arrow, bolt, or staff projectile spawns where it lands. Water splashes are a separate effect and are left alone.", (AcceptableValueBase)null, new object[1] { Admin() }))); AoeHits = Tunable<bool>(cfg.Bind<bool>("3 - Sources", "Area of effect hit effects", true, new ConfigDescription("Dampen the burst an area attack spawns on each thing it hits: atgeir sweeps, bombs, ground slams.", (AcceptableValueBase)null, new object[1] { Admin() }))); StatusEffectVisuals = Tunable<bool>(cfg.Bind<bool>("3 - Sources", "Status effect visuals on creatures", true, new ConfigDescription("Dampen the lingering aura a status effect puts on a creature - the flames on a burning enemy, the frost shell, the poison cloud - and the burst it re-spawns on every damage tick. These persist for the whole duration rather than flashing once, so they hide a creature far longer than the impact burst does. Never applied to players.", (AcceptableValueBase)null, new object[1] { Admin() }))); IncludePlayerHits = Tunable<bool>(cfg.Bind<bool>("3 - Sources", "Include hits on players", false, new ConfigDescription("Also dampen the character hit effects spawned when a player is the one struck. Off by default so your own damage feedback stays at full strength.", (AcceptableValueBase)null, new object[1] { Admin() }))); cfg.SettingChanged += delegate { if (UseEntryValues) { CaptureLocalValues(); } }; } private static ConfigurationManagerAttributes Admin() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown return new ConfigurationManagerAttributes { IsAdminOnly = true }; } private static SyncedSetting<T> Tunable<T>(ConfigEntry<T> entry) { SyncedSetting<T> syncedSetting = new SyncedSetting<T>(entry); Tunables.Add(syncedSetting); return syncedSetting; } private static void CaptureLocalValues() { foreach (object tunable in Tunables) { (tunable as SyncedSetting<bool>)?.CaptureLocal(); (tunable as SyncedSetting<float>)?.CaptureLocal(); } } public static bool ShouldDampenCharacter(Character victim) { if (!Enabled.Value || !CharacterHits.Value || (Object)(object)victim == (Object)null) { return false; } if (!IncludePlayerHits.Value) { return !victim.IsPlayer(); } return true; } public static bool ShouldDampenStatusEffect(Character carrier) { if (Enabled.Value && StatusEffectVisuals.Value && (Object)(object)carrier != (Object)null) { return !carrier.IsPlayer(); } return false; } public static bool ShouldDampen(SyncedSetting<bool> source) { if (Enabled.Value) { return source.Value; } return false; } public static bool IsSourceEnabled(HitVfxSource source) { if ((source & HitVfxSource.Character) != HitVfxSource.None && CharacterHits.Value) { return true; } if ((source & HitVfxSource.Weapon) != HitVfxSource.None && WeaponHits.Value) { return true; } if ((source & HitVfxSource.Projectile) != HitVfxSource.None && ProjectileHits.Value) { return true; } if ((source & HitVfxSource.Aoe) != HitVfxSource.None && AoeHits.Value) { return true; } if ((source & HitVfxSource.StatusEffect) != HitVfxSource.None && StatusEffectVisuals.Value) { return true; } return false; } } internal static class ParticleDampener { public static void Apply(GameObject[] spawned, float alpha, float brightness, float size) { if (spawned != null) { for (int i = 0; i < spawned.Length; i++) { Apply(spawned[i], alpha, brightness, size); } } } public static void Apply(GameObject root, float alpha, float brightness, float size) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0065: 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_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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_009e: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: 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_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)root == (Object)null) { return; } bool flag = alpha < 1f || brightness < 1f; bool flag2 = size < 1f; if (!flag && !flag2) { return; } bool active = ParticleProbe.Active; ParticleSystem[] componentsInChildren = root.GetComponentsInChildren<ParticleSystem>(true); foreach (ParticleSystem val in componentsInChildren) { if ((Object)(object)val == (Object)null) { continue; } MainModule main = val.main; MinMaxGradient beforeColour = (MinMaxGradient)(active ? ((MainModule)(ref main)).startColor : default(MinMaxGradient)); MinMaxCurve beforeSize = (MinMaxCurve)(active ? ((MainModule)(ref main)).startSize : default(MinMaxCurve)); if (flag) { ((MainModule)(ref main)).startColor = ScaleGradient(((MainModule)(ref main)).startColor, alpha, brightness); } if (flag2) { if (((MainModule)(ref main)).startSize3D) { ((MainModule)(ref main)).startSizeX = ScaleCurve(((MainModule)(ref main)).startSizeX, size); ((MainModule)(ref main)).startSizeY = ScaleCurve(((MainModule)(ref main)).startSizeY, size); ((MainModule)(ref main)).startSizeZ = ScaleCurve(((MainModule)(ref main)).startSizeZ, size); } else { ((MainModule)(ref main)).startSize = ScaleCurve(((MainModule)(ref main)).startSize, size); } } if (active) { ParticleProbe.Report(root, val, beforeColour, beforeSize); } } } public static string Describe(GameObject root) { if ((Object)(object)root == (Object)null) { return "<destroyed>"; } int num = root.GetComponentsInChildren<ParticleSystem>(true).Length; int num2 = root.GetComponentsInChildren<Light>(true).Length; int num3 = 0; Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true); for (int i = 0; i < componentsInChildren.Length; i++) { if (!(componentsInChildren[i] is ParticleSystemRenderer)) { num3++; } } return $"{((Object)root).name}: {num} particle system(s), " + $"{num2} light(s), {num3} non-particle renderer(s)"; } private static MinMaxGradient ScaleGradient(MinMaxGradient source, float alpha, float brightness) { //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_0022: Expected I4, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) ParticleSystemGradientMode mode = ((MinMaxGradient)(ref source)).mode; switch ((int)mode) { case 0: return new MinMaxGradient(Scale(((MinMaxGradient)(ref source)).color, alpha, brightness)); case 2: return new MinMaxGradient(Scale(((MinMaxGradient)(ref source)).colorMin, alpha, brightness), Scale(((MinMaxGradient)(ref source)).colorMax, alpha, brightness)); case 1: case 4: { MinMaxGradient result = default(MinMaxGradient); ((MinMaxGradient)(ref result))..ctor(Scale(((MinMaxGradient)(ref source)).gradient, alpha, brightness)); ((MinMaxGradient)(ref result)).mode = ((MinMaxGradient)(ref source)).mode; return result; } case 3: return new MinMaxGradient(Scale(((MinMaxGradient)(ref source)).gradientMin, alpha, brightness), Scale(((MinMaxGradient)(ref source)).gradientMax, alpha, brightness)); default: return source; } } private static Color Scale(Color colour, float alpha, float brightness) { //IL_0000: 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_0010: 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_0020: Unknown result type (might be due to invalid IL or missing references) return new Color(colour.r * brightness, colour.g * brightness, colour.b * brightness, colour.a * alpha); } private static Gradient Scale(Gradient source, float alpha, float brightness) { //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: 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_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) if (source == null) { return null; } GradientColorKey[] colorKeys = source.colorKeys; GradientAlphaKey[] alphaKeys = source.alphaKeys; if (brightness < 1f) { for (int i = 0; i < colorKeys.Length; i++) { Color color = colorKeys[i].color; colorKeys[i].color = new Color(color.r * brightness, color.g * brightness, color.b * brightness, color.a); } } if (alpha < 1f) { for (int j = 0; j < alphaKeys.Length; j++) { alphaKeys[j].alpha *= alpha; } } Gradient val = new Gradient { mode = source.mode, colorSpace = source.colorSpace }; val.SetKeys(colorKeys, alphaKeys); return val; } private static MinMaxCurve ScaleCurve(MinMaxCurve curve, float multiplier) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) ((MinMaxCurve)(ref curve)).constantMin = ((MinMaxCurve)(ref curve)).constantMin * multiplier; ((MinMaxCurve)(ref curve)).constantMax = ((MinMaxCurve)(ref curve)).constantMax * multiplier; ((MinMaxCurve)(ref curve)).curveMultiplier = ((MinMaxCurve)(ref curve)).curveMultiplier * multiplier; return curve; } } internal static class ParticleProbe { private const int MaxLines = 60; private static int _used; public static bool Active { get { if (HitVfxSettings.LogDampenedEffects.Value) { return _used < 60; } return false; } } public static void Reset() { _used = 0; } public static void Report(GameObject root, ParticleSystem ps, MinMaxGradient beforeColour, MinMaxCurve beforeSize) { //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_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) if (_used < 60) { _used++; MainModule main = ps.main; ManualLogSource log = Plugin.Log; string[] obj = new string[10] { "[Probe] ", ((Object)root).name, "/", ((Object)ps).name, " ", $"colour(mode={((MinMaxGradient)(ref beforeColour)).mode} alpha {Alpha(beforeColour):0.00} -> {Alpha(((MainModule)(ref main)).startColor):0.00}) ", null, null, null, null }; object[] obj2 = new object[4] { ((MinMaxCurve)(ref beforeSize)).mode, ((MinMaxCurve)(ref beforeSize)).constantMax, null, null }; MinMaxCurve startSize = ((MainModule)(ref main)).startSize; obj2[2] = ((MinMaxCurve)(ref startSize)).constantMax; obj2[3] = ((MainModule)(ref main)).startSize3D; obj[6] = string.Format("size(mode={0} {1:0.000} -> {2:0.000} 3d={3}) ", obj2); obj[7] = $"playing={ps.isPlaying} emitted={ps.particleCount} "; obj[8] = "renderer="; obj[9] = RendererState(ps); log.LogInfo((object)string.Concat(obj)); if ((Object)(object)Plugin.Instance != (Object)null) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(Recheck(ps)); } } } private static IEnumerator Recheck(ParticleSystem ps) { yield return (object)new WaitForSeconds(0.3f); if (!((Object)(object)ps == (Object)null)) { MainModule main = ps.main; ManualLogSource log = Plugin.Log; string text = $"[Probe +0.3s] {((Object)ps).name} alpha={Alpha(((MainModule)(ref main)).startColor):0.00} "; MinMaxCurve startSize = ((MainModule)(ref main)).startSize; log.LogInfo((object)(text + $"size={((MinMaxCurve)(ref startSize)).constantMax:0.000} emitted={ps.particleCount}")); } } private static float Alpha(MinMaxGradient gradient) { //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_0022: Expected I4, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) ParticleSystemGradientMode mode = ((MinMaxGradient)(ref gradient)).mode; switch ((int)mode) { case 0: return ((MinMaxGradient)(ref gradient)).color.a; case 2: return ((MinMaxGradient)(ref gradient)).colorMax.a; case 1: case 4: return TopAlpha(((MinMaxGradient)(ref gradient)).gradient); case 3: return TopAlpha(((MinMaxGradient)(ref gradient)).gradientMax); default: return -1f; } } private static float TopAlpha(Gradient gradient) { if (gradient == null) { return -1f; } float num = 0f; GradientAlphaKey[] alphaKeys = gradient.alphaKeys; for (int i = 0; i < alphaKeys.Length; i++) { if (alphaKeys[i].alpha > num) { num = alphaKeys[i].alpha; } } return num; } private static string RendererState(ParticleSystem ps) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) ParticleSystemRenderer component = ((Component)ps).GetComponent<ParticleSystemRenderer>(); if ((Object)(object)component == (Object)null) { return "<none>"; } string arg = (((Object)(object)((Renderer)component).sharedMaterial != (Object)null && (Object)(object)((Renderer)component).sharedMaterial.shader != (Object)null) ? ((Object)((Renderer)component).sharedMaterial.shader).name : "<no material>"); return string.Format("{0}/{1}/{2}", ((Renderer)component).enabled ? "on" : "off", component.renderMode, arg); } } internal sealed class SyncedSetting<T> { private readonly ConfigEntry<T> _entry; private T _local; public ConfigEntry<T> Entry => _entry; public T Value { get { if (!HitVfxSettings.UseEntryValues) { return _local; } return _entry.Value; } } public SyncedSetting(ConfigEntry<T> entry) { _entry = entry; _local = entry.Value; } public void CaptureLocal() { _local = _entry.Value; } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }