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 LagFix v1.0.0
LagFix.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using RoR2; using RoR2.Orbs; using RoR2.Projectile; using UnityEngine; using UnityEngine.Networking; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyVersion("0.0.0.0")] namespace LagFix; [BepInPlugin("com.proigryfedorov.lagfix", "LagFix", "1.0.0")] public class LagFixPlugin : BaseUnityPlugin { private class ProjectileBudget { public float windowStart; public int fired; public float bankedDamage; } private class EffectBudget { public float windowStart; public int shown; } public const string PluginGuid = "com.proigryfedorov.lagfix"; public const string PluginName = "LagFix"; public const string PluginVersion = "1.0.0"; internal static LagFixPlugin Instance; internal static ConfigEntry<bool> FastLuck; internal static ConfigEntry<bool> MergeThornStacks; internal static ConfigEntry<int> ThornStackCap; internal static ConfigEntry<bool> MergeProjectiles; internal static ConfigEntry<int> ProjectilesPerSecond; internal static ConfigEntry<string> MergedProjectiles; internal static ConfigEntry<bool> ThrottleEffects; internal static ConfigEntry<int> EffectsPerSecond; internal static ConfigEntry<bool> InstantExperience; internal static ConfigEntry<bool> InstantGold; internal static ConfigEntry<bool> TameBlackHoles; internal static ConfigEntry<string> BlackHoleNames; internal static ConfigEntry<bool> LogEffectNames; private static readonly Dictionary<string, ProjectileBudget> budgets = new Dictionary<string, ProjectileBudget>(); private static string mergedListSource; private static string[] mergedList = new string[0]; private static readonly Dictionary<int, EffectBudget> effectBudgets = new Dictionary<int, EffectBudget>(); private void Awake() { //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Expected O, but got Unknown Instance = this; FastLuck = ((BaseUnityPlugin)this).Config.Bind<bool>("Items", "FastLuck", true, "57-листный клевер: считать удачу по формуле одним-двумя бросками вместо броска на каждую единицу удачи. Шансы те же."); MergeThornStacks = ((BaseUnityPlugin)this).Config.Bind<bool>("Items", "MergeThornStacks", true, "Вредный шип: объединять переносимые стаки урона (кровотечение, горение…) в меньшее число стаков с тем же общим уроном."); ThornStackCap = ((BaseUnityPlugin)this).Config.Bind<int>("Items", "ThornStackCap", 50, "Вредный шип: сколько стаков одного эффекта максимум переносится одному врагу. Урон с лишних добавляется к ним; у дебаффов без урона лишние отбрасываются."); MergeProjectiles = ((BaseUnityPlugin)this).Config.Bind<bool>("Items", "MergeProjectiles", true, "AtG, Церемониальный кинжал, Связка петард: если снарядов больше лимита в секунду, лишние не создаются, а их урон добавляется к следующему снаряду."); ProjectilesPerSecond = ((BaseUnityPlugin)this).Config.Bind<int>("Items", "ProjectilesPerSecond", 12, "Сколько таких снарядов в секунду может выпустить один игрок (на каждый вид снаряда)."); MergedProjectiles = ((BaseUnityPlugin)this).Config.Bind<string>("Items", "MergedProjectiles", "MissileProjectile,DaggerProjectile,FireworkProjectile", "Имена снарядов, которые объединяются (через запятую, достаточно части имени)."); ThrottleEffects = ((BaseUnityPlugin)this).Config.Bind<bool>("Effects", "ThrottleEffects", true, "Ограничивать число одинаковых визуальных эффектов в секунду (взрывы Бензина, молнии Укулеле и Полилютни, Огонёк, Руническая линза…). На урон не влияет."); EffectsPerSecond = ((BaseUnityPlugin)this).Config.Bind<int>("Effects", "EffectsPerSecond", 15, "Сколько одинаковых эффектов в секунду показывать."); InstantExperience = ((BaseUnityPlugin)this).Config.Bind<bool>("Effects", "InstantExperience", true, "Давать опыт сразу, без летящих шариков опыта (у хоста)."); InstantGold = ((BaseUnityPlugin)this).Config.Bind<bool>("Effects", "InstantGold", true, "Давать золото сразу, без летящих монеток (у хоста)."); TameBlackHoles = ((BaseUnityPlugin)this).Config.Bind<bool>("Effects", "TameBlackHoles", true, "«Чёрные дыры»: убирать слепящие вспышки, свет и искажение, оставляя кольцо и границу."); BlackHoleNames = ((BaseUnityPlugin)this).Config.Bind<string>("Effects", "BlackHoleNames", "ElementalRingVoidBlackHole,NullifierDeathBomb,VoidJailerDeathBomb,VoidMegaCrabDeathBomb,VoidDeathBomb,GravSphere", "Части имён объектов, считающихся «чёрными дырами» (через запятую)."); LogEffectNames = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "LogEffectNames", false, "Писать в лог имена появляющихся эффектов и снарядов — чтобы найти, какой эффект добавить в BlackHoleNames."); Harmony harmony = new Harmony("com.proigryfedorov.lagfix"); Patch(harmony, typeof(Util), "CheckRoll", new Type[3] { typeof(float), typeof(float), typeof(CharacterMaster) }, "CheckRollPrefix"); Patch(harmony, typeof(VineOrb), "OnArrival", Type.EmptyTypes, "VineOrbPrefix"); Patch(harmony, typeof(ProjectileManager), "FireProjectile", new Type[1] { typeof(FireProjectileInfo) }, "FireProjectilePrefix"); Patch(harmony, typeof(EffectManager), "SpawnEffect", new Type[3] { typeof(GameObject), typeof(EffectData), typeof(bool) }, "SpawnEffectPrefabPrefix"); Patch(harmony, typeof(EffectManager), "SpawnEffect", new Type[3] { typeof(EffectIndex), typeof(EffectData), typeof(bool) }, "SpawnEffectIndexPrefix"); Patch(harmony, typeof(ExperienceManager), "AwardExperience", null, "AwardExperiencePrefix"); Patch(harmony, typeof(OrbManager), "AddOrb", null, "AddOrbPrefix"); BlackHole.Patch(harmony); ((BaseUnityPlugin)this).Logger.LogInfo((object)"LagFix 1.0.0 loaded"); } private void Patch(Harmony harmony, Type type, string method, Type[] args, string prefix) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown try { harmony.Patch((MethodBase)AccessTools.Method(type, method, args, (Type[])null), new HarmonyMethod(typeof(LagFixPlugin), prefix, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Не удалось пропатчить " + type.Name + "." + method + ": " + ex.Message)); } } internal static void Log(string text) { if ((Object)(object)Instance != (Object)null) { ((BaseUnityPlugin)Instance).Logger.LogInfo((object)text); } } private static bool CheckRollPrefix(float percentChance, float luck, CharacterMaster effectOriginMaster, ref bool __result) { if (!FastLuck.Value) { return true; } if (percentChance <= 0f) { __result = false; return false; } int num = Mathf.CeilToInt(Mathf.Abs(luck)); float num2 = Random.Range(0f, 100f); if (num == 0 || luck == 0f) { __result = num2 < percentChance; return false; } double num3 = (double)Math.Min(percentChance, 100f) / 100.0; if (luck > 0f) { if (num2 < percentChance) { __result = true; return false; } double num4 = 1.0 - Math.Pow(1.0 - num3, num); __result = (double)Random.value < num4; if (__result) { MarkLucky(effectOriginMaster); } } else { __result = num2 < percentChance && (double)Random.value < Math.Pow(num3, num); } return false; } private static void MarkLucky(CharacterMaster master) { if (!((Object)(object)master == (Object)null)) { GameObject bodyObject = master.GetBodyObject(); CharacterBody val = (((Object)(object)bodyObject != (Object)null) ? bodyObject.GetComponent<CharacterBody>() : null); if ((Object)(object)val != (Object)null) { val.wasLucky = true; } } } private static void VineOrbPrefix(VineOrb __instance) { //IL_0066: 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_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_0101: 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_0108: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0175: 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) if (!MergeThornStacks.Value || __instance.splitDebuffInformation == null) { return; } int num = Math.Max(1, ThornStackCap.Value); HurtBox target = ((Orb)__instance).target; CharacterBody val = (((Object)(object)target != (Object)null && (Object)(object)target.healthComponent != (Object)null) ? target.healthComponent.body : null); bool flag = false; foreach (SplitDebuffInformation item in __instance.splitDebuffInformation) { flag |= item.count > num; } if (!flag) { return; } List<SplitDebuffInformation> list = (__instance.splitDebuffInformation = new List<SplitDebuffInformation>(__instance.splitDebuffInformation)); for (int i = 0; i < list.Count; i++) { SplitDebuffInformation value = list[i]; if (value.count <= num) { continue; } BuffDef buffDef = BuffCatalog.GetBuffDef(value.index); if ((Object)(object)buffDef != (Object)null && buffDef.isDOT && (Object)(object)val != (Object)null) { DotIndex dotDefIndex = DotController.GetDotDefIndex(buffDef); DotDef dotDef = DotController.GetDotDef(dotDefIndex); if (dotDef == null) { continue; } InflictDotInfo val2 = new InflictDotInfo { attackerObject = value.attacker, victimObject = ((Component)val).gameObject, dotIndex = dotDefIndex, duration = ((value.duration == 0f) ? dotDef.interval : value.duration), hitHurtBox = target, procChainMask = value.procChainMask, damageMultiplier = (float)value.count / (float)num }; for (int j = 0; j < num; j++) { DotController.InflictDot(ref val2); } value.count = 0; } else { value.count = num; } list[i] = value; } } private static bool IsMerged(string prefabName) { if (mergedListSource != MergedProjectiles.Value) { mergedListSource = MergedProjectiles.Value; mergedList = SplitNames(mergedListSource); } string[] array = mergedList; foreach (string value in array) { if (prefabName.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0) { return true; } } return false; } internal static string[] SplitNames(string text) { List<string> list = new List<string>(); string[] array = (text ?? "").Split(','); foreach (string text2 in array) { string text3 = text2.Trim(); if (text3.Length > 0) { list.Add(text3); } } return list.ToArray(); } private static bool FireProjectilePrefix(ref FireProjectileInfo fireProjectileInfo) { GameObject projectilePrefab = fireProjectileInfo.projectilePrefab; if (LogEffectNames.Value && (Object)(object)projectilePrefab != (Object)null) { Log("Снаряд: " + ((Object)projectilePrefab).name); } if (!MergeProjectiles.Value || !NetworkServer.active || (Object)(object)projectilePrefab == (Object)null || (Object)(object)fireProjectileInfo.owner == (Object)null) { return true; } if (!IsMerged(((Object)projectilePrefab).name)) { return true; } string key = ((Object)fireProjectileInfo.owner).GetInstanceID() + "/" + ((Object)projectilePrefab).name; if (!budgets.TryGetValue(key, out var value)) { value = new ProjectileBudget(); budgets[key] = value; } float time = Time.time; if (time - value.windowStart >= 1f) { value.windowStart = time; value.fired = 0; } if (value.fired >= Math.Max(1, ProjectilesPerSecond.Value)) { value.bankedDamage += fireProjectileInfo.damage; return false; } value.fired++; fireProjectileInfo.damage += value.bankedDamage; value.bankedDamage = 0f; return true; } private static bool AllowEffect(int key, string name) { if (LogEffectNames.Value && name != null) { Log("Эффект: " + name); } if (!ThrottleEffects.Value) { return true; } if (!effectBudgets.TryGetValue(key, out var value)) { value = new EffectBudget(); effectBudgets[key] = value; } float unscaledTime = Time.unscaledTime; if (unscaledTime - value.windowStart >= 1f) { value.windowStart = unscaledTime; value.shown = 0; } if (value.shown >= Math.Max(1, EffectsPerSecond.Value)) { return false; } value.shown++; return true; } private static bool SpawnEffectPrefabPrefix(GameObject effectPrefab) { if ((Object)(object)effectPrefab == (Object)null) { return true; } return AllowEffect(((Object)effectPrefab).GetInstanceID(), ((Object)effectPrefab).name); } private static bool SpawnEffectIndexPrefix(EffectIndex effectIndex) { //IL_0000: 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_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected I4, but got Unknown EffectDef effectDef = EffectCatalog.GetEffectDef(effectIndex); return AllowEffect(int.MinValue + effectIndex, (effectDef != null && (Object)(object)effectDef.prefab != (Object)null) ? ((Object)effectDef.prefab).name : null); } private static bool AwardExperiencePrefix(CharacterBody body, ulong amount) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) if (!InstantExperience.Value || !NetworkServer.active || (Object)(object)TeamManager.instance == (Object)null) { return true; } if (SuppressExperience.suppressExperience || (Object)(object)body == (Object)null || (Object)(object)body.master == (Object)null) { return false; } TeamManager.instance.GiveTeamExperience(body.master.teamIndex, amount); return false; } private static bool AddOrbPrefix(Orb orb) { if (!InstantGold.Value || !NetworkServer.active) { return true; } GoldOrb val = (GoldOrb)(object)((orb is GoldOrb) ? orb : null); if (val == null) { return true; } ((Orb)val).OnArrival(); return false; } } internal static class BlackHole { public const string DefaultNames = "ElementalRingVoidBlackHole,NullifierDeathBomb,VoidJailerDeathBomb,VoidMegaCrabDeathBomb,VoidDeathBomb,GravSphere"; private static string namesSource; private static string[] names = new string[0]; private static readonly string[] BlindingMaterialWords = new string[3] { "distort", "flash", "screen" }; public static void Patch(Harmony harmony) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown HarmonyMethod val = new HarmonyMethod(typeof(BlackHole), "SpawnedPostfix", (Type[])null); harmony.Patch((MethodBase)AccessTools.Method(typeof(EffectComponent), "Start", (Type[])null, (Type[])null), (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(ProjectileGhostController), "Awake", (Type[])null, (Type[])null), (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(ProjectileController), "Start", (Type[])null, (Type[])null), (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } private static void SpawnedPostfix(MonoBehaviour __instance) { if (LagFixPlugin.TameBlackHoles.Value && !((Object)(object)__instance == (Object)null)) { GameObject gameObject = ((Component)__instance).gameObject; if (Matches(((Object)gameObject).name)) { Tame(gameObject); } } } private static bool Matches(string objectName) { if (namesSource != LagFixPlugin.BlackHoleNames.Value) { namesSource = LagFixPlugin.BlackHoleNames.Value; names = LagFixPlugin.SplitNames(namesSource); } string[] array = names; foreach (string value in array) { if (objectName.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0) { return true; } } return false; } private static void Tame(GameObject go) { Light[] componentsInChildren = go.GetComponentsInChildren<Light>(true); foreach (Light val in componentsInChildren) { ((Behaviour)val).enabled = false; } Behaviour[] componentsInChildren2 = go.GetComponentsInChildren<Behaviour>(true); foreach (Behaviour val2 in componentsInChildren2) { string name = ((object)val2).GetType().Name; if (name == "PostProcessVolume" || name == "PostProcessDuration") { val2.enabled = false; } } Renderer[] componentsInChildren3 = go.GetComponentsInChildren<Renderer>(true); foreach (Renderer val3 in componentsInChildren3) { Material sharedMaterial = val3.sharedMaterial; if ((Object)(object)sharedMaterial == (Object)null) { continue; } string text = (((Object)sharedMaterial).name + " " + (((Object)(object)sharedMaterial.shader != (Object)null) ? ((Object)sharedMaterial.shader).name : "")).ToLowerInvariant(); string[] blindingMaterialWords = BlindingMaterialWords; foreach (string value in blindingMaterialWords) { if (text.Contains(value)) { val3.enabled = false; break; } } } } }