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 EpicLootAdjustments v1.5.6
Cjayride.EpicLootAdjustments.dll
Decompiled 3 days agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; 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 HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")] [assembly: AssemblyCompany("Cjayride.EpicLootAdjustments")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.5.6.0")] [assembly: AssemblyInformationalVersion("1.5.6+c87fcaf2e698b4fe7a60025a938ca50543ea54a3")] [assembly: AssemblyProduct("Cjayride.EpicLootAdjustments")] [assembly: AssemblyTitle("Cjayride.EpicLootAdjustments")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.5.6.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 Cjayride.EpicLootAdjustments { public static class ConfigButtonHide { private static readonly string[] BrokerTypeNames = new string[3] { "Common.QuickConfigBroker", "EpicLoot.QuickConfigBroker", "EpicLoot.Common.QuickConfigBroker" }; private static Type _brokerType; private static FieldInfo _instanceField; private static FieldInfo _pauseButtonField; private static FieldInfo _mainMenuButtonField; private static FieldInfo _listPanelField; private static bool _quickConfigAvailable; public static ConfigEntry<bool> HideButton; public static void Bind(ConfigFile config) { HideButton = config.Bind<bool>("Interface", "HideEpicLootConfigButton", true, "Hide the Epic Loot / Mod Config button on the main menu and pause screen. The BepInEx config files still work."); } public static void TryPatch(Harmony harmony) { //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Expected O, but got Unknown //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Expected O, but got Unknown _brokerType = ResolveBrokerType(); if (_brokerType == null) { Plugin.Log.LogInfo((object)"EpicLoot Quick Config button was not found. Config button hide is skipped (no Menu.Update work)."); return; } _instanceField = _brokerType.GetField("Instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); _pauseButtonField = _brokerType.GetField("pauseButton", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _mainMenuButtonField = _brokerType.GetField("mainMenuButton", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _listPanelField = _brokerType.GetField("listPanel", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _quickConfigAvailable = true; PatchPrefix(harmony, _brokerType, "TryBuildButtons", "SkipIfHidden"); PatchPrefix(harmony, _brokerType, "EnsurePauseButton", "SkipIfHidden"); PatchPrefix(harmony, _brokerType, "OnMenuStart", "SkipIfHidden"); MethodInfo methodInfo = FindMethod(_brokerType, "RefreshVisibility"); if (methodInfo != null) { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(ConfigButtonHide), "HideBrokerButtons", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } MethodInfo methodInfo2 = AccessTools.Method(typeof(Menu), "Show", (Type[])null, (Type[])null); if (methodInfo2 != null) { harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(ConfigButtonHide), "HideBrokerButtons", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } Plugin.Log.LogInfo((object)(HideButton.Value ? "EpicLoot pause-screen config button is hidden." : "EpicLoot pause-screen config button is visible.")); } public static bool SkipIfHidden() { if (HideButton != null) { return !HideButton.Value; } return true; } public static void HideBrokerButtons() { if (_quickConfigAvailable && HideButton != null && HideButton.Value) { object obj = _instanceField?.GetValue(null); if (obj != null) { HideField(_pauseButtonField, obj); HideField(_mainMenuButtonField, obj); HideField(_listPanelField, obj); } } } private static Type ResolveBrokerType() { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); string[] brokerTypeNames = BrokerTypeNames; foreach (string name in brokerTypeNames) { Assembly[] array = assemblies; for (int j = 0; j < array.Length; j++) { Type type = array[j].GetType(name, throwOnError: false); if (type != null) { return type; } } } return null; } private static void HideField(FieldInfo field, object instance) { object? obj = field?.GetValue(instance); GameObject val = (GameObject)((obj is GameObject) ? obj : null); if ((Object)(object)val != (Object)null && val.activeSelf) { val.SetActive(false); } } private static void PatchPrefix(Harmony harmony, Type type, string methodName, string prefix) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown MethodInfo methodInfo = FindMethod(type, methodName); if (!(methodInfo == null)) { harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(ConfigButtonHide), prefix, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } private static MethodInfo FindMethod(Type type, string methodName) { MethodInfo[] methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name == methodName) { return methodInfo; } } return null; } } public static class DropThatAllowList { private static readonly Dictionary<string, HashSet<string>> Allowed = new Dictionary<string, HashSet<string>>(StringComparer.OrdinalIgnoreCase); private static ConfigEntry<string> FileNames; private static bool _loaded; public static void Bind(ConfigFile config) { FileNames = config.Bind<string>("Exceptions", "DropThatAllowFiles", "drop_that.character_drop.BossBonusTools.cfg", "Comma-separated Drop That character-drop files in BepInEx/config. Items listed on a creature in these files are not downgraded, even if they are above that creature's zone."); } public static bool IsAllowed(string creature, string item) { EnsureLoaded(); creature = LootMappings.Clean(creature); item = LootMappings.Clean(item); if (string.IsNullOrEmpty(creature) || string.IsNullOrEmpty(item)) { return false; } if (Allowed.TryGetValue(creature, out var value)) { return value.Contains(item); } return false; } private static void EnsureLoaded() { if (_loaded) { return; } _loaded = true; Allowed.Clear(); string configPath = Paths.ConfigPath; if (string.IsNullOrEmpty(configPath) || !Directory.Exists(configPath)) { return; } string[] array = ((FileNames != null) ? FileNames.Value : "drop_that.character_drop.BossBonusTools.cfg").Split(new char[2] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries); int num = 0; for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length != 0) { string text2 = Path.Combine(configPath, text); if (!File.Exists(text2)) { Plugin.Log.LogInfo((object)("Drop That allow-list file not found: " + text2)); } else { num += LoadFile(text2); } } } Plugin.Log.LogInfo((object)("Drop That allow-list loaded " + num + " creature/item pairs.")); } private static int LoadFile(string path) { int num = 0; string creature = null; string prefab = null; bool enabled = true; string[] array = File.ReadAllLines(path); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length == 0 || text[0] == '#') { continue; } if (text[0] == '[') { num += Commit(creature, prefab, enabled); creature = ParseCreature(text); prefab = null; enabled = true; continue; } int num2 = text.IndexOf('='); if (num2 > 0) { string text2 = text.Substring(0, num2).Trim(); string text3 = text.Substring(num2 + 1).Trim(); if (text2.Equals("PrefabName", StringComparison.OrdinalIgnoreCase)) { prefab = text3; } else if (text2.Equals("EnableConfig", StringComparison.OrdinalIgnoreCase)) { enabled = !text3.Equals("false", StringComparison.OrdinalIgnoreCase); } } } return num + Commit(creature, prefab, enabled); } private static int Commit(string creature, string prefab, bool enabled) { if (!enabled || string.IsNullOrEmpty(creature) || string.IsNullOrEmpty(prefab)) { return 0; } if (!Allowed.TryGetValue(creature, out var value)) { value = new HashSet<string>(StringComparer.OrdinalIgnoreCase); Allowed.Add(creature, value); } return value.Add(prefab) ? 1 : 0; } private static string ParseCreature(string section) { int num = section.IndexOf('[') + 1; int num2 = section.IndexOf(']'); if (num <= 0 || num2 <= num) { return null; } string text = section.Substring(num, num2 - num); int num3 = text.IndexOf('.'); if (num3 > 0) { text = text.Substring(0, num3); } return text.Trim(); } } public static class ItemTierIndex { private class ItemRecord { public string Name; public int Tier; public ItemType Type; } private static readonly Dictionary<string, ItemRecord> ByName = new Dictionary<string, ItemRecord>(); private static readonly Dictionary<string, List<Recipe>> Recipes = new Dictionary<string, List<Recipe>>(); private static readonly Dictionary<string, int> TierCache = new Dictionary<string, int>(); private static readonly HashSet<string> Visiting = new HashSet<string>(); private static bool _ready; public static void Invalidate() { _ready = false; } public static bool ShouldRemove(string itemName, int maxTier) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) itemName = LootMappings.Clean(itemName); if (string.IsNullOrEmpty(itemName) || LootMappings.IsShardStone(itemName)) { return false; } EnsureBuilt(); ItemRecord itemRecord = Find(itemName); if (itemRecord == null || !IsGear(itemRecord.Type)) { return false; } return itemRecord.Tier > maxTier; } private static bool IsGear(ItemType type) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected I4, but got Unknown switch (type - 3) { case 0: case 1: case 2: case 3: case 4: case 6: case 8: case 11: case 12: case 14: case 15: case 16: case 17: case 19: case 20: return true; default: return false; } } private static ItemRecord Find(string itemName) { if (ByName.TryGetValue(itemName, out var value)) { return value; } ObjectDB instance = ObjectDB.instance; GameObject val = ((instance != null) ? instance.GetItemPrefab(itemName) : null); if ((Object)(object)val == (Object)null) { return null; } return AddPrefab(val); } private static bool EnsureBuilt() { if (_ready) { return true; } ObjectDB instance = ObjectDB.instance; if ((Object)(object)instance == (Object)null || instance.m_items == null || instance.m_items.Count == 0) { return false; } try { Build(instance); _ready = true; Plugin.Log.LogInfo((object)("Indexed " + ByName.Count + " items for zone checks.")); return true; } catch (Exception ex) { _ready = true; Plugin.Log.LogError((object)("Failed to index item tiers: " + ex)); return false; } } private static void Build(ObjectDB db) { ByName.Clear(); Recipes.Clear(); TierCache.Clear(); Visiting.Clear(); if (db.m_recipes != null) { for (int i = 0; i < db.m_recipes.Count; i++) { Recipe val = db.m_recipes[i]; if ((Object)(object)val?.m_item == (Object)null) { continue; } string text = LootMappings.Clean(((Object)val.m_item).name); if (!string.IsNullOrEmpty(text)) { if (!Recipes.TryGetValue(text, out var value)) { value = new List<Recipe>(); Recipes.Add(text, value); } value.Add(val); } } } for (int j = 0; j < db.m_items.Count; j++) { AddPrefab(db.m_items[j]); } } private static ItemRecord AddPrefab(GameObject prefab) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)prefab == (Object)null) { return null; } ItemDrop component = prefab.GetComponent<ItemDrop>(); if (component?.m_itemData?.m_shared == null) { return null; } string text = LootMappings.Clean(((Object)prefab).name); if (string.IsNullOrEmpty(text)) { return null; } if (ByName.TryGetValue(text, out var value)) { return value; } SharedData shared = component.m_itemData.m_shared; ItemRecord itemRecord = new ItemRecord { Name = text, Type = shared.m_itemType, Tier = ComputeTier(text) }; ByName.Add(text, itemRecord); return itemRecord; } private static int ComputeTier(string name) { if (TierCache.TryGetValue(name, out var value)) { return value; } if (!Visiting.Add(name)) { return LootMappings.MaterialTier(name); } int num = LootMappings.MaterialTier(name); if (Recipes.TryGetValue(name, out var value2)) { for (int i = 0; i < value2.Count; i++) { Requirement[] resources = value2[i].m_resources; if (resources == null) { continue; } for (int j = 0; j < resources.Length; j++) { ItemDrop val = resources[j]?.m_resItem; if ((Object)(object)val == (Object)null) { continue; } string text = LootMappings.Clean(((Object)val).name); if (!string.IsNullOrEmpty(text) && !(text == name)) { int num2 = ComputeTier(text); if (num2 > num) { num = num2; } } } } } Visiting.Remove(name); TierCache[name] = num; return num; } } public static class LootMappings { public const int MeadowsTier = 1; public const int BlackForestTier = 2; public const int SwampTier = 3; public const int MountainTier = 4; public const int PlainsTier = 5; public const int MistlandsTier = 6; public const int AshlandsTier = 7; public const int DeepNorthTier = 8; public static readonly Dictionary<string, int> ZoneTiers; public static readonly Dictionary<string, string> CreatureZones; public static readonly Dictionary<string, int> Materials; private static readonly List<KeyValuePair<string, int>> Tokens; static LootMappings() { ZoneTiers = new Dictionary<string, int> { { "Meadows", 1 }, { "Black Forest", 2 }, { "Swamp", 3 }, { "Mountain", 4 }, { "Ocean", 4 }, { "Plains", 5 }, { "Mistlands", 6 }, { "Ashlands", 7 }, { "Deep North", 8 } }; CreatureZones = new Dictionary<string, string>(); Materials = new Dictionary<string, int>(); Tokens = new List<KeyValuePair<string, int>>(); AddMaterials(1, "Wood", "Stone", "Flint", "Resin", "LeatherScraps", "DeerHide", "HardAntler", "Coal", "Feathers"); AddMaterials(2, "Copper", "CopperOre", "Tin", "TinOre", "Bronze", "BronzeNails", "RoundLog", "FineWood", "CoreWood", "TrollHide", "BjornHide", "BjornPaw", "GreydwarfEye", "BoneFragments", "SurtlingCore"); AddMaterials(3, "Iron", "IronScrap", "IronOre", "IronNails", "Chain", "ElderBark", "Guck", "Ooze", "Root", "Bloodbag", "Entrails", "WitheredBone", "Turnip", "WrithanRoots", "Sausages", "Sausage", "TurnipStew", "BlackSoup"); AddMaterials(4, "Silver", "SilverOre", "Obsidian", "WolfHairBundle", "WolfPelt", "WolfClaw", "WolfFang", "FreezeGland", "Chitin", "SerpentScale", "SerpentMeat"); AddMaterials(5, "Needle", "BlackMetal", "BlackMetalScrap", "LinenThread", "Linen", "LoxPelt", "Barley", "BarleyFlour", "Flax", "Tar", "Cloudberry", "UndeadBjornRibcage"); AddMaterials(6, "YggdrasilWood", "BlackMarble", "Eitr", "RefinedEitr", "BlackCore", "Mandible", "Carapace", "ScaleHide", "Sap", "Softtissue", "Magecap", "RoyalJelly", "Bilebag", "JuteRed", "Wisp", "YagluthDrop"); AddMaterials(7, "Flametal", "FlametalNew", "FlametalOre", "FlametalOreNew", "Blackwood", "CharredBone", "MoltenCore", "GemstoneBlue", "GemstoneGreen", "GemstoneRed", "CelestialFeather", "AskHide", "AsksvinHide", "AsksvinBladder", "Grausten", "CeramicPlate", "ProustitePowder", "MorgenHeart", "MorgenSinew", "Fiddlehead", "VoltureEgg", "Sulfur"); AddMaterials(8, "Gold", "GoldOre", "Frostwood", "FrostCore", "Ice", "FrozenFuel", "MooseHide", "MooseSinew", "MooseMeat", "SealHide", "SealBlubber", "ElakingHairBundle", "NornThread", "Leatherstraps", "MoleClaws", "BarkaBranch", "OozeMork", "OrbFrostFire", "OrbThunderBlood", "AncientCoin", "AncientGemstoneBlack", "AncientGemstoneGreen", "AncientGemstoneOrange", "AncientGemstonePurple", "MemorialCoal", "HatefulBlood", "CrownJewel", "FrozenKingDrop", "Lingonberry", "GlowWorm", "Kale", "KaleSeeds", "Oat", "OatSeeds", "Poteitr", "PoteitrSeeds", "FirConeFrost"); AddCreatures("Meadows", "Boar", "Boar_piggy", "Chicken", "Deer", "Greyling", "Hen", "MeadowsSpider", "Neck", "Rainbow_Butterfly", "Eikthyr", "Golden_Greydwarf_Miniboss", "GoldenEikthyr"); AddCreatures("Black Forest", "Bjorn", "BlackForestSpider", "ForestSpider", "Green_Butterfly", "Greydwarf", "Greydwarf_Elite", "Greydwarf_Purple", "Greydwarf_Purple_Shroom", "Greydwarf_Shaman", "JumpingSpider", "LandMolluscan", "Molluscan", "NormalSkeletonWarrior", "Skeleton", "SkeletonWarrior", "Skeleton_NoArcher", "TreeSpider", "Troll", "gd_king", "Skeleton_Hildir", "Golden_Troll_Miniboss", "GoldenTheElder"); AddCreatures("Swamp", "Abomination", "Blob", "BlobElite", "BogWitchKvastur", "Draugr", "DraugrShip", "Draugr_Elite", "Draugr_Ranged", "Ghost", "GreenSpider", "Leech", "Leech_Calf", "Leech_cave", "LurkingSpiderSwamp", "ML_DraugrShip", "RancidRemains", "Skeleton_Poison", "Surtling", "Wraith", "Writhan", "Bonemass", "Golden_Wraith_Miniboss", "DraugrMariner", "GoldenBonemass"); AddCreatures("Mountain", "Bat", "Drake", "Fenring", "Fenring_Cultist", "GhostWarrior", "Hatchling", "SnowSpider", "StoneGolem", "Ulv", "Wolf", "Wolf_cub", "Dragon", "Ulv_Hildir", "FrostwingFae", "GoldenModer"); AddCreatures("Plains", "BlobTar", "BrownSpider", "Deathsquito", "DwarfGoblin", "DwarfGoblinLoot", "DwarfGoblinShaman", "FulingShip", "Goblin", "GoblinArcher", "GoblinBase", "GoblinBrute", "GoblinBruteBros", "GoblinBruteBros_nochest", "GoblinLoot", "GoblinLox", "GoblinShaman", "GoblinShamanNew", "Goblin_Gem", "Lox", "LoxCalf", "Unbjorn", "GoblinKing", "GoblinBrute_Hildir", "GoldenYagluth"); AddCreatures("Mistlands", "Dverger", "DvergerMage", "DvergerMageFire", "DvergerMageIce", "DvergerMageSupport", "Hare", "PulpHexahedric", "PulpShapeless", "PulpTiny", "Seeker", "SeekerBrood", "SeekerBrute", "Silkworm_Butterfly", "Spiderling", "Tick", "SeekerQueen", "SvartalfarQueen"); AddCreatures("Ashlands", "AshHatchling", "AshHuldra", "AshHuldraQueen", "Asksvin", "Asksvin_hatchling", "BlobLava", "Bonemaw", "BonemawSerpent", "ChaosSkeletonWarrior", "CharredMelee_Reto", "Charred_Archer", "Charred_Archer_Fader", "Charred_Mage", "Charred_Melee", "Charred_Melee_Dyrnwyn", "Charred_Melee_Fader", "Charred_Twitcher", "Charred_Twitcher_Summoned", "DamnedOne_TW", "DvergerAshlands", "FallenValkyrie", "FireGolem", "FireSkeletonWarrior", "InfernalMinotaur", "ML_AshHatchling", "ML_AshHuldra", "MagmaSkarab", "Morgen", "Morgen_NonSleeping", "ObsidianGolem", "SkeletonWarriorFire", "Volture", "Fader", "HelDemon"); AddCreatures("Deep North", "Barka", "BlobFrost", "CrystalhideUrsar", "CrystalhideUrsar_Cub", "Elaking", "EyelessOne", "FallenWarrior", "FrigidSpider", "FrostSpider", "Frostling", "Gammeltroll", "Hexen", "IceGolem", "IceSkeletonWarrior", "IceSkeletonWarriorT6", "Krigen", "Moose", "SkeletonWarriorIce", "KallFimbulbringer", "Jotunn"); AddCreatures("Ocean", "CommonJellyfish", "DeepSeaMolluscan", "DeepSeaSerpent", "DeepSea_Serpent", "Kraken", "KrakenLD", "ML_DeepSeaMolluscan", "ML_JellyFish0", "Seal", "Serpent"); AddTokens(8, "DeepNorth", "Frostwood", "FrostCore", "NornThread"); AddTokens(7, "Flametal", "Blackwood", "CharredBone", "MoltenCore", "Asksvin", "Grausten", "Dyrnwyn", "Niedhogg", "Berzerkr"); AddTokens(6, "Yggdrasil", "BlackMarble", "Carapace", "ScaleHide", "Mistwalker", "JotunBane", "Himminafl", "HimminAfl"); AddTokens(5, "BlackMetal", "Blackmetal", "LinenThread"); AddTokens(4, "SerpentScale", "FreezeGland", "WolfPelt", "Obsidian"); AddTokens(3, "ElderBark", "WitheredBone", "IronScrap", "Sausage"); AddTokens(2, "FineWood", "CoreWood", "TrollHide", "Bronze"); AddTokens(4, "Silver"); AddTokens(5, "BlackMetal", "Blackmetal"); AddTokens(7, "Flametal"); AddTokens(8, "Gold"); foreach (KeyValuePair<string, string> creatureZone in CreatureZones) { if (ZoneTiers.TryGetValue(creatureZone.Value, out var value)) { Materials[creatureZone.Key] = value; Materials["Trophy" + creatureZone.Key] = value; } } } public static bool TryGetCreature(string prefabName, out string creature, out string zone, out int tier) { creature = Clean(prefabName); zone = null; tier = 0; if (string.IsNullOrEmpty(creature)) { return false; } if (!CreatureZones.TryGetValue(creature, out zone)) { return false; } return ZoneTiers.TryGetValue(zone, out tier); } public static bool IsShardStone(string prefabName) { if (!string.IsNullOrEmpty(prefabName)) { return prefabName.IndexOf("ShardStone", StringComparison.OrdinalIgnoreCase) >= 0; } return false; } public static int MaterialTier(string prefabName) { if (string.IsNullOrEmpty(prefabName)) { return 0; } int num = ShardStoneTier(prefabName); if (num > 0) { return num; } int num2 = 0; if (Materials.TryGetValue(prefabName, out var value) && value > num2) { num2 = value; } int num3 = SegmentTier(prefabName); if (num3 > num2) { num2 = num3; } int num4 = TokenTier(prefabName); if (num4 > num2) { num2 = num4; } return num2; } public static string[] FallbackMaterials(int tier) { return tier switch { 1 => new string[2] { "Wood", "Flint" }, 2 => new string[2] { "Bronze", "FineWood" }, 3 => new string[2] { "Iron", "ElderBark" }, 4 => new string[2] { "Silver", "Obsidian" }, 5 => new string[2] { "BlackMetal", "Needle" }, 6 => new string[3] { "Eitr", "Carapace", "YggdrasilWood" }, 7 => new string[3] { "FlametalNew", "Flametal", "Blackwood" }, 8 => new string[3] { "Gold", "GoldOre", "Frostwood" }, _ => new string[1] { "Wood" }, }; } public static string[] FallbackFood(int tier) { return tier switch { 1 => new string[4] { "CookedMeat", "GrilledNeckTail", "Honey", "Raspberry" }, 2 => new string[3] { "CarrotSoup", "MincedMeatSauce", "CookedDeerMeat" }, 3 => new string[3] { "Sausages", "TurnipStew", "BlackSoup" }, 4 => new string[3] { "WolfMeat", "OnionSoup", "CookedWolfMeat" }, 5 => new string[3] { "LoxPie", "BloodPudding", "Bread" }, 6 => new string[3] { "MisthareSupreme", "MushroomOmelette", "Salad" }, 7 => new string[3] { "CookedAsksvinMeat", "FiddleheadFern", "PiquantPie" }, 8 => new string[2] { "CookedMooseMeat", "Lingonberry" }, _ => new string[1] { "CookedMeat" }, }; } public static string[] FallbackTrophies(int tier) { return tier switch { 1 => new string[4] { "TrophyBoar", "TrophyDeer", "TrophyNeck", "TrophyEikthyr" }, 2 => new string[5] { "TrophyGreydwarf", "TrophySkeleton", "TrophyTroll", "TrophyTheElder", "Trophygd_king" }, 3 => new string[4] { "TrophyDraugr", "TrophyLeech", "TrophyBlob", "TrophyBonemass" }, 4 => new string[4] { "TrophyWolf", "TrophyHatchling", "TrophySGolem", "TrophyDragonQueen" }, 5 => new string[4] { "TrophyGoblin", "TrophyLox", "TrophyGrowth", "TrophyGoblinKing" }, 6 => new string[4] { "TrophySeeker", "TrophySeekerBrute", "TrophyDvergr", "TrophySeekerQueen" }, 7 => new string[3] { "TrophyCharredMelee", "TrophyAsksvin", "TrophyFader" }, 8 => new string[3] { "TrophyMoose", "TrophySeal", "TrophyElaking" }, _ => new string[1] { "TrophyBoar" }, }; } public static string Clean(string name) { if (string.IsNullOrEmpty(name)) { return name; } int num = name.IndexOf("(Clone)", StringComparison.Ordinal); if (num >= 0) { name = name.Remove(num); } return name.Trim(); } private static void AddMaterials(int tier, params string[] names) { for (int i = 0; i < names.Length; i++) { Materials[names[i]] = tier; } } private static void AddCreatures(string zone, params string[] names) { for (int i = 0; i < names.Length; i++) { if (CreatureZones.ContainsKey(names[i])) { throw new InvalidOperationException("Duplicate creature mapping: " + names[i]); } CreatureZones.Add(names[i], zone); } } private static int ShardStoneTier(string name) { if (!IsShardStone(name)) { return 0; } if (name.IndexOf("_Ancient_", StringComparison.OrdinalIgnoreCase) >= 0 || name.EndsWith("_Ancient_ShardStone", StringComparison.OrdinalIgnoreCase) || name.IndexOf("Ancient_ShardStone", StringComparison.OrdinalIgnoreCase) >= 0) { return 8; } if (name.IndexOf("_Mythic_", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("Mythic_ShardStone", StringComparison.OrdinalIgnoreCase) >= 0) { return 6; } if (name.IndexOf("_Legendary_", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("Legendary_ShardStone", StringComparison.OrdinalIgnoreCase) >= 0) { return 4; } if (name.IndexOf("_Epic_", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("Epic_ShardStone", StringComparison.OrdinalIgnoreCase) >= 0) { return 3; } if (name.IndexOf("_Rare_", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("Rare_ShardStone", StringComparison.OrdinalIgnoreCase) >= 0) { return 2; } if (name.IndexOf("_Magic_", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("Magic_ShardStone", StringComparison.OrdinalIgnoreCase) >= 0) { return 1; } return 8; } private static int SegmentTier(string name) { int num = 0; int num2 = 0; for (int i = 0; i <= name.Length; i++) { bool flag = i == name.Length; bool flag2 = !flag && i > num2 && char.IsUpper(name[i]) && char.IsLower(name[i - 1]); bool flag3 = flag || !char.IsLetter(name[i]); if (flag2 || flag3) { if (i > num2 && Materials.TryGetValue(name.Substring(num2, i - num2), out var value) && value > num) { num = value; } num2 = (flag2 ? i : (i + 1)); } } return num; } private static void AddTokens(int tier, params string[] names) { for (int i = 0; i < names.Length; i++) { Tokens.Add(new KeyValuePair<string, int>(names[i], tier)); } } private static int TokenTier(string name) { int num = 0; for (int i = 0; i < Tokens.Count; i++) { if (Tokens[i].Value > num && name.IndexOf(Tokens[i].Key, StringComparison.Ordinal) >= 0) { num = Tokens[i].Value; } } return num; } } public static class OutdatedConfigHide { private const string VersionManagerTypeName = "EpicLoot.Config.ConfigVersionManager"; private const string UpdatePromptTypeName = "EpicLoot.ConfigUpdatePrompt"; private static MethodInfo _declineOutdated; private static PropertyInfo _hasOutdatedConfigs; private static bool _declinedOnce; public static ConfigEntry<bool> HideOutdatedConfigPrompt; public static void Bind(ConfigFile config) { HideOutdatedConfigPrompt = config.Bind<bool>("Interface", "HideEpicLootOutdatedConfigPrompt", true, "Hide Epic Loot's main-menu \"Outdated Configs\" update prompt. Modpack JSON is left unchanged; declining is recorded so Epic Loot does not ask again until those files change in a future Epic Loot update."); } public static void TryPatch(Harmony harmony) { //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Expected O, but got Unknown Type type = AccessTools.TypeByName("EpicLoot.ConfigUpdatePrompt"); if (type == null) { Plugin.Log.LogInfo((object)"EpicLoot ConfigUpdatePrompt was not found. Outdated config prompt hide is skipped."); return; } Type type2 = AccessTools.TypeByName("EpicLoot.Config.ConfigVersionManager"); if (type2 != null) { _declineOutdated = AccessTools.Method(type2, "DeclineOutdatedConfigs", (Type[])null, (Type[])null); _hasOutdatedConfigs = AccessTools.Property(type2, "HasOutdatedConfigs"); MethodInfo methodInfo = AccessTools.Method(type2, "RefreshUnmodifiedConfigs", (Type[])null, (Type[])null); if (methodInfo != null) { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(OutdatedConfigHide), "AfterConfigVersionRefresh", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } PatchPrefixReturnFalse(harmony, type, "ShouldPrompt", "BlockPrompt"); PatchPrefixReturnFalse(harmony, type, "TryOpen", "BlockPrompt"); PatchPrefixReturnFalse(harmony, type, "ShowConfigMessage", "BlockShowMessage"); Plugin.Log.LogInfo((object)(HideOutdatedConfigPrompt.Value ? "EpicLoot outdated config prompt is hidden." : "EpicLoot outdated config prompt is visible.")); } public static void AfterConfigVersionRefresh() { TryDeclineOutdatedConfigs(); } public static bool BlockPrompt(ref bool __result) { if (HideOutdatedConfigPrompt == null || !HideOutdatedConfigPrompt.Value) { return true; } TryDeclineOutdatedConfigs(); __result = false; return false; } public static bool BlockShowMessage() { if (HideOutdatedConfigPrompt == null || !HideOutdatedConfigPrompt.Value) { return true; } TryDeclineOutdatedConfigs(); return false; } private static void TryDeclineOutdatedConfigs() { if (_declinedOnce || HideOutdatedConfigPrompt == null || !HideOutdatedConfigPrompt.Value || _declineOutdated == null) { return; } try { if (_hasOutdatedConfigs != null) { object value = _hasOutdatedConfigs.GetValue(null, null); if (value is bool && !(bool)value) { return; } } _declineOutdated.Invoke(null, null); _declinedOnce = true; Plugin.Log.LogInfo((object)"EpicLoot outdated config files were auto-declined (modpack configs unchanged)."); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Could not auto-decline EpicLoot outdated configs: " + ex.Message)); } } private static void PatchPrefixReturnFalse(Harmony harmony, Type type, string methodName, string prefixName) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(type, methodName, (Type[])null, (Type[])null); if (methodInfo == null) { Plugin.Log.LogWarning((object)("EpicLoot method " + methodName + " was not found for outdated config hide.")); } else { harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(OutdatedConfigHide), prefixName, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } } [BepInPlugin("com.cjayride.epiclootadjustments", "EpicLootAdjustments", "1.5.6")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { internal static ManualLogSource Log; public static bool IsInitialized; public void Awake() { //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_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown //IL_005e: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; SetFx.Bind(((BaseUnityPlugin)this).Config); DropThatAllowList.Bind(((BaseUnityPlugin)this).Config); ConfigButtonHide.Bind(((BaseUnityPlugin)this).Config); OutdatedConfigHide.Bind(((BaseUnityPlugin)this).Config); Harmony val = new Harmony("com.cjayride.epiclootadjustments"); val.PatchAll(); EpicLootPatches.TryPatch(val); SetFx.TryPatch(val); ConfigButtonHide.TryPatch(val); OutdatedConfigHide.TryPatch(val); IsInitialized = true; Log.LogInfo((object)("Ready. Mapped " + LootMappings.CreatureZones.Count + " creatures.")); } } [HarmonyPatch(typeof(ObjectDB), "Awake")] internal static class ObjectDBAwakePatch { private static void Postfix() { ItemTierIndex.Invalidate(); SetFx.OnEpicPrefabsReady(); } } [HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")] internal static class ObjectDBCopyPatch { private static void Postfix() { ItemTierIndex.Invalidate(); SetFx.OnEpicPrefabsReady(); } } [HarmonyPatch(typeof(CharacterDrop), "GenerateDropList")] public static class CharacterDropPatch { [HarmonyPostfix] [HarmonyPriority(0)] public static void Postfix(CharacterDrop __instance, ref List<KeyValuePair<GameObject, int>> __result) { if (__result == null || __result.Count == 0 || (Object)(object)__instance == (Object)null || !LootMappings.TryGetCreature(((Object)((Component)__instance).gameObject).name, out var creature, out var zone, out var tier)) { return; } for (int i = 0; i < __result.Count; i++) { GameObject key = __result[i].Key; if (!((Object)(object)key == (Object)null) && !DropThatAllowList.IsAllowed(creature, ((Object)key).name) && ItemTierIndex.ShouldRemove(((Object)key).name, tier)) { Plugin.Log.LogInfo((object)(creature + " (" + zone + ") blocked " + LootMappings.Clean(((Object)key).name))); __result[i] = new KeyValuePair<GameObject, int>(key, 0); } } } } internal static class EpicLootPatches { private static string _creature; private static string _zone; private static int _maxTier; public static void TryPatch(Harmony harmony) { //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Expected O, but got Unknown //IL_010b: Expected O, but got Unknown //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Expected O, but got Unknown Type type = AccessTools.TypeByName("EpicLoot.LootRoller"); Type type2 = AccessTools.TypeByName("EpicLoot.GatedItemType.GatedItemTypeHelper"); if (type == null || type2 == null) { Plugin.Log.LogInfo((object)"EpicLoot is not loaded. Ordinary creature drops are still filtered."); return; } MethodInfo methodInfo = AccessTools.Method(type, "SpawnNormalItem", (Type[])null, (Type[])null); MethodInfo methodInfo2 = null; foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(type2)) { if (!(declaredMethod.Name != "GetGatedItemNameFromItemOrType") && !(declaredMethod.ReturnType != typeof(string)) && declaredMethod.GetParameters().Length == 2) { methodInfo2 = declaredMethod; break; } } if (methodInfo == null || methodInfo2 == null) { Plugin.Log.LogWarning((object)"EpicLoot is loaded, but its loot methods were not found. Magic drops will not be filtered."); return; } harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(EpicLootPatches), "BeginDrop", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(EpicLootPatches), "EndDrop", (Type[])null), (HarmonyMethod)null); harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(EpicLootPatches), "FilterGatedItem", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Plugin.Log.LogInfo((object)"EpicLoot over-tier gear will be removed. Drops are not rewritten."); } public static void BeginDrop(string objectName) { _creature = null; if (!LootMappings.TryGetCreature(objectName, out _creature, out _zone, out _maxTier)) { _creature = null; } } public static Exception EndDrop() { _creature = null; return null; } public static void FilterGatedItem(ref string __result) { if (string.IsNullOrEmpty(_creature) || string.IsNullOrEmpty(__result)) { return; } try { if (ItemTierIndex.ShouldRemove(__result, _maxTier)) { Plugin.Log.LogInfo((object)(_creature + " (" + _zone + ") blocked " + __result)); __result = ""; } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Failed to filter " + __result + " from " + _creature + ": " + ex.Message)); } } } public static class SetFx { private static readonly HashSet<int> Touched = new HashSet<int>(); private static readonly HashSet<string> AssetNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private static readonly string[] NameHints = new string[33] { "IceSpikes", "Berserker", "Bulwark", "Undying", "MagicShield", "DodgeBuff", "sfx_berserker", "sfx_bulwark", "sfx_undying", "sfx_offset", "fenring_icenova", "FrostNova", "FrostAOE", "Earthshaker", "Firebrand", "Artillery", "Assassin", "Hexen", "Huldu", "SpiritAnimal", "ShieldThrow", "Kinetic", "Overwhelming", "Jotunn", "Gullveig", "EitrInfusion", "Quarry", "HelHarvest", "PiercingBolt", "ConjuredArrow", "Frostwalker", "LifeSiphon", "NineSteps" }; public static ConfigEntry<float> Volume; public static ConfigEntry<bool> DisableSmoke; public static ConfigEntry<bool> ReduceParticles; public static ConfigEntry<bool> DisableVisuals; public static void Bind(ConfigFile config) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown Volume = config.Bind<float>("Set Abilities", "Volume", 0.35f, new ConfigDescription("Volume scale for EpicLoot legendary set abilities (Ragnar frost cone, Berserker, Bulwark, Undying, and newer set abilities). 1 is the original volume.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); DisableSmoke = config.Bind<bool>("Set Abilities", "DisableSmokeEffects", true, "Disable smoke, mist, fog, dust, and steam particle systems on set-ability effects."); ReduceParticles = config.Bind<bool>("Set Abilities", "ReduceParticleEffects", true, "Lower particle counts on remaining set-ability visuals so they cost less FPS."); DisableVisuals = config.Bind<bool>("Set Abilities", "DisableVisualEffects", false, "Turn off all particle, trail, and light visuals on set-ability effects. Sound is still scaled by Volume."); } public static void TryPatch(Harmony harmony) { PatchIfPresent(harmony, "EpicLoot.EpicLoot", "LoadAssets", "OnEpicPrefabsReady"); PatchIfPresent(harmony, "EpicLoot.EpicLoot", "ResolveAudioMixerMocks", "OnEpicPrefabsReady"); PatchIfPresent(harmony, "EpicLoot.MagicItemEffects.FrostAOE", "HookUpIceSpikesAudio", "OnEpicPrefabsReady"); PatchIfPresent(harmony, "EpicLoot.src.Magic.MagicItemEffects.Helpers.FrostNovaFx", "GetOrCreateTemplate", "OnNovaTemplate"); PatchIfPresent(harmony, "EpicLoot.src.Magic.MagicItemEffects.Helpers.FrostNovaFx", "GetOrBuildTemplate", "OnNovaTemplate"); Plugin.Log.LogInfo((object)("EpicLoot set-ability volume default is " + Volume.Value + ".")); } private static void PatchIfPresent(Harmony harmony, string typeName, string methodName, string postfix) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown MethodInfo methodInfo = FindMethod(AccessTools.TypeByName(typeName), methodName); if (!(methodInfo == null)) { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(SetFx), postfix, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } private static MethodInfo FindMethod(Type type, string methodName) { if (type == null) { return null; } MethodInfo[] methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name == methodName) { return methodInfo; } } return null; } public static void OnEpicPrefabsReady() { Type type = AccessTools.TypeByName("EpicLoot.EpicAssets"); if (type == null) { return; } FieldInfo[] fields = type.GetFields(BindingFlags.Static | BindingFlags.Public); foreach (FieldInfo fieldInfo in fields) { if (!(fieldInfo.FieldType != typeof(GameObject))) { object? value = fieldInfo.GetValue(null); GameObject val = (GameObject)((value is GameObject) ? value : null); if ((Object)(object)val != (Object)null && IsSetEffect(((Object)val).name)) { Apply(val, isPrefab: true); } } } } public static void OnNovaTemplate(GameObject __result) { Apply(__result, isPrefab: true); } public static void Apply(GameObject root, bool isPrefab) { if ((Object)(object)root == (Object)null || !IsSetEffect(((Object)root).name)) { return; } int instanceID = ((Object)root).GetInstanceID(); if (!Touched.Add(instanceID)) { return; } float num = ((Volume != null) ? Mathf.Clamp01(Volume.Value) : 0.35f); ZSFX[] componentsInChildren = root.GetComponentsInChildren<ZSFX>(true); for (int i = 0; i < componentsInChildren.Length; i++) { ScaleSound(componentsInChildren[i], num); } AudioSource[] componentsInChildren2 = root.GetComponentsInChildren<AudioSource>(true); for (int j = 0; j < componentsInChildren2.Length; j++) { if ((Object)(object)componentsInChildren2[j] != (Object)null) { AudioSource obj = componentsInChildren2[j]; obj.volume *= num; } } ParticleSystem[] componentsInChildren3 = root.GetComponentsInChildren<ParticleSystem>(true); for (int k = 0; k < componentsInChildren3.Length; k++) { TrimParticles(componentsInChildren3[k]); } if (DisableVisuals == null || !DisableVisuals.Value) { return; } TrailRenderer[] componentsInChildren4 = root.GetComponentsInChildren<TrailRenderer>(true); for (int l = 0; l < componentsInChildren4.Length; l++) { if ((Object)(object)componentsInChildren4[l] != (Object)null) { ((Renderer)componentsInChildren4[l]).enabled = false; } } Light[] componentsInChildren5 = root.GetComponentsInChildren<Light>(true); for (int m = 0; m < componentsInChildren5.Length; m++) { if ((Object)(object)componentsInChildren5[m] != (Object)null) { ((Behaviour)componentsInChildren5[m]).enabled = false; } } } private static void ScaleSound(ZSFX sound, float volume) { if (!((Object)(object)sound == (Object)null)) { sound.m_minVol *= volume; sound.m_maxVol *= volume; AudioSource component = ((Component)sound).GetComponent<AudioSource>(); if ((Object)(object)component != (Object)null) { component.volume *= volume; } } } private static void TrimParticles(ParticleSystem system) { //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)system == (Object)null) { return; } bool flag = ContainsAny(((Object)((Component)system).gameObject).name ?? "", "smoke", "mist", "fog", "dust", "steam", "puff", "cloud"); if ((DisableVisuals != null && DisableVisuals.Value) || (flag && DisableSmoke != null && DisableSmoke.Value)) { system.Stop(true, (ParticleSystemStopBehavior)0); EmissionModule emission = system.emission; ((EmissionModule)(ref emission)).enabled = false; ((Component)system).gameObject.SetActive(false); } else if (ReduceParticles != null && ReduceParticles.Value) { MainModule main = system.main; if (((MainModule)(ref main)).maxParticles > 24) { ((MainModule)(ref main)).maxParticles = 24; } EmissionModule emission2 = system.emission; MinMaxCurve rateOverTime = ((EmissionModule)(ref emission2)).rateOverTime; if (((MinMaxCurve)(ref rateOverTime)).constant > 8f) { ((EmissionModule)(ref emission2)).rateOverTime = MinMaxCurve.op_Implicit(8f); } } } public static bool IsSetEffect(string name) { name = LootMappings.Clean(name); if (string.IsNullOrEmpty(name)) { return false; } if (AssetNames.Contains(name)) { return true; } return MatchesHint(name); } private static bool MatchesHint(string name) { for (int i = 0; i < NameHints.Length; i++) { if (name.IndexOf(NameHints[i], StringComparison.OrdinalIgnoreCase) >= 0) { return true; } } return false; } private static bool ContainsAny(string name, params string[] parts) { for (int i = 0; i < parts.Length; i++) { if (name.IndexOf(parts[i], StringComparison.OrdinalIgnoreCase) >= 0) { return true; } } return false; } } [HarmonyPatch(typeof(EffectList), "Create")] internal static class SetFxEffectCreatePatch { private static void Postfix(GameObject[] __result) { if (__result == null || SetFx.Volume == null) { return; } foreach (GameObject val in __result) { if ((Object)(object)val != (Object)null && SetFx.IsSetEffect(((Object)val).name)) { SetFx.Apply(val, isPrefab: false); } } } } [HarmonyPatch(typeof(ZSFX), "Play")] internal static class SetFxZsfxPatch { private static void Prefix(ZSFX __instance) { if ((Object)(object)__instance == (Object)null || SetFx.Volume == null) { return; } Transform val = ((Component)__instance).transform; while ((Object)(object)val != (Object)null) { if (SetFx.IsSetEffect(((Object)val).name)) { SetFx.Apply(((Component)val).gameObject, isPrefab: false); break; } val = val.parent; } } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }