Decompiled source of EpicLootAdjustments v1.5.6

Cjayride.EpicLootAdjustments.dll

Decompiled 3 days ago
using 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)
		{
		}
	}
}