using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using EpicLoot.Adventure; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")] [assembly: AssemblyCompany("MGDev.EpicLootExtraSettings")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("MGDev.EpicLootExtraSettings")] [assembly: AssemblyTitle("MGDev.EpicLootExtraSettings")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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 MGDev.EpicLootExtraSettings { [BepInPlugin("mgdev.epiclootextrasettings", "EpicLoot Extra Settings", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class EpicLootConfigAdditionsPlugin : BaseUnityPlugin { public const string PluginGuid = "mgdev.epiclootextrasettings"; public const string PluginName = "EpicLoot Extra Settings"; public const string PluginVersion = "1.0.0"; private static EpicLootConfigAdditionsPlugin _instance; private Harmony _harmony; internal static ConfigEntry BountyRefreshDays; internal static ConfigEntry TreasureMapRefreshDays; internal static ConfigEntry GambleRefreshDays; internal static ConfigEntry SecretStashRefreshDays; internal static ConfigEntry IronMinLevel; internal static ConfigEntry IronMaxLevel; internal static ConfigEntry IronHealthMultiplier; internal static ConfigEntry GoldMinLevel; internal static ConfigEntry GoldMaxLevel; internal static ConfigEntry GoldHealthMultiplier; internal static ConfigEntry AddsMinLevel; internal static ConfigEntry AddsMaxLevel; internal static ConfigEntry AddsHealthMultiplier; internal static ConfigEntry BountyCoinRewardMultiplier; internal static ConfigEntry BountyIronTokenRewardMultiplier; internal static ConfigEntry BountyGoldTokenRewardMultiplier; internal static ConfigEntry CoinGambleCount; internal static ConfigEntry ForestTokenGambleCount; internal static ConfigEntry IronBountyTokenGambleCount; internal static ConfigEntry GoldBountyTokenGambleCount; internal static ConfigEntry ForestTokenCoinCostMultiplier; internal static ConfigEntry ForestTokenCostMin; internal static ConfigEntry ForestTokenCostMax; internal static ConfigEntry IronBountyCoinCostMultiplier; internal static ConfigEntry IronBountyTokenCost; internal static ConfigEntry GoldBountyCoinCostMultiplier; internal static ConfigEntry GoldBountyTokenCost; internal static ConfigEntry GambleRarityChances; internal static ConfigEntry SecretStashMagicRolls; internal static ConfigEntry SecretStashRareRolls; internal static ConfigEntry SecretStashEpicRolls; internal static ConfigEntry SecretStashLegendaryRolls; internal static ConfigEntry SecretStashMythicRolls; internal static ConfigEntry SecretStashRandomItemCount; internal static ConfigEntry TreasureMapCircleRadius; internal static readonly List BiomeTreasureSettings = new List(); internal static ConfigEntry FulingCoinDropScale; internal static ConfigEntry OnlyUseExploredAdventureLocations; internal static ConfigEntry FallbackToUnexploredLocations; internal static ConfigEntry ExploredOnlyFallbackAfterRejectedLocations; private static int _unexploredLocationsRejected; private void Awake() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown _instance = this; BindConfig(); _harmony = new Harmony("mgdev.epiclootextrasettings"); _harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"EpicLoot Extra Settings 1.0.0 loaded."); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } private void BindConfig() { BountyRefreshDays = ((BaseUnityPlugin)this).Config.Bind("1 - Refresh Timers", "BountyRefreshDays", 7, "Controls how often Haldor gets a fresh bounty list.\n1 means every in-game day."); TreasureMapRefreshDays = ((BaseUnityPlugin)this).Config.Bind("1 - Refresh Timers", "TreasureMapRefreshDays", 7, "Controls how often Haldor gets a fresh treasure map list.\n1 means every in-game day."); GambleRefreshDays = ((BaseUnityPlugin)this).Config.Bind("1 - Refresh Timers", "GambleRefreshDays", 1, "Controls how often the gamble shop gets new offers.\n1 means every in-game day."); SecretStashRefreshDays = ((BaseUnityPlugin)this).Config.Bind("1 - Refresh Timers", "SecretStashRefreshDays", 1, "Controls how often the secret stash gets new offers.\n1 means every in-game day."); IronMinLevel = ((BaseUnityPlugin)this).Config.Bind("2 - Bounty Target Scaling", "IronTokenBountyMinLevel", 2, "Lowest star level for bounties that reward Iron Bounty Tokens only.\nThis affects the spawned target, not the reward amount."); IronMaxLevel = ((BaseUnityPlugin)this).Config.Bind("2 - Bounty Target Scaling", "IronTokenBountyMaxLevel", 3, "Highest star level for bounties that reward Iron Bounty Tokens only.\nUse the same value as the minimum if you want fixed levels."); IronHealthMultiplier = ((BaseUnityPlugin)this).Config.Bind("2 - Bounty Target Scaling", "IronTokenBountyHealthMultiplier", 2f, "Health multiplier for bounties that reward Iron Bounty Tokens only.\nExample: 2 means double health."); GoldMinLevel = ((BaseUnityPlugin)this).Config.Bind("2 - Bounty Target Scaling", "GoldTokenBountyMinLevel", 3, "Lowest star level for bounties that reward Gold Bounty Tokens.\nIf a bounty rewards both iron and gold tokens, this gold-token scaling is used."); GoldMaxLevel = ((BaseUnityPlugin)this).Config.Bind("2 - Bounty Target Scaling", "GoldTokenBountyMaxLevel", 3, "Highest star level for bounties that reward Gold Bounty Tokens.\nUse the same value as the minimum if you want fixed levels."); GoldHealthMultiplier = ((BaseUnityPlugin)this).Config.Bind("2 - Bounty Target Scaling", "GoldTokenBountyHealthMultiplier", 3f, "Health multiplier for bounties that reward Gold Bounty Tokens.\nExample: 3 means triple health."); AddsMinLevel = ((BaseUnityPlugin)this).Config.Bind("2 - Bounty Target Scaling", "BountyMinionMinLevel", 1, "Lowest star level for minions that may spawn around the bounty target."); AddsMaxLevel = ((BaseUnityPlugin)this).Config.Bind("2 - Bounty Target Scaling", "BountyMinionMaxLevel", 2, "Highest star level for minions that may spawn around the bounty target."); AddsHealthMultiplier = ((BaseUnityPlugin)this).Config.Bind("2 - Bounty Target Scaling", "BountyMinionHealthMultiplier", 1.5f, "Health multiplier for minions that may spawn around the bounty target.\nExample: 1.5 means 50 percent more health."); BountyCoinRewardMultiplier = ((BaseUnityPlugin)this).Config.Bind("2.1 - Bounty Rewards", "CoinRewardMultiplier", 1f, "Multiplies the coin reward shown on bounties.\nExample: 2 doubles coin rewards."); BountyIronTokenRewardMultiplier = ((BaseUnityPlugin)this).Config.Bind("2.1 - Bounty Rewards", "IronBountyTokenRewardMultiplier", 1f, "Multiplies Iron Bounty Token rewards shown on bounties.\nExample: 0.5 cuts them in half."); BountyGoldTokenRewardMultiplier = ((BaseUnityPlugin)this).Config.Bind("2.1 - Bounty Rewards", "GoldBountyTokenRewardMultiplier", 1f, "Multiplies Gold Bounty Token rewards shown on bounties.\nExample: 2 doubles them."); CoinGambleCount = ((BaseUnityPlugin)this).Config.Bind("3 - Gambling", "CoinGambleItemCount", 4, "How many gamble offers appear with a coin-only price."); ForestTokenGambleCount = ((BaseUnityPlugin)this).Config.Bind("3 - Gambling", "ForestTokenGambleItemCount", 2, "How many gamble offers appear with a coin plus Forest Token price."); IronBountyTokenGambleCount = ((BaseUnityPlugin)this).Config.Bind("3 - Gambling", "IronBountyTokenGambleItemCount", 2, "How many gamble offers appear with a coin plus Iron Bounty Token price."); GoldBountyTokenGambleCount = ((BaseUnityPlugin)this).Config.Bind("3 - Gambling", "GoldBountyTokenGambleItemCount", 1, "How many gamble offers appear with a coin plus Gold Bounty Token price."); ForestTokenCoinCostMultiplier = ((BaseUnityPlugin)this).Config.Bind("3 - Gambling", "ForestTokenCoinCostMultiplier", 1.5f, "Changes the coin part of Forest Token gamble prices.\nExample: 2 makes the coin price twice as high."); ForestTokenCostMin = ((BaseUnityPlugin)this).Config.Bind("3 - Gambling", "ForestTokenCostMin", 5, "Lowest Forest Token cost for gamble offers that use Forest Tokens."); ForestTokenCostMax = ((BaseUnityPlugin)this).Config.Bind("3 - Gambling", "ForestTokenCostMax", 9, "Highest Forest Token cost for gamble offers that use Forest Tokens."); IronBountyCoinCostMultiplier = ((BaseUnityPlugin)this).Config.Bind("3 - Gambling", "IronBountyCoinCostMultiplier", 1.5f, "Changes the coin part of Iron Bounty Token gamble prices.\nExample: 0.5 makes the coin price half as high."); IronBountyTokenCost = ((BaseUnityPlugin)this).Config.Bind("3 - Gambling", "IronBountyTokenCost", 5, "Iron Bounty Token cost for gamble offers that use Iron Bounty Tokens."); GoldBountyCoinCostMultiplier = ((BaseUnityPlugin)this).Config.Bind("3 - Gambling", "GoldBountyCoinCostMultiplier", 1.5f, "Changes the coin part of Gold Bounty Token gamble prices.\nExample: 2 makes the coin price twice as high."); GoldBountyTokenCost = ((BaseUnityPlugin)this).Config.Bind("3 - Gambling", "GoldBountyTokenCost", 3, "Gold Bounty Token cost for gamble offers that use Gold Bounty Tokens."); GambleRarityChances = ((BaseUnityPlugin)this).Config.Bind("3 - Gambling", "RarityChances", "10,68,15,4,2,1", "Controls how likely each gamble rarity is, from lowest rarity to highest rarity.\nBigger numbers appear more often. Keep the same comma format as the default value."); SecretStashMagicRolls = ((BaseUnityPlugin)this).Config.Bind("4 - Secret Stash", "MagicMaterialOffers", 1, "How many magic-rarity material offers can appear in the secret stash after refresh."); SecretStashRareRolls = ((BaseUnityPlugin)this).Config.Bind("4 - Secret Stash", "RareMaterialOffers", 1, "How many rare-rarity material offers can appear in the secret stash after refresh."); SecretStashEpicRolls = ((BaseUnityPlugin)this).Config.Bind("4 - Secret Stash", "EpicMaterialOffers", 1, "How many epic-rarity material offers can appear in the secret stash after refresh."); SecretStashLegendaryRolls = ((BaseUnityPlugin)this).Config.Bind("4 - Secret Stash", "LegendaryMaterialOffers", 1, "How many legendary-rarity material offers can appear in the secret stash after refresh."); SecretStashMythicRolls = ((BaseUnityPlugin)this).Config.Bind("4 - Secret Stash", "MythicMaterialOffers", 1, "How many mythic-rarity material offers can appear in the secret stash after refresh."); SecretStashRandomItemCount = ((BaseUnityPlugin)this).Config.Bind("4 - Secret Stash", "RandomItemCount", 0, "Adds extra known non-material items to the secret stash."); TreasureMapCircleRadius = ((BaseUnityPlugin)this).Config.Bind("5 - Treasure Maps", "MinimapCircleRadius", 45f, "Size of the search circle shown after using a treasure map.\nSmaller is more precise; larger makes the treasure harder to pinpoint."); BindBiomeTreasureSettings(); FulingCoinDropScale = ((BaseUnityPlugin)this).Config.Bind("6 - Drops", "FulingCoinDropScale", 1f, "Changes coin drops affected by Epic Loot, mainly Fuling/goblin coin drops.\nExample: 2 doubles those coin drops."); OnlyUseExploredAdventureLocations = ((BaseUnityPlugin)this).Config.Bind("7 - Adventure Locations", "OnlyUseExploredAdventureLocations", false, "If true, new bounties and treasure maps try to use explored map areas only.\nIf your explored map is too small, finding a valid spot may take longer."); FallbackToUnexploredLocations = ((BaseUnityPlugin)this).Config.Bind("7 - Adventure Locations", "FallbackToUnexploredLocations", true, "If explored-only search keeps failing, allow an unexplored valid spot instead.\nThis prevents bounties or maps from getting stuck."); ExploredOnlyFallbackAfterRejectedLocations = ((BaseUnityPlugin)this).Config.Bind("7 - Adventure Locations", "FallbackAfterRejectedLocations", 80, "How many valid-but-unexplored spots can be rejected before fallback starts.\nHigher means stricter explored-only behavior."); } private void BindBiomeTreasureSettings() { BiomeTreasureSettings.Clear(); BiomeTreasureSettings.Add(new BiomeTreasureMapSettings(((BaseUnityPlugin)this).Config, "5 - Treasure Maps", "Meadows", (Biome)1, 100, "5,0,0,0")); BiomeTreasureSettings.Add(new BiomeTreasureMapSettings(((BaseUnityPlugin)this).Config, "5 - Treasure Maps", "BlackForest", (Biome)8, 200, "10,0,0,0")); BiomeTreasureSettings.Add(new BiomeTreasureMapSettings(((BaseUnityPlugin)this).Config, "5 - Treasure Maps", "Ocean", (Biome)256, -1, "0,0,0,0")); BiomeTreasureSettings.Add(new BiomeTreasureMapSettings(((BaseUnityPlugin)this).Config, "5 - Treasure Maps", "Swamp", (Biome)2, 300, "15,0,0,0")); BiomeTreasureSettings.Add(new BiomeTreasureMapSettings(((BaseUnityPlugin)this).Config, "5 - Treasure Maps", "Mountain", (Biome)4, 400, "20,0,0,0")); BiomeTreasureSettings.Add(new BiomeTreasureMapSettings(((BaseUnityPlugin)this).Config, "5 - Treasure Maps", "Plains", (Biome)16, 500, "25,0,0,0")); BiomeTreasureSettings.Add(new BiomeTreasureMapSettings(((BaseUnityPlugin)this).Config, "5 - Treasure Maps", "Mistlands", (Biome)512, 600, "30,0,0,0")); BiomeTreasureSettings.Add(new BiomeTreasureMapSettings(((BaseUnityPlugin)this).Config, "5 - Treasure Maps", "Ashlands", (Biome)32, 700, "35,0,0,0")); } internal static void ApplyOverrides() { AdventureDataConfig config = AdventureDataManager.Config; if (config != null) { config.Bounties.RefreshInterval = Math.Max(1, BountyRefreshDays.Value); config.TreasureMap.RefreshInterval = Math.Max(1, TreasureMapRefreshDays.Value); config.Gamble.RefreshInterval = Math.Max(1, GambleRefreshDays.Value); config.SecretStash.RefreshInterval = Math.Max(1, SecretStashRefreshDays.Value); config.Bounties.IronMinLevel = Math.Max(1, IronMinLevel.Value); config.Bounties.IronMaxLevel = Math.Max(config.Bounties.IronMinLevel, IronMaxLevel.Value); config.Bounties.IronHealthMultiplier = Math.Max(0.01f, IronHealthMultiplier.Value); config.Bounties.GoldMinLevel = Math.Max(1, GoldMinLevel.Value); config.Bounties.GoldMaxLevel = Math.Max(config.Bounties.GoldMinLevel, GoldMaxLevel.Value); config.Bounties.GoldHealthMultiplier = Math.Max(0.01f, GoldHealthMultiplier.Value); config.Bounties.AddsMinLevel = Math.Max(1, AddsMinLevel.Value); config.Bounties.AddsMaxLevel = Math.Max(config.Bounties.AddsMinLevel, AddsMaxLevel.Value); config.Bounties.AddsHealthMultiplier = Math.Max(0.01f, AddsHealthMultiplier.Value); ApplyBountyRewardMultipliers(config); config.Gamble.GamblesCount = Math.Max(0, CoinGambleCount.Value); config.Gamble.ForestTokenGamblesCount = Math.Max(0, ForestTokenGambleCount.Value); config.Gamble.IronBountyGamblesCount = Math.Max(0, IronBountyTokenGambleCount.Value); config.Gamble.GoldBountyGamblesCount = Math.Max(0, GoldBountyTokenGambleCount.Value); config.Gamble.ForestTokenGambleCoinsCost = Math.Max(0f, ForestTokenCoinCostMultiplier.Value); config.Gamble.ForestTokenGambleCostMin = Math.Max(0, ForestTokenCostMin.Value); config.Gamble.ForestTokenGambleCostMax = Math.Max(config.Gamble.ForestTokenGambleCostMin, ForestTokenCostMax.Value); config.Gamble.IronBountyGambleCoinsCost = Math.Max(0f, IronBountyCoinCostMultiplier.Value); config.Gamble.IronBountyGambleCost = Math.Max(0, IronBountyTokenCost.Value); config.Gamble.GoldBountyGambleCoinsCost = Math.Max(0f, GoldBountyCoinCostMultiplier.Value); config.Gamble.GoldBountyGambleCost = Math.Max(0, GoldBountyTokenCost.Value); ApplyGambleRarityChances(config); config.SecretStash.RollsPerRarity = new List { Math.Max(0, SecretStashMagicRolls.Value), Math.Max(0, SecretStashRareRolls.Value), Math.Max(0, SecretStashEpicRolls.Value), Math.Max(0, SecretStashLegendaryRolls.Value), Math.Max(0, SecretStashMythicRolls.Value) }; config.SecretStash.RandomItemsCount = Math.Max(0, SecretStashRandomItemCount.Value); config.TreasureMap.MinimapAreaRadius = Math.Max(1f, TreasureMapCircleRadius.Value); ApplyBiomeTreasureSettings(config); config.FulingCoinDropScale = Math.Max(0f, FulingCoinDropScale.Value); } } private static void ApplyBountyRewardMultipliers(AdventureDataConfig config) { float num = Math.Max(0f, BountyCoinRewardMultiplier.Value); float num2 = Math.Max(0f, BountyIronTokenRewardMultiplier.Value); float num3 = Math.Max(0f, BountyGoldTokenRewardMultiplier.Value); foreach (BountyTargetConfig target in config.Bounties.Targets) { target.RewardCoins = Mathf.RoundToInt((float)target.RewardCoins * num); target.RewardIron = Mathf.RoundToInt((float)target.RewardIron * num2); target.RewardGold = Mathf.RoundToInt((float)target.RewardGold * num3); } } private static void ApplyGambleRarityChances(AdventureDataConfig config) { string[] array = GambleRarityChances.Value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); List list = new List(); string[] array2 = array; for (int i = 0; i < array2.Length; i++) { if (float.TryParse(array2[i].Trim(), out var result)) { list.Add(Math.Max(0f, result)); } } if (list.Count != 0) { config.Gamble.GambleRarityChance = list.ToArray(); } } private static void ApplyBiomeTreasureSettings(AdventureDataConfig config) { foreach (BiomeTreasureMapSettings settings in BiomeTreasureSettings) { TreasureMapBiomeInfoConfig val = config.TreasureMap.BiomeInfo.Find((TreasureMapBiomeInfoConfig x) => x.Biome == settings.Biome); if (val != null) { val.Cost = settings.Cost.Value; int[] array = ParseRewards(settings.Rewards.Value); val.ForestTokens = array[0]; val.IronTokens = array[1]; val.GoldTokens = array[2]; val.Coins = array[3]; } } config.TreasureMap.UpdateBiomeList(); } private static int[] ParseRewards(string value) { int[] array = new int[4]; string[] array2 = value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length && i < array2.Length; i++) { if (int.TryParse(array2[i].Trim(), out var result)) { array[i] = Math.Max(0, result); } } return array; } internal static bool IsExplored(Vector3 location) { //IL_0072: Unknown result type (might be due to invalid IL or missing references) if (!OnlyUseExploredAdventureLocations.Value) { return true; } Minimap instance = Minimap.instance; if ((Object)(object)instance == (Object)null) { return true; } MethodInfo methodInfo = AccessTools.Method(typeof(Minimap), "IsExplored", new Type[1] { typeof(Vector3) }, (Type[])null); if (methodInfo == null) { ((BaseUnityPlugin)_instance).Logger.LogWarning((object)"Minimap.IsExplored(Vector3) was not found; explored-only adventure locations were skipped."); return true; } try { if ((bool)methodInfo.Invoke(instance, new object[1] { location })) { _unexploredLocationsRejected = 0; return true; } _unexploredLocationsRejected++; if (FallbackToUnexploredLocations.Value && _unexploredLocationsRejected >= Math.Max(1, ExploredOnlyFallbackAfterRejectedLocations.Value)) { _unexploredLocationsRejected = 0; return true; } return false; } catch (Exception ex) { ((BaseUnityPlugin)_instance).Logger.LogWarning((object)("Could not check explored map data; explored-only adventure locations were skipped. " + ex.Message)); return true; } } } internal class BiomeTreasureMapSettings { public readonly Biome Biome; public readonly ConfigEntry Cost; public readonly ConfigEntry Rewards; public BiomeTreasureMapSettings(ConfigFile config, string section, string name, Biome biome, int cost, string rewards) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) Biome = biome; Cost = config.Bind(section, name + "MapCost", cost, "Coin price for buying this biome's treasure map.\n-1 makes that map unavailable."); Rewards = config.Bind(section, name + "ChestRewards", rewards, "Chest rewards in this order:\nForest Tokens, Iron Bounty Tokens, Gold Bounty Tokens, Coins."); } } [HarmonyPatch(typeof(AdventureDataManager), "Initialize")] internal static class AdventureDataManagerInitializePatch { private static void Postfix() { EpicLootConfigAdditionsPlugin.ApplyOverrides(); } } [HarmonyPatch(typeof(AdventureDataManager), "UpdateAventureData")] internal static class AdventureDataManagerUpdatePatch { private static void Postfix() { EpicLootConfigAdditionsPlugin.ApplyOverrides(); } } [HarmonyPatch] internal static class BountyLocationExploredPatch { private static MethodBase TargetMethod() { return AccessTools.Method(AccessTools.TypeByName("EpicLoot.Adventure.Feature.BountyLocationEarlyCache"), "IsSpawnLocationValid", (Type[])null, (Type[])null); } private static void Postfix(Vector3 location, ref bool __result) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) if (__result && !EpicLootConfigAdditionsPlugin.IsExplored(location)) { __result = false; } } } }