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 Unofficial EpicLoot BountyAdditions v1.3.0
plugins/UnofficialEpicLootBountyAdditions/UnofficialEpicLootBountyAdditions.dll
Decompiled 5 days agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using EpicLoot; using EpicLoot.Adventure; using EpicLoot.Adventure.Feature; using EpicLoot.Biomes; using HarmonyLib; using Jotunn.Managers; using Jotunn.Utils; 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("UnofficialEpicLootBountyAdditions")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.3.0.0")] [assembly: AssemblyInformationalVersion("1.3.0")] [assembly: AssemblyProduct("UnofficialEpicLootBountyAdditions")] [assembly: AssemblyTitle("UnofficialEpicLootBountyAdditions")] [assembly: AssemblyVersion("1.3.0.0")] [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 VanillaBounties { [BepInPlugin("vapok.mods.unofficialepiclootbountyadditions", "Unofficial EpicLoot BountyAdditions", "1.3.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] [SynchronizationMode(/*Could not decode attribute arguments.*/)] public sealed class VanillaBountiesPlugin : BaseUnityPlugin { public const string PluginId = "vapok.mods.unofficialepiclootbountyadditions"; public const string PluginName = "Unofficial EpicLoot BountyAdditions"; public const string PluginVersion = "1.3.0"; private Harmony _harmony; internal static ConfigEntry<int> VanillaBossDropMultiplier { get; private set; } internal static ConfigEntry<bool> GuaranteeEpicLootItem { get; private set; } internal static ManualLogSource LogSource { get; private set; } private void Awake() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Expected O, but got Unknown //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Expected O, but got Unknown LogSource = ((BaseUnityPlugin)this).Logger; ConfigurationManagerAttributes val = new ConfigurationManagerAttributes { IsAdminOnly = true }; VanillaBossDropMultiplier = ((BaseUnityPlugin)this).Config.Bind<int>("Boss Bounty Rewards", "Vanilla Drop Multiplier", 2, new ConfigDescription("Total multiplier for every vanilla drop from a bounty boss, including trophies, boss keys and Wishbones.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10), new object[1] { val })); GuaranteeEpicLootItem = ((BaseUnityPlugin)this).Config.Bind<bool>("Boss Bounty Rewards", "Guarantee Epic Loot Item", true, new ConfigDescription("Guarantees that the first eligible Epic Loot gear result from a bounty boss remains an enchanted item instead of being converted to materials, a shard or an unidentified item. Does not add another loot-table roll.", (AcceptableValueBase)null, new object[1] { val })); _harmony = new Harmony("vapok.mods.unofficialepiclootbountyadditions"); _harmony.PatchAll(); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } internal static class BossBountyRewards { internal const string CompletionSentKey = "VanillaBounties.CompletionSent"; internal const string RewardContextKey = "VanillaBounties.BossRewardContext"; private const string BountyIdKey = "BountyID"; private const string BountyDataKey = "BountyData"; private const string MonsterIdKey = "MonsterID"; private const string IsAddKey = "IsAdd"; internal static bool IsBossBounty(Character character) { ZDO zdo; string monsterId; BountyInfo bounty; return TryGetBossBounty(character, out zdo, out monsterId, out bounty); } internal static bool TryGetBossBounty(Character character, out ZDO zdo, out string monsterId, out BountyInfo bounty) { //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Expected O, but got Unknown zdo = null; monsterId = null; bounty = null; if ((Object)(object)character == (Object)null) { return false; } ZNetView component = ((Component)character).GetComponent<ZNetView>(); zdo = ((component != null) ? component.GetZDO() : null); if (zdo == null || string.IsNullOrWhiteSpace(zdo.GetString("BountyID", "")) || zdo.GetBool("IsAdd", false)) { return false; } monsterId = zdo.GetString("MonsterID", ""); object obj; if (!string.IsNullOrWhiteSpace(monsterId)) { GameObject prefab = PrefabManager.Instance.GetPrefab(monsterId); obj = ((prefab != null) ? prefab.GetComponent<Character>() : null); } else { obj = null; } Character val = (Character)obj; if ((Object)(object)val == (Object)null || !val.IsBoss()) { return false; } string text = zdo.GetString("BountyData", ""); if (!string.IsNullOrWhiteSpace(text)) { try { bounty = BountyInfo.FromPackage(new ZPackage(text)); } catch (Exception ex) { VanillaBountiesPlugin.LogSource.LogWarning((object)("Could not read bounty data for " + monsterId + ": " + ex.Message)); } } return true; } internal static bool IsProtectedBossDrop(GameObject prefab) { if ((Object)(object)prefab == (Object)null) { return true; } return false; } } internal static class BossBountyEpicLootReward { [ThreadStatic] private static bool _guaranteedItemPending; internal static void Begin(bool isBossBounty) { _guaranteedItemPending = isBossBounty && VanillaBountiesPlugin.GuaranteeEpicLootItem.Value; } internal static void End() { _guaranteedItemPending = false; } internal static bool TryConsumeFor(LootDrop lootDrop, bool isShardDrop) { if (!_guaranteedItemPending || isShardDrop || lootDrop == null || string.IsNullOrWhiteSpace(lootDrop.Item) || (Object)(object)ObjectDB.instance == (Object)null) { return false; } GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(lootDrop.Item); ItemDrop val = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null); if ((Object)(object)val == (Object)null || !EpicLoot.IsAllowedMagicItemType(val.m_itemData)) { return false; } _guaranteedItemPending = false; VanillaBountiesPlugin.LogSource.LogInfo((object)("Guaranteed bounty-boss Epic Loot item from resolved entry " + lootDrop.Item + ".")); return true; } } [HarmonyPatch(typeof(LootRoller), "SelectDropType")] internal static class BossBountyEpicLootCategoryPatch { private static bool Prefix(LootDrop lootDrop, bool isShardDrop, ref LootDropType __result) { if (!BossBountyEpicLootReward.TryConsumeFor(lootDrop, isShardDrop)) { return true; } __result = (LootDropType)0; return false; } } [HarmonyPatch(typeof(CharacterDrop), "OnDeath")] [HarmonyAfter(new string[] { "randyknapp.mods.epicloot" })] internal static class BossBountyInstantRewardContextPatch { private static void Prefix(CharacterDrop __instance) { BossBountyEpicLootReward.Begin(BossBountyRewards.IsBossBounty(((Component)__instance).GetComponent<Character>())); } private static void Postfix() { BossBountyEpicLootReward.End(); } private static Exception Finalizer(Exception __exception) { BossBountyEpicLootReward.End(); return __exception; } } [HarmonyPatch(typeof(Ragdoll), "Setup")] [HarmonyAfter(new string[] { "randyknapp.mods.epicloot" })] internal static class BossBountyRagdollMarkerPatch { private static void Postfix(Ragdoll __instance, CharacterDrop characterDrop) { if (!((Object)(object)characterDrop != (Object)null) || !BossBountyRewards.IsBossBounty(((Component)characterDrop).GetComponent<Character>())) { return; } ZNetView component = ((Component)__instance).GetComponent<ZNetView>(); if (component != null) { ZDO zDO = component.GetZDO(); if (zDO != null) { zDO.Set("VanillaBounties.BossRewardContext", true); } } } } [HarmonyPatch(typeof(Ragdoll), "SpawnLoot")] [HarmonyAfter(new string[] { "randyknapp.mods.epicloot" })] internal static class BossBountyRagdollRewardContextPatch { private static void Prefix(Ragdoll __instance) { ZNetView component = ((Component)__instance).GetComponent<ZNetView>(); ZDO val = ((component != null) ? component.GetZDO() : null); BossBountyEpicLootReward.Begin(val != null && val.GetBool("VanillaBounties.BossRewardContext", false)); } private static void Postfix() { BossBountyEpicLootReward.End(); } private static Exception Finalizer(Exception __exception) { BossBountyEpicLootReward.End(); return __exception; } } [HarmonyPatch(typeof(CharacterDrop), "GenerateDropList")] [HarmonyAfter(new string[] { "randyknapp.mods.epicloot" })] internal static class BossBountyVanillaDropsPatch { private static void Postfix(CharacterDrop __instance, ref List<KeyValuePair<GameObject, int>> __result) { int value = VanillaBountiesPlugin.VanillaBossDropMultiplier.Value; Character component = ((Component)__instance).GetComponent<Character>(); if (value <= 1 || __result == null || !BossBountyRewards.IsBossBounty(component)) { return; } for (int i = 0; i < __result.Count; i++) { KeyValuePair<GameObject, int> keyValuePair = __result[i]; if (!BossBountyRewards.IsProtectedBossDrop(keyValuePair.Key)) { int value2 = ((keyValuePair.Value > int.MaxValue / value) ? int.MaxValue : (keyValuePair.Value * value)); __result[i] = new KeyValuePair<GameObject, int>(keyValuePair.Key, value2); } } VanillaBountiesPlugin.LogSource.LogInfo((object)$"Applied {value}x vanilla material drops to bounty boss {((Object)component).name}."); } } [HarmonyPatch(typeof(CharacterDrop), "OnDeath")] [HarmonyBefore(new string[] { "randyknapp.mods.epicloot" })] internal static class BossBountyCompletionPatch { private static void Postfix(CharacterDrop __instance) { Character component = ((Component)__instance).GetComponent<Character>(); if (!BossBountyRewards.TryGetBossBounty(component, out var zdo, out var monsterId, out var bounty) || bounty == null || zdo.GetBool("VanillaBounties.CompletionSent", false)) { return; } ZNetView component2 = ((Component)component).GetComponent<ZNetView>(); if ((Object)(object)component2 == (Object)null || !component2.IsOwner() || ZRoutedRpc.instance == null) { return; } zdo.Set("VanillaBounties.CompletionSent", true); ReportSlain(bounty, monsterId, isAdd: false); int num = 0; foreach (BountyTargetInfo item in bounty.Adds ?? new List<BountyTargetInfo>()) { for (int i = 0; i < item.Count; i++) { ReportSlain(bounty, item.MonsterID, isAdd: true); num++; } } VanillaBountiesPlugin.LogSource.LogInfo((object)$"Reported bounty boss {monsterId} slain and credited {num} encounter add(s)."); } private static void ReportSlain(BountyInfo bounty, string monsterId, bool isAdd) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown ZPackage val = new ZPackage(); bounty.ToPackage(val); ZRoutedRpc.instance.InvokeRoutedRPC(0L, "SlayBountyTarget", new object[3] { val, monsterId, isAdd }); } } [HarmonyPatch(typeof(BountiesAdventureFeature), "GetAvailableBounties", new Type[] { typeof(int), typeof(bool), typeof(List<BountyFilterNote>) })] internal static class BountySelectionPatch { private const int BossRandomStream = 1; private static void Prefix(out List<BountyTargetConfig> __state) { __state = AdventureDataManager.Config?.Bounties?.Targets; if (__state != null) { AdventureDataManager.Config.Bounties.Targets = __state.Where((BountyTargetConfig target) => !IsBossTarget(target)).ToList(); } } private static void Postfix(int interval, bool removeAcceptedBounties, ref List<BountyInfo> __result, List<BountyTargetConfig> __state) { RestoreTargets(__state); if (__state == null || __result == null || (Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)ZoneSystem.instance == (Object)null) { return; } List<IGrouping<string, BountyTargetConfig>> list = (from target in __state.Where(IsEligibleDefeatedBoss) group target by target.TargetID into @group orderby @group.Min((BountyTargetConfig target) => BiomeDataManager.GetOrder(target.GetBiome())) select @group).ThenBy<IGrouping<string, BountyTargetConfig>, string>((IGrouping<string, BountyTargetConfig> group) => group.Key, StringComparer.Ordinal).ToList(); if (list.Count == 0) { return; } AdventureSaveData adventureSaveData = PlayerExtensions_Adventure.GetAdventureSaveData(Player.m_localPlayer); Random random = CreateBossRandom(interval); int num = PositiveModulo(interval, list.Count); for (int num2 = 0; num2 < list.Count; num2++) { List<BountyTargetConfig> list2 = list[(num + num2) % list.Count].ToList(); BountyInfo val = CreateBounty(list2[random.Next(list2.Count)], interval, random); if (!removeAcceptedBounties || !adventureSaveData.HasAcceptedBounty(val.Interval, val.ID)) { __result.Add(val); break; } } } private static Exception Finalizer(Exception __exception, List<BountyTargetConfig> __state) { RestoreTargets(__state); return __exception; } private static void RestoreTargets(List<BountyTargetConfig> targets) { if (targets != null && AdventureDataManager.Config?.Bounties != null) { AdventureDataManager.Config.Bounties.Targets = targets; } } private static bool IsBossTarget(BountyTargetConfig target) { if (target == null || string.IsNullOrWhiteSpace(target.TargetID)) { return false; } GameObject prefab = PrefabManager.Instance.GetPrefab(target.TargetID); Character val = ((prefab != null) ? prefab.GetComponent<Character>() : null); if ((Object)(object)val != (Object)null) { return val.IsBoss(); } return false; } private static bool IsEligibleDefeatedBoss(BountyTargetConfig target) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) if (!IsBossTarget(target)) { return false; } Biome biome = target.GetBiome(); if ((int)biome == 0) { return false; } IReadOnlyList<string> bossKeys = BiomeDataManager.GetBossKeys(biome); if (bossKeys.Count > 0) { return bossKeys.All((string key) => ZoneSystem.instance.GetGlobalKey(key)); } return false; } private static Random CreateBossRandom(int interval) { int num = (int)Player.m_localPlayer.GetPlayerID(); int refreshInterval = AdventureDataManager.Config.Bounties.RefreshInterval; return new Random(num + interval * 1000 + refreshInterval * 100 + 7919); } private static BountyInfo CreateBounty(BountyTargetConfig target, int interval, Random random) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: 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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Expected O, but got Unknown return new BountyInfo { Biome = target.GetBiome(), Interval = interval, PlayerID = Player.m_localPlayer.GetPlayerID(), Target = new BountyTargetInfo { MonsterID = target.TargetID, Level = GetTargetLevel(random, target.RewardGold > 0, isAdd: false), Count = 1 }, TargetName = BountiesAdventureFeature.GenerateTargetName(random), RewardIron = target.RewardIron, RewardGold = target.RewardGold, RewardCoins = target.RewardCoins, Adds = ((IEnumerable<BountyTargetAddConfig>)(target.Adds ?? new List<BountyTargetAddConfig>())).Select((Func<BountyTargetAddConfig, BountyTargetInfo>)((BountyTargetAddConfig add) => new BountyTargetInfo { MonsterID = add.ID, Count = add.Count, Level = GetTargetLevel(random, isGold: false, isAdd: true) })).ToList() }; } private static int GetTargetLevel(Random random, bool isGold, bool isAdd) { BountiesConfig bounties = AdventureDataManager.Config.Bounties; int minValue = (isAdd ? bounties.AddsMinLevel : (isGold ? bounties.GoldMinLevel : bounties.IronMinLevel)); int num = (isAdd ? bounties.AddsMaxLevel : (isGold ? bounties.GoldMaxLevel : bounties.IronMaxLevel)); return random.Next(minValue, num + 1); } private static int PositiveModulo(int value, int divisor) { int num = value % divisor; if (num >= 0) { return num; } return num + divisor; } } }